0

In Rails 4, I have a project in which I've set up three models with the following many-to-many relationships:

  • An Item
    • has_and_belongs_to_many categories
    • has_and_belongs_to_many tags
  • A Category
    • has_and_belongs_to_many items
  • A Tag
    • has_and_belongs_to_many items

And while it's easy to select an Item and automatically get all associated categories and tags, there are some situations in which I'd want to select items AND their associated categories, but NOT their tags. In these cases, I'd like to avoid doing extra database joins against the Tags table and ItemsTags join table. Can anyone help me with the correct find syntax to only join Items to categories? (Side note: I'm also planning on adding 10 additional many-to-many relationships between items and other models, but I'm just simplifying the scenario for this question. In the end, I'm trying to avoid doing a join with an excessive number of tables whenever I can.)

Thanks!

hithere
  • 520
  • 4
  • 17

1 Answers1

0

Rails will by default not load associated records unless you request it

Item.all will only fetch record from 'items' table

Then later in your code if you call item.categories that's the point when a query is performed to fetch all categories of this particular item. If you never call item.tags then the query to 'tags' table is never executed and the records are not fetch. Bottom line is: you can have as many associations as needed, as long as you don't explicitly call them they won't be loaded.

Side note about performance, rails offer several ways to join and include associated tables:

Item.include(:category).all Will trigger only 2 queries to fetch all items, and all associated categories.

Item.include(:category).joins(:category).all -> will trigger only 1 query joining the items and categories tables (but it may be slower than 2 requests)

So you have all control over what's loaded from the database. Those can apply for scope as well.

Benjamin Bouchet
  • 12,971
  • 2
  • 41
  • 73
  • Thank you! I didn't realize that was happening behind the scenes (on-the-fly retrieval, as needed). Your .include() examples were exactly what I was looking for. Really appreciate the help! I'll give this a try! – hithere Jul 23 '13 at 01:48
  • More info http://guides.rubyonrails.org/association_basics.html and http://guides.rubyonrails.org/active_record_querying.html Search also for leazy loading and eager loading on google, thats what you are looking for – Benjamin Bouchet Jul 23 '13 at 01:59
  • @ Benjamin - sorry for the delay. Got held up and didn't get the chance to try this right away. Thanks for the help! – hithere Jul 26 '13 at 19:30