Associations Ruby on Rails

Rails belongs_to association: queries refactoring

Rails belongs_to association: queries refactoring January 2, 20187 Comments
Rails belongs_to association: queries refactoring

Since belongs_to relation is one of the most common association in each Rails application I bet that you deal with it many times in your application. Let’s say that we have two models: Job and Category – one job belongs to one category and category can have many jobs, simple as that.

Category model has published:boolean attribute which determines if we can show jobs for given category. Our goal is to create a query that would return only jobs assigned to published categories.

Standard way

Usually we would use something like this:

Job.joins(:category).where(categries: {published: true})

What is wrong with the above example? Nothing, but let’s focus on logic isolation. When we are operating on `Job` model we shouldn’t care about conditions that we have to meet in order to fetch only published categories – it’s `Category` model related logic so let’s move it there.

Logic isolation

class Category < ActiveRecord::Base
 has_many :jobs
      
  def self.publishable
    where(published: true)
  end
end

You can use scope instead of class method - I described it here [link to the article about scope vs class method]. I decided to go for the class method as it’s clear to me. Let’s take a look at the `Job` model now:

class Job < ActiveRecord::Base
  belongs_to :category
      
  def self.publishable
    joins(:category).merge(Category.publishable)
  end
end

so we can now call

Job.publishable

Why

You are probably wondering why the second solution is better when there is a lot more code to maintain. Here is why:

1. Logic is isolated. Category related stuff is in Category model, the same for job-related stuff. Your teammates can just call Job.publishable without digging into logic and wondering what query they should exactly use
2. Imagine that you have the first version of the query, Job.joins(:category).where(categries: {published: true}), in many places of the app. What do you do when to determine if the category is published you have to check more conditions? You have to find all places where you used it - poorly. But when you use the second version all you need to do is to change on method. You didn’t change anything else.
3. It’s just more readable for human beings - it’s very important when you have junior developers in your team
4. You can use Category.published everywhere with any model associated with Category

Having problems with refactory or Ruby on Rails?

Hit me on twitter or use contact form and let me know how can I help you!

Image source: pexels.com

Download free RSpec & TDD ebook

Do you want to earn more or jump to the next level in your company? Do you know that testing skills are one of the most desired skills? There is only first step: start testing and do it right. My ebook can help you. Subscribe to the newsletter to get a free copy of the book.

7 comments

    1. You’re right but it’s a nice way to keep things clean 🙂 Are there any other patterns that you are using to isolate query logic?

Leave a Reply

Your email address will not be published. Required fields are marked *