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
5 years ago
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
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
...
...
This diff is collapsed.
Click to expand it.
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