Has_many :through and foreign key parameters

I just took my HABTM and turned it into a :through since my join table
has another “non-joiny” attribute.

I went from this:

has_many_and_belongs_to :jobs, :join_table => ‘tablename’,
:foreign_key => ‘x’,
:association_foreign_key => ‘y’

to this:

has_many :jobs, :through => ‘model_name’

Should this work? I’m thinking that the foreign_key and assoc. foreign
key are no longer necessary since Rails can just go to the join model
and figure out the foreign keys, right?

Wes

Wes G. wrote:

I just took my HABTM and turned it into a :through since my join table
has another “non-joiny” attribute.

I went from this:

has_many_and_belongs_to :jobs, :join_table => ‘tablename’,
:foreign_key => ‘x’,
:association_foreign_key => ‘y’

to this:

has_many :jobs, :through => ‘model_name’

Should this work? I’m thinking that the foreign_key and assoc. foreign
key are no longer necessary since Rails can just go to the join model
and figure out the foreign keys, right?

That won’t work - you need to go through an association as a symbol,
(e.g. :join_models), not a name as a string. If you’re just starting out
with has_many :through, I’ve got some good examples on my blog. You
should start with
http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off

You can use :foreign_key for hmt, but instead of
:association_foreign_key you’ll use the :source option to select the
join model’s association to join with the third table.


Josh S.
http://blog.hasmanythrough.com

  1. The API docs. on ‘source’ are really confusing:

“:source: Specifies the source association name used by has_many
:through queries. Only use it if the name cannot be inferred from the
association. has_many :subscribers, :through => :subscriptions will look
for either +:subscribers+ or +:subscriber+ on Subscription, unless a
+:source+ is given.”

I would think that :source has nothing to do with foreign_key column
names? That source is a reference to an alternate model name, if, for
some reason you had a different collection that you wanted to reference
in the relationship.

Thanks,
Wes

I keep re-reading it, but I have no idea what that :source option
documentation is trying to say. Am I supposed to be specifying a
foreign_key column name, and then a source model object name to get
through to the other side?

WG

Wes G. wrote:

Just discovered your blog this AM and am really digging it. Thanks so
much for doing it.

Thanks, and you’re welcome.

Please indulge me in a couple of questions, if you would.

  1. The API docs. for ActiveRecord::Base say that :foreign_key will not
    be evaluated if you use has_many :through - are the API docs. wrong?

Oh, sorry. You’d use :foreign_key on the has_many for the join model.
That sets up the relationship of your main table to the join model.
:source is then used on the :through instead of :association_foreign_key

  1. The API docs. on ‘source’ are really confusing:

Yeah, I should try to clean those docs up. They are rather opaque. I
don’t really like the term :source either.

:source is used to specify the association in the join model to get to
the other side. You can see examples in
http://blog.hasmanythrough.com/articles/2006/05/06/through_gets_uniq
http://blog.hasmanythrough.com/articles/2006/04/21/self-referential-through


Josh S.
http://blog.hasmanythrough.com

So just to be explicit, from class A (backed by database table Table_A),
attempting to relate to class B, (backed by database table Table_B),
joined by model C

has_many :whatevers, :through => ‘C’,
:foreign_key => ‘key into Table_A’, :source => ‘B’

?

So just to be explicit, from class A (backed by database table Table_A),
attempting to relate to class B, (backed by database table Table_B),
joined by model C

has_many :whatevers, :through => ‘C’,
:foreign_key => ‘key into Table_A’, :source => ‘B’

?

So there is no reference to the foreign key column from B into C
(unlike the HABTM specification), correct?

Thanks,
Wes

Josh S. wrote:

Wes G. wrote:

I just took my HABTM and turned it into a :through since my join table
has another “non-joiny” attribute.

I went from this:

has_many_and_belongs_to :jobs, :join_table => ‘tablename’,
:foreign_key => ‘x’,
:association_foreign_key => ‘y’

to this:

has_many :jobs, :through => ‘model_name’

Should this work? I’m thinking that the foreign_key and assoc. foreign
key are no longer necessary since Rails can just go to the join model
and figure out the foreign keys, right?

That won’t work - you need to go through an association as a symbol,
(e.g. :join_models), not a name as a string. If you’re just starting out
with has_many :through, I’ve got some good examples on my blog. You
should start with
http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off

You can use :foreign_key for hmt, but instead of
:association_foreign_key you’ll use the :source option to select the
join model’s association to join with the third table.


Josh S.
http://blog.hasmanythrough.com

Johs,

Just discovered your blog this AM and am really digging it. Thanks so
much for doing it.

