Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
acts_as_pasting
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
acts_as_pasting
Commits
896f6f72
Commit
896f6f72
authored
May 10, 2020
by
Ivan Lan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add pasting type logic
parent
6402d2ab
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
185 additions
and
167 deletions
+185
-167
1_create_acts_as_pasting_pastings.rb
db/migrate/1_create_acts_as_pasting_pastings.rb
+0
-1
pasted.rb
lib/acts_as_pasting/pasted.rb
+183
-166
pasting.rb
lib/acts_as_pasting/pasting.rb
+2
-0
No files found.
db/migrate/1_create_acts_as_pasting_pastings.rb
View file @
896f6f72
...
...
@@ -4,7 +4,6 @@ class CreateActsAsPastingPastings < ActiveRecord::Migration[5.2]
t
.
references
:pasteable
,
polymorphic:
true
,
index:
{
name:
'acts_as_pasting_pasteable'
}
t
.
references
:pasted
,
polymorphic:
true
,
index:
{
name:
'acts_as_pasting_pasted'
}
t
.
string
:type
,
index:
true
t
.
string
:pasting_type
t
.
timestamps
end
...
...
lib/acts_as_pasting/pasted.rb
View file @
896f6f72
module
ActsAsPasting
module
Pasted
extend
ActiveSupport
::
Concern
included
do
has_many
:pastings
,
as: :pasted
,
class_name:
'ActsAsPasting::Pasting'
# ary => [[klass, id], [klass, id]]
# ary => [obj, obj]
scope
:pasted_with_any
,
->
(
ary
)
{
ary
=
parsed_condition_ary
(
ary
)
ary
.
map
{
|
klass
,
id
|
joins
(
:pastings
).
where
(
'acts_as_pasting_pastings.pasteable_type = ? AND acts_as_pasting_pastings.pasteable_id = ?'
,
klass
.
constantize
.
base_class
.
name
,
id
)
}.
reduce
(
:or
)
&
.
distinct
||
self
.
none
}
scope
:pasted_with_all
,
->
(
ary
)
{
ary
=
parsed_condition_ary
(
ary
)
ids
=
ary
.
map
do
|
klass
,
id
|
joins
(
:pastings
).
where
(
pastings:
{
pasteable_type:
klass
.
constantize
.
base_class
.
name
,
pasteable_id:
id
}).
pluck
(
:id
)
end
.
reduce
(
:&
)
where
(
id:
ids
)
}
after_create
:save_paste_list
def
paste_list
pastings
.
reload
.
map
(
&
:pasteable
)
end
def
paste_list_for
klass_name
klass_name
.
constantize
.
where
(
id:
pastings
.
where
(
pasteable_type:
klass_name
.
constantize
.
base_class
.
name
).
pluck
(
:pasteable_id
)
)
end
def
paste_list_names
paste_list
.
map
(
&
:name
)
end
module
Pasted
extend
ActiveSupport
::
Concern
# 带 prefix 的 pasted_with,独立于不带 prefix 的之外
included
do
has_many
:pastings
,
as: :pasted
# ary => [[klass, id], [klass, id]]
# ary => [obj, obj]
scope
:pasted_with_any
,
->
(
ary
,
prefix:
''
)
{
ary
=
parsed_condition_ary
(
ary
)
ids
=
ary
.
map
do
|
klass
,
id
|
joins
(
:pastings
).
where
(
pastings:
{
pasteable_type:
klass
.
constantize
.
base_class
.
name
,
pasteable_id:
id
,
type:
prefix
}).
pluck
(
:id
)
end
.
reduce
(
:|
)
where
(
id:
ids
)
}
scope
:pasted_with_all
,
->
(
ary
,
prefix:
''
)
{
ary
=
parsed_condition_ary
(
ary
)
ids
=
ary
.
map
do
|
klass
,
id
|
joins
(
:pastings
).
where
(
pastings:
{
pasteable_type:
klass
.
constantize
.
base_class
.
name
,
pasteable_id:
id
,
type:
prefix
}).
pluck
(
:id
)
end
.
reduce
(
:&
)
where
(
id:
ids
)
}
after_create
:save_paste_list
# 不包含 带 prefix 的 pasted_with
def
paste_list
pastings
.
where
(
type:
''
).
reload
.
map
(
&
:pasteable
).
uniq
end
def
paste_list_add
obj
pastings
.
create!
(
pasted:
self
,
pasteable:
obj
)
end
# def paste_list_for klass_name
# klass_name.constantize.where(
# id: pastings.where(pasteable_type: klass_name.constantize.base_class.name).pluck(:pasteable_id)
# )
# end
def
paste_list_remove
obj
pastings
.
where
(
pasted:
self
,
pasteable:
obj
).
destroy_all
end
# ary => [[klass, id], [klass, id]]
# ary => [obj, obj]
def
paste_list
=
ary
ary
=
self
.
class
.
parsed_condition_ary
(
ary
)
exist_ary
=
pastings
.
where
(
pasted:
self
).
pluck
(
:pasteable_type
,
:pasteable_id
)
add_ary
=
ary
-
exist_ary
remove_ary
=
exist_ary
-
ary
if
new_record?
@paste_list
=
ary
else
self
.
class
.
transaction
do
remove_ary
.
each
{
|
klass
,
id
|
pastings
.
where
(
pasted:
self
,
pasteable_type:
klass
,
pasteable_id:
id
).
destroy_all
}
add_ary
.
each
{
|
klass
,
id
|
pastings
.
create!
(
pasted:
self
,
pasteable_type:
klass
,
pasteable_id:
id
)
}
end
end
end
def
paste_list_names
paste_list
.
map
(
&
:name
)
end
def
method_missing
name
,
*
arg
,
&
block
klass_downcase
=
/^paste_(.+)_list$/
.
match
(
name
)
&
.
[
](
1
)
if
klass_downcase
downcase_all_combination
(
klass_downcase
).
each
do
|
str
|
return
paste_list_for
(
str
)
if
correct_class_name?
(
str
)
end
end
super
(
name
,
*
arg
,
&
block
)
end
def
paste_list_add
obj
pastings
.
where
(
type:
''
).
create!
(
pasted:
self
,
pasteable:
obj
)
end
private
def
paste_list_remove
obj
pastings
.
where
(
type:
''
).
where
(
pasted:
self
,
pasteable:
obj
).
destroy_all
end
def
save_paste_list
if
@paste_list
self
.
paste_list
=
@paste_list
# ary => [[klass, id], [klass, id]]
# ary => [obj, obj]
# 不包含 带 prefix 的 pasted_with
def
paste_list
=
ary
ary
=
self
.
class
.
parsed_condition_ary
(
ary
)
exist_ary
=
pastings
.
where
(
pasted:
self
).
pluck
(
:pasteable_type
,
:pasteable_id
)
add_ary
=
ary
-
exist_ary
remove_ary
=
exist_ary
-
ary
if
new_record?
@paste_list
=
ary
else
self
.
class
.
transaction
do
remove_ary
.
each
{
|
klass
,
id
|
pastings
.
where
(
type:
''
,
pasted:
self
,
pasteable_type:
klass
,
pasteable_id:
id
).
destroy_all
}
add_ary
.
each
{
|
klass
,
id
|
pastings
.
create!
(
type:
''
,
pasted:
self
,
pasteable_type:
klass
,
pasteable_id:
id
)
}
end
end
end
def
correct_class_name?
name
ActiveRecord
::
Base
===
name
.
safe_constantize
.
try
(
:new
)
# def method_missing name, *arg, &block
# klass_downcase = /^paste_(.+)_list$/.match(name)&.[](1)
# if klass_downcase
# downcase_all_combination(klass_downcase).each do |str|
# return paste_list_for(str) if correct_class_name?(str)
# end
# end
# super(name, *arg, &block)
# end
private
def
save_paste_list
if
@paste_list
self
.
paste_list
=
@paste_list
end
end
def
downcase_all_combination
str
downcase_all_combination_ary
(
str
).
reverse
.
map
{
|
x
|
(
String
===
x
?
x
:
x
.
flatten
.
join
).
classify
}
end
def
correct_class_name?
name
ActiveRecord
::
Base
===
name
.
safe_constantize
.
try
(
:new
)
end
def
downcase_all_combination_ary
str
items
=
String
===
str
?
str
.
split
(
'_'
)
:
str
return
items
if
items
.
length
==
1
l
=
downcase_all_combination_ary
(
items
[
1
..-
1
])
result
=
[]
l
.
each
do
|
i
|
result
.
push
(
items
[
0
,
1
]
<<
'/'
<<
i
)
result
.
push
(
items
[
0
,
1
]
<<
'_'
<<
i
)
end
result
end
def
downcase_all_combination
str
downcase_all_combination_ary
(
str
).
reverse
.
map
{
|
x
|
(
String
===
x
?
x
:
x
.
flatten
.
join
).
classify
}
end
module
ClassMethods
def
pasted_with
*
klasses
klasses
.
each
do
|
klass
|
downcase
=
klass
.
name
.
underscore
.
gsub
(
'/'
,
'_'
)
base_class_name
=
klass
.
base_class
.
name
class_eval
<<-
RUBY
,
__FILE__
,
__LINE__
+
1
after_create :save_paste_
#{
downcase
}
_list
def
downcase_all_combination_ary
str
items
=
String
===
str
?
str
.
split
(
'_'
)
:
str
return
items
if
items
.
length
==
1
l
=
downcase_all_combination_ary
(
items
[
1
..-
1
])
result
=
[]
l
.
each
do
|
i
|
result
.
push
(
items
[
0
,
1
]
<<
'/'
<<
i
)
result
.
push
(
items
[
0
,
1
]
<<
'_'
<<
i
)
end
result
end
end
def paste_
#{
downcase
}
_list
paste_list_for("
#{
klass
}
")
end
module
ClassMethods
def
pasted_with
*
klasses
,
prefix:
nil
klasses
.
each
do
|
klass
|
downcase
=
klass
.
name
.
underscore
.
gsub
(
'/'
,
'_'
)
downcase
=
"
#{
prefix
}#{
downcase
}
"
if
prefix
type_value
=
prefix
?
prefix
:
nil
base_class_name
=
klass
.
base_class
.
name
class_eval
<<-
RUBY
,
__FILE__
,
__LINE__
+
1
after_create :save_paste_
#{
downcase
}
_list
def paste_
#{
downcase
}
_list
#{
klass
}
.where(
id: pastings.where(type: "
#{
type_value
}
", pasteable_type:
#{
klass
}
.base_class.name).pluck(:pasteable_id)
)
end
def paste_
#{
downcase
}
_ids= ids
ary = ids.map { |id| ["
#{
base_class_name
}
", id] }
self.paste_
#{
downcase
}
_list = ary
end
def paste_
#{
downcase
}
_ids= ids
ary = ids.map { |id| ["
#{
base_class_name
}
", id] }
self.paste_
#{
downcase
}
_list = ary
end
def paste_
#{
downcase
}
_list= ary, run_save: true
ary = self.class.parsed_condition_ary(ary).select { |a|
a.first == "
#{
base_class_name
}
"
}
if new_record?
@paste_
#{
downcase
}
_list = ary
else
exist_ary = pastings.where(pasted: self, pasteable_type: "
#{
base_class_name
}
").pluck(:pasteable_type, :pasteable_id)
add_ary = ary - exist_ary
remove_ary = exist_ary - ary
self.class.transaction do
remove_ary.each { |klass, id| pastings.where(
pasted: self,
pasteable_type: klass,
pasteable_id: id
).destroy_all
}
add_ary.each { |klass, id| pastings.create!(
pasted: self,
pasteable_type: klass,
pasteable_id: id
)
}
end
def paste_
#{
downcase
}
_list= ary, run_save: true
ary = self.class.parsed_condition_ary(ary).select { |a|
a.first == "
#{
base_class_name
}
"
}
if new_record?
@paste_
#{
downcase
}
_list = ary
else
exist_ary = pastings.where(
type: "
#{
type_value
}
", pasted: self, pasteable_type: "
#{
base_class_name
}
"
).pluck(:pasteable_type, :pasteable_id)
add_ary = ary - exist_ary
remove_ary = exist_ary - ary
self.class.transaction do
remove_ary.each { |klass, id| pastings.where(
type: "
#{
type_value
}
",
pasted: self,
pasteable_type: klass,
pasteable_id: id
).destroy_all
}
add_ary.each { |klass, id| pastings.create!(
type: "
#{
type_value
}
",
pasted: self,
pasteable_type: klass,
pasteable_id: id
)
}
end
end
end
private
private
def save_paste_
#{
downcase
}
_list
if @paste_
#{
downcase
}
_list
self.paste_
#{
downcase
}
_list = @paste_
#{
downcase
}
_list
end
def save_paste_
#{
downcase
}
_list
if @paste_
#{
downcase
}
_list
self.paste_
#{
downcase
}
_list = @paste_
#{
downcase
}
_list
end
RUBY
end
end
RUBY
end
end
def
parsed_condition_ary
ary
case
ary
.
first
when
ActiveRecord
::
Base
ary
.
map
{
|
obj
|
[
obj
.
class
.
base_class
.
name
,
obj
.
id
]
}
when
Hash
ary
.
map
{
|
h
|
[
h
[
:paste_type
].
constantize
.
base_class
.
name
,
h
[
:paste_id
]]
}
else
ary
.
map
{
|
a
|
[
a
.
first
.
constantize
.
base_class
.
name
,
a
.
last
]
}
end
def
parsed_condition_ary
ary
ary
=
ary
.
compact
return
[]
unless
ary
&&
ary
.
first
case
ary
.
first
when
ActiveRecord
::
Base
ary
.
map
{
|
obj
|
[
obj
.
class
.
base_class
.
name
,
obj
.
id
]
}
when
Hash
ary
.
map
{
|
h
|
[
h
[
:pasted_type
].
constantize
.
base_class
.
name
,
h
[
:pasted_id
]]
}
else
ary
.
map
{
|
a
|
[
a
.
first
.
constantize
.
base_class
.
name
,
a
.
last
]
}
end
end
def
acts_as_pasted
associations
,
options
=
{}
has_many
associations
,
through: :pastings
,
source: :pasteable
,
**
options
end
def
acts_as_pasted
associations
,
options
=
{}
has_many
associations
,
through: :pastings
,
source: :pasteable
,
**
options
end
end
module
Association
def
acts_as_pasted
associations
,
options
=
{}
has_many
:pastings
,
as: :pasteable
has_many
associations
,
through: :pastings
,
source: :pasted
,
**
options
end
module
Association
def
acts_as_pasted
associations
,
options
=
{}
has_many
:pastings
,
as: :pasteable
has_many
associations
,
through: :pastings
,
source: :pasted
,
**
options
end
end
end
lib/acts_as_pasting/pasting.rb
View file @
896f6f72
...
...
@@ -20,6 +20,8 @@
#
module
ActsAsPasting
class
Pasting
<
ApplicationRecord
self
.
inheritance_column
=
:_type_disabled
belongs_to
:pasteable
,
polymorphic:
true
belongs_to
:pasted
,
polymorphic:
true
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment