使用多态关联迭代Rails模型类

时间:2013-01-26 10:42:20

标签: ruby-on-rails polymorphism iteration

在应用程序中,有许多模型具有多态关联,如:

has_many :mentions, :as => :mentionable, :dependent => :destroy

在库类中,收集所有可提及的模型以供稍后迭代。

mentionables = Model1.all + Model2.all + Model3.all ...

这有效,但它只是静态的,这对于库代码来说是不可取的。底层声明会更加直观,但它无法发挥作用。

mentionables = Mentionable.all

Rails中是否有一个API来迭代具有':as =>定义的多态关系的模型......'指令?

1 个答案:

答案 0 :(得分:1)

我认为这里有两个问题,我会尽力回答这两个问题。首先,您需要一种方法来列出Rails应用程序中的所有模型。 this问题中提供了一些方法,我更喜欢this answersj26}。

# Really depends on how your classes are loaded, usually environment specific.
Rails.application.eager_load!
ActiveRecord::Base.descendants

之后,您需要解析模型关联以确定它们是否具有:@option,并拉出关联的类名。这假设你的关联是这样创建的:

class Mentionee < ActiveRecord::Base
  has_many :mentions, :as => :mentionable, :dependent => :destroy, :class_name => 'Mentionable'
end

您可以使用reflect_on_all_associations方法执行此操作(可能有更多红宝石式的方式来编写此方法):

Mentionee.reflect_on_all_associations.select {|a| a.options[:as] == :mentionable }

将返回Mentionable的多态类模型。要加入这些,您可以执行以下操作(未经测试!):

Rails.application.eager_load!

mentionables = []

ActiveRecord::Base.descendants.each do |descendent|
  mentionables << descendent.reflect_on_all_associations.select{|a| a.options[:as] == :mentionable}
end

mentionables.each do |mentionable|
  # Do your work here
end