Please indulge me in a couple of questions, if you would.

  1. The API docs. for ActiveRecord::Base say that :foreign_key will not
    be evaluated if you use has_many :through - are the API docs. wrong?

  2. The API docs. on ‘source’ are really confusing:

“:source: Specifies the source association name used by has_many
:through queries. Only use it if the name cannot be inferred from the
association. has_many :subscribers, :through => :subscriptions will look
for either +:subscribers+ or +:subscriber+ on Subscription, unless a
+:source+ is given.”

I would think that :source has nothing to do with foreign_key column
names? That source is a reference to an alternate model name, if, for
some reason you had a different collection that you wanted to reference
in the relationship.

Thanks,
Wes

Wes G. wrote:

So just to be explicit, from class A (backed by database table Table_A),
attempting to relate to class B, (backed by database table Table_B),
joined by model C

has_many :Bs, :through => ‘C’,
:foreign_key => ‘key into Table_A’, :source => ‘B’

?

So there is no reference to the foreign key column from B into C
(unlike the HABTM specification), correct?

Thanks,
Wes

Better yet, let’s be really explicit.

I am trying to relate Job to TargetList through JobListAssociation.
None of the tables have “traditional” Rails naming conventions except
for the join table which happens to have an “id” column.

job.rb:

class Job < ActiveRecord::Base
set_table_name :JobData
set_primary_key :JobReferenceNumber

has_many :target_lists, :through => :job_list_association,
:foreign_key => :JobReferenceNumber,
:source => :target_list


target_list.rb:

class TargetList < ActiveRecord::Base
set_table_name :DataSetInfo
set_primary_key :DataSetID

has_many :jobs, :through => :job_list_association,
:foreign_key => :DataSetID,
:source => :job


job_list_association.rb:

class JobListAssociation < ActiveRecord::Base
set_table_name :DataTables

belongs_to :job, :foreign_key => ‘JobReferenceNumber’
belongs_to :target_list, :foreign_key => ‘DataSetID’

When I attempt to call @current_job.target_lists.include? in my view, I
see:

ActiveRecord::HasManyThroughAssociationNotFoundError in
E_simply#job_params

C:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/reflection.rb:169:in
check_validity!' C:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/associations/has_many_through_association.rb:6:ininitialize’
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/associations.rb:876:in
`target_lists’

Do I need to add a :condition onto my has_many specification?

Should I always be using symbols instead of strings as hash values in
these ActiveRecord relationship method calls? If so, why?

Thanks,
Wes

Wes G. wrote:

So just to be explicit, from class A (backed by database table Table_A),
attempting to relate to class B, (backed by database table Table_B),
joined by model C

has_many :whatevers, :through => ‘C’,
:foreign_key => ‘key into Table_A’, :source => ‘B’

So there is no reference to the foreign key column from B into C
(unlike the HABTM specification), correct?

You always need 2 associations in each class to do a join model - 2
belongs_to in the join model, then a has_many and a has_many :through in
the joined classes.

has_many :joinings, :foreign_key = “fk_id”
has_many :things, :through => :joinings, :source => :other

Please look at the examples on my blog. I don’t want to repeat myself
here.


Josh S.
http://blog.hasmanythrough.com

So just to be explicit, from class A (backed by database table Table_A),
attempting to relate to class B, (backed by database table Table_B),
joined by model C

has_many :Bs, :through => ‘C’,
:foreign_key => ‘key into Table_A’, :source => ‘B’

?

So there is no reference to the foreign key column from B into C
(unlike the HABTM specification), correct?

Thanks,
Wes

Josh S. wrote:

Wes G. wrote:

So just to be explicit, from class A (backed by database table Table_A),
attempting to relate to class B, (backed by database table Table_B),
joined by model C

has_many :whatevers, :through => ‘C’,
:foreign_key => ‘key into Table_A’, :source => ‘B’

So there is no reference to the foreign key column from B into C
(unlike the HABTM specification), correct?

You always need 2 associations in each class to do a join model - 2
belongs_to in the join model, then a has_many and a has_many :through in
the joined classes.

has_many :joinings, :foreign_key = “fk_id”
has_many :things, :through => :joinings, :source => :other

Please look at the examples on my blog. I don’t want to repeat myself
here.


Josh S.
http://blog.hasmanythrough.com

Josh,

Thank you. That was a major piece of information that I didn’t have
before. And, believe it or not, I read two of your blog entries
(dance-off and one other) end to end :slight_smile: before I ever posted.

Does using symbols vs. strings really matter when setting the values of
the hash parameters on the way into these methods? Is :through =>
:join_table going to work differently than :through => ‘join_table’?

I have some questions about whether this approach buys you much over the
HABTM approach which I will pose in a separate thread.

Thanks again,
Wes

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs