I've nailed down what I want, but I can't seem to get it in a way that the rails designers are looking for. Basically, I have (please set aside pluralization/etc issues):
Human Relationships (Parent, Offspring)
I'm trying to get all the offsprings for a single parent, and the single parent for many offsprings (assume only one parent per offspring).
I can do this in the following way in the model:
has_one :parent, :through => :relationships, :foreign_key => :human_id, :source => :source_human
has_many :offsprings, :finder_sql =>
'SELECT DISTINCT offsprings.* ' +
'FROM humans offsprings INNER JOIN relationships r on ' +
'r.human_id = offsprings.id where r.source_human_id = #{id}'
I had to do this, because the nicer way to do it:
has_many :offsprings, :through => :relationships, :foreign_key => :source_human_id, :source => :human
Is not possible because foreign keys are ignored in has_many (according to the docs here: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many)
However, now I'm getting this error:
DEPRECATION WARNING: String-based interpolation of association conditions is deprecated. Please use a proc instead. So, for example, has_many :older_friends, :conditions => 'age > #{age}' should be changed to has_many :older_friends, :conditions => proc { "age > #{age}" }. (called from irb_binding at (irb):1)
However, no matter how I hack at :conditions here, it does not appear that :finder_sql wants to participate. Any thoughts?
Rails offers two different ways to declare a many-to-many relationship between models. The first way is to use has_and_belongs_to_many, which allows you to make the association directly: The second way to declare a many-to-many relationship is to use has_many :through.
Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.
has_one means that there is a foreign key in another table that references this class. So has_one can ONLY go in a class that is referenced by a column in another table. For a two-way association, you need one of each, and they have to go in the right class. Even for a one-way association, it matters which one you use.
What if you do
has_many :offsprings, :finder_sql =>
proc { "SELECT DISTINCT offsprings.* " +
"FROM humans offsprings INNER JOIN relationships r on " +
"r.human_id = offsprings.id where r.source_human_id = #{id}" }
Actually, I'd write it this way:
has_many :offsprings, :finder_sql => proc {OFFSPRING_SQL % {id: id}}
OFFSPRING_SQL = "SELECT DISTINCT offsprings.*
FROM humans offsprings
INNER JOIN relationships r
ON r.human_id = offsprings_id
WHERE r.source_human_id = %{id}"
I think it makes the association easier to understand, and it make the naked SQL easier to edit. It also takes advantage of string-based parameter interpolation.
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