In this article, we learned about another Ruby On Rails Design Pattern – Query Object

design-pattern

Rails Query Object is a type of design pattern that lets us fetch query logic from Controllers and Models into reusable classes.
While this article is written with Ruby On Rails in mind, it easily applies to other frameworks, especially MVC based and applying ActiveRecord pattern.

Let’s have a look at the below example

We want to request a list of posts with the type “video” that has a view count greater than 1000 and that the current user can access.

Class PostController < ApplicationController 
  def index @posts = Post.accessible_by(current_ability) 
                         .where(type: :video) 
                         .where('view_count > ?',1000)
  end
end

The problems in the above code:
1) This code isn’t reusable
2) It’s hard to test the logic.
3) Any changes to the post schema can break this logic/code.

To make the controller light wight, readable, and neat we can use scopes

Class Post < ApplicationRecord 
  scope :video_type, -> { where(type: :video) }
  scope :popular, -> { where ('view_count > ?',1000) }
  scope :popular_video_type, -> { popular.video_type }
end

So, the controller will look like that:

Class PostController < ApplicationController
  def index
    @posts = Post.accessible_by(current_ability)
                 .popular_video_type
  end
end

But still, it is not an appropriate solution; here we need to create scopes for every query condition we want to add, we are also increasing the code in the Model with various combinations of scope for diverse use cases.

To solve this kind of problem, we use the Rails Query Object:

video_query.rb

Class VideoQuery
  def call(ability)
    ability
     .where(type: :video)
     .where('view_count > ?', 1000)
  end
end

post_controller.rb

Class PostController < ApplicationController
  def index
    ability   = Post.accessible_by(current_ability)
    @articles = VideoQuery.new.call(ability)
  end
end

Now, it’s reusable! We can use this class to query any other models that have a similar scheme.

Conclusion

A query object is a simple, easily testable pattern that helps in abstracting queries, relations and scope chains with complex implementation.

In the next blog, We will learn about the Decorators Design Pattern.
The decorator is a design pattern that allows the behavior to be added to an object, dynamically, without disturbing the behavior of other objects of the same class

You can read about Ruby On Rails Design Pattern at https://runwithcode.blogspot.com/2020/04/design-patterns-in-ruby-on-rails.html
Thanks For Reading …

Leave a Reply

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