Module: Warped::Controllers::Filterable

Extended by:
ActiveSupport::Concern
Included in:
Ui, Tabulatable
Defined in:
lib/warped/controllers/filterable.rb,
lib/warped/controllers/filterable/ui.rb

Overview

Provides functionality for filtering records from an ActiveRecord::Relation in a controller.

Example usage:

class UsersController < ApplicationController
  include Filterable

  filterable_by :name, :created_at, 'accounts.kind'

  def index
    scope = filter(User.joins(:account))
    render json: scope
  end
end

Example requests:

GET /users?name=John
GET /users?created_at=2020-01-01
GET /users?accounts.kind=premium
GET /users?accounts.kind=premium&accounts.kind.rel=neq

Filters can be combined:

GET /users?name=John&created_at=2020-01-01

Renaming filter keys:

In some cases, you may not want to expose the actual column names to the client. In such cases, you can rename the filter keys by passing a hash to the filterable_by method.

Example:

class UsersController < ApplicationController
  include Filterable

  filterable_by :name, :created_at, 'accounts.kind' => 'kind'

  def index
    scope = filter(User.joins(:account))
    render json: scope
  end
end

Example requests:

GET /users?kind=premium

Using relations:

In some cases, you may want to filter records based on a relation. For example, you may want to filter users based on operands like:

  • greater than

  • less than

  • not equal

To see the full list of operands, check the Warped::Queries::Filter::RELATIONS constant.

To use the operands, you must pass a parameter appended with ‘.rel`, and the value of a valid operand.

Example requests:

GET /users?created_at=2020-01-01&created_at.rel=gt
GET /users?created_at=2020-01-01&created_at.rel=lt
GET /users?created_at=2020-01-01&created_at.rel=neq

When the operand relation requires multiple values, like in, not_in, or between, you can pass an array of values.

Example requests:

GET /users?created_at[]=2020-01-01&created_at[]=2020-01-03&created_at.rel=in
GET /users?created_at[]=2020-01-01&created_at[]=2020-01-03&created_at.rel=between

Defined Under Namespace

Modules: Ui

Instance Method Summary collapse

Instance Method Details

#filter(scope, filter_conditions: filter_conditions(*filter_fields, *mapped_filter_fields)) ⇒ ActiveRecord::Relation

Parameters:

  • scope (ActiveRecord::Relation)
  • filter_conditions (Array<Hash>) (defaults to: filter_conditions(*filter_fields, *mapped_filter_fields))

Options Hash (filter_conditions:):

  • :field (Symbol, String)
  • :value (String, Integer, Array<String,Integer>)
  • :relation (String)

Returns:

  • (ActiveRecord::Relation)


100
101
102
# File 'lib/warped/controllers/filterable.rb', line 100

def filter(scope, filter_conditions: filter_conditions(*filter_fields, *mapped_filter_fields))
  Warped::Queries::Filter.call(scope, filter_conditions:)
end

#filter_conditions(*fields) ⇒ Array<Hash>

Parameters:

  • fields (Array<Symbol,String>)

Returns:

  • (Array<Hash>)


106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/warped/controllers/filterable.rb', line 106

def filter_conditions(*fields)
  fields.filter_map do |filter_opt|
    field = filter_name(filter_opt)

    next if filter_value(filter_opt).blank? && %w[is_null is_not_null].exclude?(filter_rel_value(filter_opt))

    {
      field:,
      value: filter_value(filter_opt),
      relation: filter_rel_value(filter_opt).presence || (filter_value(filter_opt).is_a?(Array) ? "in" : "eq")
    }
  end
end

#filterable_byObject



120
121
122
# File 'lib/warped/controllers/filterable.rb', line 120

def filterable_by
  @filterable_by ||= self.class.filter_fields.concat(self.class.mapped_filter_fields)
end