有没有办法重构将多态关联解压缩到其模型中?

时间:2014-10-15 10:18:46

标签: ruby-on-rails rails-activerecord

示例:

假设我们有一个具有多态关联的模型提醒。

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的可链接性是一般的坏习惯。

2 个答案:

答案 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的可链接性,我宁愿把它写成一个类方法(而不是显式范围)。