I''d like to use :through to create a web of associations like: class Thing < ActiveRecord::Base has_many :child_things, :through => :thing_thing has_many :parent_things, :through => :thing_thing, :some_other_option? end class ThingThing < ActiveRecord::Base belongs_to :thing belongs_to :child_thing, :class_name => ''Thing'', :foreign_key => ''child_thing_id'' end The child_things works. The parent_things does not, or at least, I cannot figure out the sytnax. I would like it to issue an sql like: SELECT things.* FROM things INNER JOIN thing_things ON things.id = thing_things.thing_id WHERE (thing_things.child_thing_id = 6201) Is there a way to trigger this sql using the through options? Many thanks Tom -- Posted via http://www.ruby-forum.com/.
It looks like you are trying to create a self-referential has_many :through association, which should work just fine for what you want. However you don''t have it set up properly. The :through option on a has_many association must refer to another has_many association in the same model. It gets to its target through the other association, thus the name. Here''s an example snipped from the Rails 1.1 test code (always a good place to look for example code): class Author < ActiveRecord::Base has_many :author_favorites has_many :favorite_authors, :through => :author_favorites, :order => ''name'' end class AuthorFavorite < ActiveRecord::Base belongs_to :author belongs_to :favorite_author, :class_name => "Author", :foreign_key => ''favorite_author_id'' end If you need to change the name of the association from its name in the join model, use the :source option to specify that name. Check the docs on that. I should blog an article on this soon, as it can get a bit tricky to combine all the options and get them to work together correctly. -- Josh Susser http://blog.hasmanythrough.com Thomas Counsell wrote:> I''d like to use :through to create a web of associations like: > > class Thing < ActiveRecord::Base > has_many :child_things, :through => :thing_thing > has_many :parent_things, :through => :thing_thing, :some_other_option? > end > > class ThingThing < ActiveRecord::Base > belongs_to :thing > belongs_to :child_thing, :class_name => ''Thing'', :foreign_key => > ''child_thing_id'' > end > > The child_things works. The parent_things does not, or at least, I > cannot figure out the sytnax. I would like it to issue an sql like: > > SELECT things.* FROM things INNER JOIN thing_things ON things.id = > thing_things.thing_id WHERE (thing_things.child_thing_id = 6201) > > Is there a way to trigger this sql using the through options? > > Many thanks > > Tom-- Posted via http://www.ruby-forum.com/.
Thanks Josh. I didn''t explain myself clearly. In terms of your model, I''m really looking for the ability to add a reverse link: class Author < ActiveRecord::Base has_many :author_favorites has_many :favorite_authors, :through => :author_favorites, :order => ''name'' # I''d like the reverse as well: has_many :other_authors_who_love_me, :through => :author_favourites end class AuthorFavorite < ActiveRecord::Base belongs_to :author belongs_to :favorite_author, :class_name => "Author", :foreign_key => ''favorite_author_id'' end The :source option appears to rename the association, what I want is to have :other_authors_who_love_me return AuthorFavorite#author by joining on AuthorFavorite#favorite_author. Is this possible? Thanks Tom Josh Susser wrote:> It looks like you are trying to create a self-referential has_many > :through association, which should work just fine for what you want. > However you don''t have it set up properly. The :through option on a > has_many association must refer to another has_many association in the > same model. It gets to its target through the other association, thus > the name. > > Here''s an example snipped from the Rails 1.1 test code (always a good > place to look for example code): > > class Author < ActiveRecord::Base > has_many :author_favorites > has_many :favorite_authors, :through => :author_favorites, :order => > ''name'' > end > > class AuthorFavorite < ActiveRecord::Base > belongs_to :author > belongs_to :favorite_author, :class_name => "Author", :foreign_key => > ''favorite_author_id'' > end > > If you need to change the name of the association from its name in the > join model, use the :source option to specify that name. Check the docs > on that. > > I should blog an article on this soon, as it can get a bit tricky to > combine all the options and get them to work together correctly. > > -- > Josh Susser > http://blog.hasmanythrough.com > > > > Thomas Counsell wrote: >> I''d like to use :through to create a web of associations like: >> >> class Thing < ActiveRecord::Base >> has_many :child_things, :through => :thing_thing >> has_many :parent_things, :through => :thing_thing, :some_other_option? >> end >> >> class ThingThing < ActiveRecord::Base >> belongs_to :thing >> belongs_to :child_thing, :class_name => ''Thing'', :foreign_key => >> ''child_thing_id'' >> end >> >> The child_things works. The parent_things does not, or at least, I >> cannot figure out the sytnax. I would like it to issue an sql like: >> >> SELECT things.* FROM things INNER JOIN thing_things ON things.id = >> thing_things.thing_id WHERE (thing_things.child_thing_id = 6201) >> >> Is there a way to trigger this sql using the through options? >> >> Many thanks >> >> Tom-- Posted via http://www.ruby-forum.com/.
The :source option doesn''t just rename the association, but it chooses which association in the join model to use to join to the target model. I think it will do just what you want: has_many :other_authors_who_love_me, :through => :author_favourites, :source => :author -- Josh Susser http://blog.hasmanythrough.com Thomas Counsell wrote:> Thanks Josh. > > I didn''t explain myself clearly. In terms of your model, I''m really > looking for the ability to add a reverse link: > > class Author < ActiveRecord::Base > has_many :author_favorites > has_many :favorite_authors, :through => :author_favorites, :order => > ''name'' > # I''d like the reverse as well: > has_many :other_authors_who_love_me, :through => :author_favourites > end > > class AuthorFavorite < ActiveRecord::Base > belongs_to :author > belongs_to :favorite_author, :class_name => "Author", :foreign_key => > ''favorite_author_id'' > end > > The :source option appears to rename the association, what I want is to > have :other_authors_who_love_me return AuthorFavorite#author by joining > on AuthorFavorite#favorite_author. > > Is this possible?-- Posted via http://www.ruby-forum.com/.
Thanks again Josh, that didn''t do what I want. After much time wasted the solution was obvious (although a little clunky), so it is probably me not explaining clearly. class Author < ActiveRecord::Base # Forwards has_many :author_favorites has_many :favorite_authors, :through => :author_favorites, :order => ''name'' ?# Backwards has_many :reverse_author_favourites, :class_name => ''AuthorFavorite'', :foreign_key => :favorite_author has_many :other_authors_who_love_me, :through => :reverse_author_favourites, :source => :authors end class AuthorFavorite < ActiveRecord::Base belongs_to :author belongs_to :favorite_author, :class_name => "Author", :foreign_key => ''favorite_author_id'' end Josh Susser wrote:> The :source option doesn''t just rename the association, but it chooses > which association in the join model to use to join to the target model. > I think it will do just what you want: > > has_many :other_authors_who_love_me, :through => :author_favourites, > :source => :author-- Posted via http://www.ruby-forum.com/.