rubyprince
rubyprince

Reputation: 17803

Which is preferred, :includes or :joins?

I have a model Product and it belongs to a Category (category_id in products table). I want to write a query which takes the first 20 products with its category name. I have 2 ways of fetching it:

  1. Use includes, like this:

    Product.includes(:category).
            order(:updated_at).
            limit(20)
    

    and take the category name in the views like this:

    <%= product.category.name if product.category %>
    

    This will create query like this:

    SELECT `products`.* from `products` ORDER BY `products`.updated_at LIMIT 20
    SELECT `categories`.* from `categories` WHERE `categories`.id IN (1,2,3,4,5..,25)
    
  2. Use joins like this:

    Product.joins("LEFT JOIN categories ON categories.id = products.category_id").
            select("products.*, categories.name as category_name").
            order(:updated_at).
            limit(20)
    

    and use it in views like this:

    <%= product.category_name %>
    

    This will generate query like this:

    SELECT products.*, categories.name as category_name from `products` LEFT JOIN categories ON categories.id = products.category_id ORDER BY `products`.updated_at LIMIT 20
    

Method 1 has the advantage that we would be able to use model level methods written on Category model and the code is more maintainable. But it has the downside that it uses a separate query for finding the categories which uses IN clause.

Which is the preferred way?

Upvotes: 1

Views: 253

Answers (3)

tsherif
tsherif

Reputation: 11710

For your example, I might go with option 1 because it's simpler and easier to read and you're not loading that many objects so I don't think the performance hit will be too severe.

In a case where you would might be loading more data, (e.g. if you took off the limit(20) part), I would go with option 2 because it saves you from instantiating the Category objects when all you need is their names. In smaller lists, this overhead might be negligible, but as the list gets long it can become significant.

Upvotes: 0

fregas
fregas

Reputation: 3260

Its not mere preference, its a matter of performance vs. maintainability. I would go the more maintainable route for your queries first. If your performance starts to suffer for certain queries, optimize by using the join syntax or just writing plain old sql from scratch. Don't prematurely optimize. Optimize where you find an actual need.

Upvotes: 2

Azolo
Azolo

Reputation: 4383

The preferred way is which ever way you personally prefer.

In all honesty though, I don't see that using an includes is that big of a deal. Especially in development of an app where what you're putting on the page is going to change.

In my opinion, just use includes most of the time in that situation. Unless you're storing a lot of text in your rows or you get to production and that query ends up being a bottle neck, then you should probably take the time and optimize it.

Upvotes: 0

Related Questions