Has_many :through

first, the models:

class Listing < ActiveRecord::Base
has_many :keyword_links
has_many :keywords, :through => :keyword_links, :conditions => "active

1"
end

class Keyword < ActiveRecord::Base
has_many :keyword_links
has_many :listings, :through => :keyword_links, :conditions => "active

1"
end

class KeywordLink < ActiveRecord::Base
belongs_to :keyword
belongs_to :listing
end

the problem is, when i loop through all the @listing.keywords, I get ALL
the
keyword_links instead of just the keyword_links for that listing. For
instance, if my @listing has an ID of 7, I’ll still have
keyword_listings
with 'listing_id’s of 2, 3, etc.

i notice (in the logs) when I loop through @listing.keywords and access
keyword_link, AR makes a query of
SELECT count(*) AS count_all FROM keyword_links WHERE
(keyword_links.keyword_id = 13)

obviously missing the listing_id part of the WHERE.

what am I missing to make this happen?

thank you,
ed

Looking at your models, I wonder if what you really need is
has_and_belongs_to_many.

Something like:

class Listing < ActiveRecord::Base
has_and_belongs_to_many :keywords, :join_table => “keyword_links”,
:conditions => “active = 1”
end

class Keyword < ActiveRecord::Base
has_and_belongs_to_many :listings, :join_table => :keyword_links,
:conditions => “active = 1”
end

Page 239-241 of Agile Web D. With Rails describes this.

Julian

thank you for the response. i should have given more info. the reason
I
went with :through instead of HABTM is that my keyword_links table has
data
i need to access…it’s not just a simple join table. ie:

CREATE TABLE keyword_links (
id int(10) unsigned NOT NULL auto_increment,
listing_id int(10) unsigned NOT NULL default ‘0’,
keyword_id int(10) unsigned NOT NULL default ‘0’,
active tinyint(1) NOT NULL default ‘1’,
max_bid decimal(6,2) NOT NULL default ‘0.00’,
url text NOT NULL,
impressions int(10) unsigned NOT NULL default ‘0’,
modified_on datetime default NULL,
created_on datetime default NULL,
PRIMARY KEY (id)
)

i used through so i could access those columns (max_bid, impressions,
etc).

any thoughts on why it’s pulling back all the keyword_links instead of
just
that listing’s?

ed

I think what is happening is this.

@listing.keywords returns an array of the keywords associated with the
listing. If you then apply .keyword_links to each of those keywords,
ActiveRecord does just that. It returns an array of the keyword_links
associated with each keyword. Although only looking at each keyword
associated with the listing, it grabs every single keyword_link that the
keyword is linked to.

So, if at present you are doing something like:

@listing.keywords.each{|k| do_something(k.keyword_links) }

You could instead do:

@listing.keywords.each{|k| do_something(k.keyword_links.find(:all,
:conditions => [“listing_id = ?”, @listing.id]) }

This will put the listing_id condition into the WHERE.

Julian

that makes sense. and it works!

thanks a lot Julian - you rock.

ed