Query Object

Purpose

Query objects encapsulate complex database queries that do not belong in a model scope.

Use this template when a query involves multiple conditions, join logic or aggregation that would overly bloat the model.

Template

# app*queries*QUERY_NAME.rb
class QUERY_NAME
  def initialize(relation = Model.all)
    @relation = relation
  end

  def call(params = {})
    # Chain scopes and conditions
    # scope = @relation
    # scope = scope.where(active: true) if params[:active_only]
    # scope = scope.includes(:association) if params[:include_association]
    # scope
  end

  private

  attr_reader :relation
end

Usage

# In a controller or service
query = QUERY_NAME.new
results = query.call(active_only: true)

# With a specific starting relation
relation = Model.where(tenant: current_tenant)
query = QUERY_NAME.new(relation)
results = query.call

Related Documents