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' => { alias_name: '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
Setting types and casting: By default, the filter values are cast to strings. If you want to cast the values to a specific type, and validate that the values are of the correct type, you can pass the kind of the filter to the filterable_by
method.
Example:
class UsersController < ApplicationController
include Filterable
filterable_by :name, :created_at, 'accounts.active' => { kind: :integer, alias_name: 'active' }
def index
scope = filter(User.joins(:account))
render json: scope
end
end
Example requests:
GET /users?active=1
The kind
parameter will be cast to an integer. If the value is not an integer, an error will be raised, and the response will be a 400 Bad Request.
In order to change the error message, you can rescue from the Filter::ValueError
exception, or override the render_invalid_filter_value
method.
def render_invalid_filter_value(exception)
render action_name, status: :bad_request
end
Defined Under Namespace
Modules: Ui
Instance Method Summary collapse
- #current_action_filter_values ⇒ Array<Warped::Filter::Base::Value>
- #current_action_filters ⇒ Array<Warped::Filter::Base>
- #filter(scope, filter_conditions: nil) ⇒ ActiveRecord::Relation
- #parse_filter_params ⇒ Array<Hash>
Instance Method Details
#current_action_filter_values ⇒ Array<Warped::Filter::Base::Value>
173 174 175 |
# File 'lib/warped/controllers/filterable.rb', line 173 def current_action_filter_values @current_action_filter_values ||= [] end |
#current_action_filters ⇒ Array<Warped::Filter::Base>
168 169 170 |
# File 'lib/warped/controllers/filterable.rb', line 168 def current_action_filters @current_action_filters ||= [] end |
#filter(scope, filter_conditions: nil) ⇒ ActiveRecord::Relation
145 146 147 148 149 150 151 |
# File 'lib/warped/controllers/filterable.rb', line 145 def filter(scope, filter_conditions: nil) action_filters = filter_conditions.presence || filters @current_action_filters = action_filters @current_action_filter_values = parse_filter_params Warped::Queries::Filter.call(scope, filter_conditions: current_action_filter_values.map(&:to_h)) end |
#parse_filter_params ⇒ Array<Hash>
154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/warped/controllers/filterable.rb', line 154 def parse_filter_params current_action_filters.filter_map do |filter| raw_value = params[filter.parameter_name] raw_relation = params["#{filter.parameter_name}.rel"] filter_value = filter.class::Value.new(filter, raw_relation.presence || "eq", raw_value.presence) next if filter_value.empty? filter_value end end |