Class: EasyFilters::ModelFilter

Inherits:
Filter
  • Object
show all
Defined in:
lib/easy_filters/model_filter.rb

Overview

Base class for ActiveRecord-bound filter classes. Subclasses must implement the #model method and optionally add custom filtering methods, as explained below in the #apply_to method.

Instance Method Summary collapse

Methods inherited from Filter

#[], #[]=, #any?, #clear!, defaults, global_key, #initialize, #key, key, #persist!, #sanitize, #values, #values=

Constructor Details

This class inherits a constructor from EasyFilters::Filter

Instance Method Details

#allObject

Get all the matching records to the current filter criteria.



13
14
15
16
# File 'lib/easy_filters/model_filter.rb', line 13

def all
  matches = model.send(scope)
  matches = apply_to matches
end

#apply_to(matches) ⇒ Object

Applies the filter criteria specified for the different fields to :matches, an ActiveRecordRelation which should start by matching all the “filterable” records.

Each field will be processed in the following way:

  1. Check if self responds to a custom filter method of the form: “filter_by_<FIELD_NAME>”. If it does, delegate the filtering of records by that field to the method. Such a method must return the updated ActiveRecordRelation. For instance, if the field name is “slug”, its custom filter method will be named “filter_by_slug”:

    def filter_by_slug(partial, value)
      partial.where(slug: value)
    end
    
  2. If no custom filter method is available for the field, check for a default filter method by the class of the value. Supported classes out-of-the-box are:

    • String: Will search with a ‘like “%value%”’.

  3. Otherwise, leave the logic up to ActiveRecord. Will add a where constraint like follows:

    partial.where(field.to_sym => value)
    


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/easy_filters/model_filter.rb', line 47

def apply_to(matches)
  values.inject(matches) do |partial, pair|
    field, value = pair
    unless value.blank?
      type = value.class.name.downcase
      custom_filter_method = "filter_by_#{field}"
      default_filter_method = "filter_#{type}_field"
      if self.respond_to? custom_filter_method
        # Custom filtering
        partial = self.send custom_filter_method, partial, value
      elsif self.respond_to? default_filter_method
        # Default method filtering
        partial = self.send default_filter_method, partial, field, value
      else
        # Leave it up to AR and its magic
        partial = partial.where(field.to_sym => value)
      end
    end

    partial
  end
end

#filter_string_field(partial, field, value) ⇒ Object

Filters String fields using LIKE.



71
72
73
# File 'lib/easy_filters/model_filter.rb', line 71

def filter_string_field(partial, field, value)
  partial.where("#{field} like ?", "%#{value}%")
end

#modelObject

Get the model class to which the filters will be applied. This method must be overridden in subclasses.

Raises:

  • (NotImplementedError)


8
9
10
# File 'lib/easy_filters/model_filter.rb', line 8

def model
  raise NotImplementedError
end

#scopeObject

Get the scope that will start the filter criteria as a symbol. The default scope is :all.



20
21
22
# File 'lib/easy_filters/model_filter.rb', line 20

def scope
  :all
end