How to get activerecord associations via reflection
Model.reflections
gives information about a model's associations. It is a Hash
keyed on the association name. e.g.
Post.reflections.keys # => ["comments"]
Here is an example of some of the information it can be used to access:
Post.reflections["comments"].table_name # => "comments"
Post.reflections["comments"].macro # => :has_many
Post.reflections["comments"].foreign_key # => "message_id"
Note: this answer has been updated to cover Rails 4.2 based on MCB's answer and the comments below. In earlier versions of Rails the reflection's foreign_key
was accessed using primary_key_name
instead, and the keys for the reflections may be symbols instead of strings depending on how the association was defined e.g. :comments
instead of "comments"
.
ActiveRecord::Reflections methods - modelname_ids
Use String#singularize
:
tale_instance_object.send(x.name.to_s.singularize + "_ids") # => [1, 2, 3, ...]
Also, you can use built-in #ids_reader
method:
my_model_instance.association(:x).ids_reader # => [1, 2, 3, ...]
Programatically get the class of the belongs_to association in Rails 4
B.reflect_on_all_associations(:belongs_to).map(&:name)
or
b.class.reflect_on_all_associations(:belongs_to).map(&:name)
How to iterate an ActiveRecord object's associated objects
Model name can be converted to object using public_send in case you fetched the association models, check below:
parent_object.reflect_on_all_associations(:has_one).map(&:class_name).each do |model_name|
# assuming that parent_object is the object that has all associations.
obj = parent_object.public_send(model_name)
do_stuff_to_assoc_object(obj)
end
def do_stuff_to_assoc_object(obj)
# I do things to the associated object here
end
As per @Clemens Kofler comment, to avoid double iteration, we can remove the .map as following:
parent_object.reflect_on_all_associations(:has_one).each do |association|
# assuming that parent_object is the object that has all associations.
obj = parent_object.public_send(association.class_name)
do_stuff_to_assoc_object(obj)
end
def do_stuff_to_assoc_object(obj)
# I do things to the associated object here
end
Reference:
https://apidock.com/ruby/Object/public_send
Processing ActiveRecord::Reflections -- some model reflections coming up empty (Rails 4.2)
I couldn't find any resources to guide me through Rails' inner-workings, so instead I went to look at a popular gem that likewise needs to parse through ActiveRecord::Reflections, ActiveModel::Serializer, since it too would likely have to deal with Rails not loading things as it wished. There, I found:
included do
...
extend ActiveSupport::Autoload
autoload :Association
autoload :Reflection
autoload :SingularReflection
autoload :CollectionReflection
autoload :BelongsToReflection
autoload :HasOneReflection
autoload :HasManyReflection
end
Adding this to my concern solved my issues. From the ActiveSupport::Autoload docs: "This module allows you to define autoloads based on Rails conventions (i.e. no need to define the path it is automatically guessed based on the filename) and also define a set of constants that needs to be eager loaded".
Is there a way to list all belongs_to associations?
You could make use of the class's reflections
hash to do this. There may be more straightforward ways, but this works:
# say you have a class Thing
class Thing < ActiveRecord::Base
belongs_to :foo
belongs_to :bar
end
# this would return a hash of all `belongs_to` reflections, in this case:
# { :foo => (the Foo Reflection), :bar => (the Bar Reflection) }
reflections = Thing.reflections.select do |association_name, reflection|
reflection.macro == :belongs_to
end
# And you could iterate over it, using the data in the reflection object,
# or just the key.
#
# These should be equivalent:
thing = Thing.first
reflections.keys.map {|association_name| thing.send(association_name) }
reflections.values.map {|reflection| thing.send(reflection.name) }
Ambiguous source reflection for through association error? (Rails)
This error is telling you the relationship between Stuff
and Thing
is ambiguous because you haven't defined the relationship between Stuff
and Foo
. This typically looks like this:
class Student
has_many :scheduled_classes
has_many :teachers, through: :scheduled_classes
end
class ScheduledClass
belongs_to :student
belongs_to :teacher
end
class Teacher
has_many :scheduled_classes
has_many :students, through: :scheduled_classes
end
Note that the through
value is named after a relationship on the same class.
Get rails associations from console
User.reflect_on_all_associations
This will return an array of associations similar to this:
#<ActiveRecord::Reflection::AssociationReflection:0x00000105575548 @macro=:has_many, @name=:posts, @options={}, @active_record=User(id: integer, login: string), @collection=false>
Sample code:
reflections = User.reflect_on_all_associations
reflections.each do |reflection|
puts ":#{reflection.macro} => :#{reflection.name}"
end
Related Topics
How to Use Ruby for Shell Scripting
Method_Missing Gotchas in Ruby
Find Out If an Ip Is Within a Range of Ips
How to Call Expire_Fragment from Rails Observer/Model
Ruby: Module, Require and Include
Rails Rbenv: Rails: Command Not Found
Rails: Modifying a Model Generated by Scaffolding
Ruby: Finding Most Recently Modified File
How to Check If a Param Is True or False
How to I Make Private Class Constants in Ruby
How to Find Where Gem Files Are Installed
How to Upgrade to the Current Version of Ruby (2.2.3) on Os X V10.6.8
Installing Ruby 1.9.1 on Ubuntu
Accessing Config from Application.Rb in Controller (Rails 3)
Active Admin: Customize Only New Form
How to Change the Position of an Array Element