示例:
假设我们有一个具有多态关联的模型提醒。
class Reminder < ActiveRecord::Base
belongs_to :rememberable, polymorphic: true
scope :events, -> { where(rememberable_type: 'Event') }
end
然后,我可以使用
获取所有记住的事件的列表events = Reminder.events.map(&:rememberable)
问题:
有没有办法将它放入多态关联的扩展或提醒的范围内?所以我们可以这样称呼它:
events = Reminder.events.unpack
我尝试了什么:
我试过
class Reminder < ActiveRecord::Base
belongs_to :rememberable, polymorphic: true do
def unpack
map(&:rememberable)
end
end
scope :events, -> { where(rememberable_type: 'Event') }
end
和
class Reminder < ActiveRecord::Base
belongs_to :rememberable, polymorphic: true
scope :events, -> { where(rememberable_type: 'Event') }
scope :unpack, -> { to_a.map(&:rememberable) }
end
没有成功。
旁注:
我知道,让一个范围结束ActiveRecord的Relation Proxy的可链接性是一般的坏习惯。
答案 0 :(得分:2)
除了破坏ActiveRecord关系链之外,还会使用map
和/或to_a
来解决性能问题,这会强制获取所有现有记录并在Rails过程中循环遍历它们。
所以不是&#34; 寻找现有的提醒并给我相关的事件&#34;你应该&#34; 查找至少有一个相关提醒的事件&#34;。事实上,在设计关联范围时,您应该始终从您希望在结果中使用的模型开始。不要尝试在Reminder
中实现可返回Event
集合的范围。
1-让我们创造一个问题:
module Rememberable
extend ActiveSupport::Concern
included do |base|
base.scope :with_reminders, -> { joins :reminders }
end
end
2-包括您对模型的关注
class Event < ActiveRecord::Base
include Rememberable
...
3-使用
events = Event.with_reminders
答案 1 :(得分:1)
实际上非常简单。您可以使用类方法作为Rails中的作用域。因此,让我们编写类方法(在Reminder
中):
def self.unpack
@relation.map(&rememberable)
end
或者如果您更喜欢范围语法:
scope :unpack, -> { @relation.map(&rememberable) }
然而,由于它结束了ActiveRecord的Relation Proxy的可链接性,我宁愿把它写成一个类方法(而不是显式范围)。