Still Having Problems With :through When Going To Same Table... Help... please :-(

I am having a problem with doing a :through that goes back to the same table.

The following are my two classes:

class User < ActiveRecord::Base   has_many :spanks   has_many :spanked, :through => :spanks, :source => :spanked_user   has_many :was_spanked_by, :through => :spanks, :source => :user end

class Spank < ActiveRecord::Base   belongs_to :spanker, :class_name => "User", :foreign_key => "user_id"   belongs_to :spankee, :class_name => "User", :foreign_key => "spanked_user_id" end

db_table:spanks id | user_id | spanked_user_id | created_at | updated_at

I want to be able to make statemets like:

john = User.find_by_nickname("john") john.spanked john.was_spanked_by

Can I do this without using a :finder_sql?

The above does not work... but the following does:

john.spanks spank = Spank.find(1) spank.spankee spank.spanker

Help... help... I get the following error:

ActiveRecord::HasManyThroughSourceAssociationNotFoundError:ActiveRecord::HasManyThroughSourceAssociationNotFoundError

John Kopanas wrote:

I am having a problem with doing a :through that goes back to the same table.   

Try this...

class User < ActiveRecord::Base   has_many :spanks_as_spankee, :foreign_key=>'spanked_user_id', :class_name => 'Spank'   has_many :spanks_as_spanker, :foreign_key=>'user_id', :class_name => 'Spank'   has_many :spanked, :through => :spanks_as_spankee   has_many :was_spanked_by, :through => :spanks_as_spanker end

although, if it were my app, I would make some small association and column name changes as well, so that...

class User < ActiveRecord::Base   has_many :spanks_as_spankee, :foreign_key=>'spankee_id', :class_name => 'Spank'   has_many :spanks_as_spanker, :foreign_key=>'spanker_id', :class_name => 'Spank'   has_many :spankees, :through => :spanks_as_spankee   has_many :spankers, :through => :spanks_as_spanker end

class Spank < ActiveRecord::Base   belongs_to :spanker, :class_name => "User", :foreign_key => "spanker_id"   belongs_to :spankee, :class_name => "User", :foreign_key => "spankee_id" end

Note: I haven't actually tested the above, but I've done similar and it works great. Credit goes to Josh Susser for showing me how to do self referential :throughs a while back via his blog. http://blog.hasmanythrough.com/

Jon Garvin wrote:

John Kopanas wrote:
I am having a problem with doing a :through that goes back to the same table.

Try this...
class User < ActiveRecord::Base
has_many :spanks_as_spankee, :foreign_key=>'spanked_user_id', :class_name => 'Spank'
has_many :spanks_as_spanker, :foreign_key=>'user_id', :class_name => 'Spank'
has_many :spanked, :through => :spanks_as_spankee
has_many :was_spanked_by, :through => :spanks_as_spanker
end
although, if it were my app, I would make some small association and
column name changes as well, so that...
class User < ActiveRecord::Base
has_many :spanks_as_spankee, :foreign_key=>'spankee_id', :class_name => 'Spank'
has_many :spanks_as_spanker, :foreign_key=>'spanker_id', :class_name => 'Spank'
has_many :spankees, :through => :spanks_as_spankee
has_many :spankers, :through => :spanks_as_spanker
end
class Spank < ActiveRecord::Base
belongs_to :spanker, :class_name => "User", :foreign_key => "spanker_id"
belongs_to :spankee, :class_name => "User", :foreign_key => "spankee_id"
end
Note: I haven't actually tested the above, but I've done similar and it
works great. Credit goes to Josh Susser for showing me how to do self
referential :throughs a while back via his blog.

Whoops, got an association backwards in the alternate option above. This is what I meant…

  class User < ActiveRecord::Base
has_many :spanks_as_spankee, :foreign_key=>'spankee_id', :class_name => 'Spank'
has_many :spanks_as_spanker, :foreign_key=>'spanker_id', :class_name => 'Spank'
has_many :spank**ers**  , :through => :spanks_as_spankee
has_many :spank**ees**, :through => :spanks_as_spanker
end

Worked great! Thanks Jon... but now I have a couple questions for you if you don't mind :-).

1) why is :through point to a has_many relatioship? I thought it usually points to an object/table.

2) If I change spankers to spanked_by it breaks... why?

Thanks again for your help :-).

John Kopanas wrote:

Worked great! Thanks Jon... but now I have a couple questions for you if you don't mind :-).

1) why is :through point to a has_many relatioship? I thought it usually points to an object/table.

2) If I change spankers to spanked_by it breaks... why?

Thanks again for your help :-).

Josh Susser, or anyone else more familiar with how this technique works, can probably provide much better answers. But...

1) Yes, normally it would point directly to the join model/table. However, to do more complex stuff (like self referential has_many :throughs), sometimes you gotta break out the magic wand and wave it with enthusiasm.

2) I just guessing, but maybe the '_by' suffix is getting some other Rails magic applied to it. Try changing it to :spanked_bx, and see if that helps. Either way, someone more familiar than I with the Rails internals might be able to explain it.