How to get activerecord associations via reflection

RubyReflectionActiverecord

Ruby Problem Overview


For normal columns, you can get at them via the columns class method. However, associations may be named something quite different if the foreign_key option is set in the relationship method. For example, given

class Post
  has_many :comments, :foreign_key => :message_id # this is a contrived example
end

if I did Post.column_names I could get at message_id, but is there any way to get comments?

Ruby Solutions


Solution 1 - Ruby

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".

Solution 2 - Ruby

For future Googlers in Rails 4 the answer would now be:

Post.reflections[:comments].foreign_key # => "message_id"

Taken from here: https://stackoverflow.com/a/15364743/2167965

EDIT:

reflections, as of 4.2, now takes strings instead of symbols which is a fun bug to track down. If you want to keep using symbols you should switch to reflect_on_association(:assoc_name). Also note reflections are actually the public api which will keep reporting things like HABTM, even though it's all has many through under the hood. The reflections Rails is actually using are now in _reflections

Solution 3 - Ruby

For an ActiveRecord object I use:

object._reflections

So, I can manipulate the Hash returned. For instance:

object._reflections.keys.each do |key|
    object.public_send(key).destroy_all
end

The above example delete all the relationships from database.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatt BriggsView Question on Stackoverflow
Solution 1 - RubymikejView Answer on Stackoverflow
Solution 2 - RubyMCBView Answer on Stackoverflow
Solution 3 - RubyLucivaldo CastroView Answer on Stackoverflow