0

I have two models, Item and Tag, that have a many-to-many relationship through a model called ItemTag. I want the user to be able to find all items that have ALL of a given set of tags.tag_name. So, the tables look like this:


items

id

...


items_tags

id

item_id

tag_id

...


tags

id

tag_name

...

Suppose I have the following item / tag_name combinations in the db (though the items_tags join table)

item 1: "red", "yellow", "blue"

item 2: "red", "yellow", "orange"

item 3: "red", "orange", "purple"

The user wants to get all Items that are associated with Tag.tag_names "red" and "yellow" (which obviously should return item 1 and item 2). How do I construct this in Rails3? My assumption is that the SQL statement needs to:

1: join items_tags and tags, obtaining all of the items_tags rows that are associated with the tag that has tag_name "red"

2: join that result set again with the tags table, narrowing the result set to those rows associated with the tag with tag_name "yellow"

3: join items with the final result set to get the list of items associated with both tags

Note that the number of tag_names selected is arbitrary. The user may select 1..n tag_names as the criteria, so I need to be able to construct this query dynamically, preferably without having to use raw SQL.

J Plato
  • 888
  • 1
  • 8
  • 17

1 Answers1

0

First you need to set the association in the models.

Items

has_many :item_tags
has_many :tags, :through => item_tags

Item_tags

belongs_to :item
belongs_to :tag

Tags

has_many :item_tags
has_many :items, :through => item_tags

Then in your controller you can do this:

red_tag_items = Tag.find_by_name('red').items
yellow_tag_items = Tag.find_by_name('yellow').items

red_yellow_tag_items = red_tag_items & yellow_tag_items

There must be more efficient ways to do this. Would love to find out. :)