Commit 0e627fc8 by Ivan Lan

Update scope & Support :prefix to association methods

parent e23bc7b1
...@@ -11,26 +11,32 @@ module ActsAsPasting ...@@ -11,26 +11,32 @@ module ActsAsPasting
# ary => [obj, obj] # ary => [obj, obj]
scope :pasted_with_any, ->(ary, prefix: '') { scope :pasted_with_any, ->(ary, prefix: '') {
ary = parsed_condition_ary(ary) ary = parsed_condition_ary(ary)
ids = ary.map do |klass, id| arel = Arel::Table.new(:acts_as_pasting_pastings, as: "acts_as_pasting_pastings_#{SecureRandom.hex(10)}")
joins(:pastings).where(acts_as_pasting_pastings: { source_arel = arel_table
pasted_type: klass.constantize.base_class.name, pasted_id: id, type: prefix join_condition = ary.group_by(&:first).map do |(klass, value)|
}).pluck(:id) ids = value.map(&:last)
end.reduce(:|) arel[:pasted_type].eq(klass.constantize.base_class.name).
where(id: ids) and(arel[:pasted_id].in(ids)).
and(arel[:pasteable_id].eq(source_arel[:id])).
and((arel[:type].eq(prefix))
end.reduce(:or)
joins(arel.join(arel).on(join_condition).join_sources).distinct
} }
scope :pasted_with_all, ->(ary, prefix: '') { scope :pasted_with_all, ->(ary, prefix: '') {
ary = parsed_condition_ary(ary) ary = parsed_condition_ary(ary)
ids = ary.map do |klass, id| ary.reduce(where(nil)) do |association, value|
joins(:pastings).where(acts_as_pasting_pastings: { association.pasted_with_any([value], prefix: prefix)
pasted_type: klass.constantize.base_class.name, pasted_id: id, type: prefix end
}).pluck(:id)
end.reduce(:&)
where(id: ids)
} }
end end
module ClassMethods module ClassMethods
def acts_as_pastable associations, options={}, prefix: ''
pasting_name = prefix.blank? ? :pastings : [prefix, 'pastings'].join('_').to_sym
has_many pasting_name, as: :pasteable, class_name: 'ActsAsPasting::Pasting'
has_many associations, through: pasting_name, source: :pasted, **options
end
end end
end end
end end
module ActsAsPasting
module Pasteable
extend ActiveSupport::Concern
# 带 prefix 的 pasted_with,独立于不带 prefix 的之外
included do
has_many :pastings, as: :pasteable, class_name: 'ActsAsPasting::Pasting'
has_many :hosts, through: :pastings
# 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(acts_as_pasting_pastings: {
pasted_type: klass.constantize.base_class.name, pasted_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(acts_as_pasting_pastings: {
pasted_type: klass.constantize.base_class.name, pasted_id: id, type: prefix
}).pluck(:id)
end.reduce(:&)
where(id: ids)
}
end
module ClassMethods
def acts_as_pastable associations, options={}
has_many :pastings, as: :pasteable, class_name: 'ActsAsPasting::Pasting'
has_many associations, through: :pastings, source: :pasted, **options
end
end
end
end
...@@ -9,22 +9,23 @@ module ActsAsPasting ...@@ -9,22 +9,23 @@ module ActsAsPasting
# ary => [obj, obj] # ary => [obj, obj]
scope :pasted_with_any, ->(ary, prefix: '') { scope :pasted_with_any, ->(ary, prefix: '') {
ary = parsed_condition_ary(ary) ary = parsed_condition_ary(ary)
ids = ary.map do |klass, id| arel = Arel::Table.new(:acts_as_pasting_pastings, as: "acts_as_pasting_pastings_#{SecureRandom.hex(10)}")
joins(:pastings).where(acts_as_pasting_pastings: { source_arel = arel_table
pasteable_type: klass.constantize.base_class.name, pasteable_id: id, type: prefix join_condition = ary.group_by(&:first).map do |(klass, value)|
}).pluck(:id) ids = value.map(&:last)
end.reduce(:|) arel[:pasteable_type].eq(klass.constantize.base_class.name).
where(id: ids) and(arel[:pasteable_id].in(ids)).
and(arel[:pasted_id].eq(source_arel[:id])).
and((arel[:type].eq(prefix))
end.reduce(:or)
joins(arel.join(arel).on(join_condition).join_sources).distinct
} }
scope :pasted_with_all, ->(ary, prefix: '') { scope :pasted_with_all, ->(ary, prefix: '') {
ary = parsed_condition_ary(ary) ary = parsed_condition_ary(ary)
ids = ary.map do |klass, id| ary.reduce(where(nil)) do |association, value|
joins(:pastings).where(acts_as_pasting_pastings: { association.pasted_with_any([value], prefix: prefix)
pasteable_type: klass.constantize.base_class.name, pasteable_id: id, type: prefix end
}).pluck(:id)
end.reduce(:&)
where(id: ids)
} }
after_create :save_paste_list after_create :save_paste_list
...@@ -156,7 +157,7 @@ module ActsAsPasting ...@@ -156,7 +157,7 @@ module ActsAsPasting
).pluck(:pasteable_type, :pasteable_id) ).pluck(:pasteable_type, :pasteable_id)
add_ary = ary - exist_ary add_ary = ary - exist_ary
remove_ary = exist_ary - ary remove_ary = exist_ary - ary
self.class.transaction do self.class.transaction do
remove_ary.each { |klass, id| pastings.where( remove_ary.each { |klass, id| pastings.where(
type: "#{type_value}", type: "#{type_value}",
...@@ -200,8 +201,10 @@ module ActsAsPasting ...@@ -200,8 +201,10 @@ module ActsAsPasting
end end
end end
def acts_as_pasted associations, options={} def acts_as_pasted associations, options={}, prefix: ''
has_many associations, through: :pastings, source: :pasteable, **options pasting_name = prefix.blank? ? :pastings : [prefix, 'pastings'].join('_').to_sym
has_many pasting_name, -> { where(type: prefix) }, class_name: 'ActsAsPasting::Pasting', as: :pasted
has_many associations, through: pasting_name, source: :pasteable, **options
end end
end end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment