1

In an application there are many models with polymorphic associations defined like:

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

In a library class all mentionable models are collected for later iterating.

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

This works but it is just static which is not desirable for a library code. Bottom statement would be much more intuitive hovever it won't work.

mentionables = Mentionable.all

Is there an API in Rails to iterate over models with Polymorphic relations defined with ':as => ...' directive?

Dara
  • 68
  • 6

1 Answers1

1

I think there are two questions in here and I'll try my best to answer both of them. First, you'd need a way to list all of the models in your Rails application. There are methods offered in this question, and I prefer this answer (by sj26).

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

After, you need to parse the model associations to determine if they have an :as @option assigned, and pull out the associated class name. This is assuming that your association has been created as such:

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

You can do this using the reflect_on_all_associations method (there is probably a more ruby-esque way to write this):

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

Which will return the polymorphic class model for Mentionable. To join these up, you could do something as follows (untested!):

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
Community
  • 1
  • 1
d_ethier
  • 3,873
  • 24
  • 31