Assuming I am abstracting code, and am looping through the column names of object x, what's the best way to detect if a column is an association or not?
I know I can do this, but I am wondering if there is a better way:
@user = User.first
@user.attributes.keys.each do |column|
if column[-3..-1] == "_id" && @user.respond_to?(column[0..-4].to_sym)
puts "#{column} is an association / relation."
else
puts "#{column} is not an assocation / relation."
end
end
end
Any built-in Rails methods or helpers to detect associations? Code above is neither pretty nor fool proof. Thanks!
They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user . To determine who "has" the other object, look at where the foreign key is.
ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending. Edit: as Mike points out, in this case ActiveRecord is a module...
Association in Rails defines the relationship between models. It is also the connection between two Active Record models. To figure out the relationship between models, we have to determine the types of relationship. Whether it; belongs_to, has_many, has_one, has_one:through, has_and_belongs_to_many.
One way to do this would be to reflect upon all associations for that class:
associations = class_goes_here.reflect_on_all_associations
And then to find just the belongs_to
ones, since those will have the _id
field:
associations = associations.select { |a| a.macro == :belongs_to }
Then you can find the foreign key used on these associations by doing this:
association_foreign_keys = associations.map(&:foreign_key)
I wouldn't use @user.attributes
to get the attributes and then keys
on that to get the column names. I would use User.column_names
to get the column names.
Therefore, with all that explained, you can then change your code to be this to make it more foolproof:
associations = User.reflect_on_all_associations
associations = associations.select { |a| a.macro == :belongs_to }
association_foreign_keys = associations.map(&:foreign_key)
User.column_names.each do |column|
if association_foreign_keys.include?(column)
puts "#{column} is an association / relation."
else
puts "#{column} is not an assocation / relation."
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With