module FetcheableOnApi::Filterable
Filterable
implements `filter` parameter support.
Constants
- PREDICATES_WITH_ARRAY
Predicates supported for filtering.
Public Class Methods
included(base)
click to toggle source
Public class methods
# File lib/fetcheable_on_api/filterable.rb, line 35 def self.included(base) base.class_eval do extend ClassMethods class_attribute :filters_configuration, instance_writer: false self.filters_configuration = {} end end
Protected Instance Methods
apply_filters(collection)
click to toggle source
# File lib/fetcheable_on_api/filterable.rb, line 101 def apply_filters(collection) return collection if params[:filter].blank? foa_valid_parameters!(:filter) filter_params = params.require(:filter) .permit(valid_keys) .to_hash filtering = filter_params.map do |column, values| config = filters_configuration[column.to_sym] format = config.fetch(:format, :string) column_name = config.fetch(:as, column) klass = config.fetch(:class_name, collection.klass) collection_klass = collection.name.constantize association_class_or_name = config.fetch( :association, klass.table_name.to_sym ) predicate = config.fetch(:with, :ilike) if collection_klass != klass collection = collection.joins(association_class_or_name) end if %i[between not_between].include?(predicate) if values.is_a?(String) predicates(predicate, collection, klass, column_name, values.split(",")) else values.map do |value| predicates(predicate, collection, klass, column_name, value.split(",")) end.inject(:or) end elsif values.is_a?(String) values.split(",").map do |value| predicates(predicate, collection, klass, column_name, value) end.inject(:or) else values.map! { |el| el.split(",") } predicates(predicate, collection, klass, column_name, values) end end collection.where(filtering.flatten.compact.inject(:and)) end
foa_default_permitted_types()
click to toggle source
Types allowed by default for filter action.
# File lib/fetcheable_on_api/filterable.rb, line 240 def foa_default_permitted_types [ActionController::Parameters, Hash, Array] end
predicates(predicate, collection, klass, column_name, value)
click to toggle source
Apply arel predicate on collection
# File lib/fetcheable_on_api/filterable.rb, line 149 def predicates(predicate, collection, klass, column_name, value) case predicate when :between klass.arel_table[column_name].between(value.first..value.last) when :does_not_match klass.arel_table[column_name].does_not_match("%#{value}%") when :does_not_match_all klass.arel_table[column_name].does_not_match_all(value) when :does_not_match_any klass.arel_table[column_name].does_not_match_any(value) when :eq klass.arel_table[column_name].eq(value) when :eq_all klass.arel_table[column_name].eq_all(value) when :eq_any klass.arel_table[column_name].eq_any(value) when :gt klass.arel_table[column_name].gt(value) when :gt_all klass.arel_table[column_name].gt_all(value) when :gt_any klass.arel_table[column_name].gt_any(value) when :gteq klass.arel_table[column_name].gteq(value) when :gteq_all klass.arel_table[column_name].gteq_all(value) when :gteq_any klass.arel_table[column_name].gteq_any(value) when :in if value.is_a?(Array) klass.arel_table[column_name].in(value.flatten.compact.uniq) else klass.arel_table[column_name].in(value) end when :in_all if value.is_a?(Array) klass.arel_table[column_name].in_all(value.flatten.compact.uniq) else klass.arel_table[column_name].in_all(value) end when :in_any if value.is_a?(Array) klass.arel_table[column_name].in_any(value.flatten.compact.uniq) else klass.arel_table[column_name].in_any(value) end when :lt klass.arel_table[column_name].lt(value) when :lt_all klass.arel_table[column_name].lt_all(value) when :lt_any klass.arel_table[column_name].lt_any(value) when :lteq klass.arel_table[column_name].lteq(value) when :lteq_all klass.arel_table[column_name].lteq_all(value) when :lteq_any klass.arel_table[column_name].lteq_any(value) when :ilike klass.arel_table[column_name].matches("%#{value}%") when :matches klass.arel_table[column_name].matches(value) when :matches_all klass.arel_table[column_name].matches_all(value) when :matches_any klass.arel_table[column_name].matches_any(value) when :not_between klass.arel_table[column_name].not_between(value.first..value.last) when :not_eq klass.arel_table[column_name].not_eq(value) when :not_eq_all klass.arel_table[column_name].not_eq_all(value) when :not_eq_any klass.arel_table[column_name].not_eq_any(value) when :not_in klass.arel_table[column_name].not_in(value) when :not_in_all klass.arel_table[column_name].not_in_all(value) when :not_in_any klass.arel_table[column_name].not_in_any(value) else unless predicate.respond_to?(:call) raise ArgumentError, "unsupported predicate `#{predicate}`" end predicate.call(collection, value) end end
valid_keys()
click to toggle source
Protected instance methods
# File lib/fetcheable_on_api/filterable.rb, line 81 def valid_keys keys = filters_configuration.keys keys.each_with_index do |key, index| predicate = filters_configuration[key.to_sym].fetch(:with, :ilike) if(%i[between not_between in in_all in_any].include?(predicate)) format = filters_configuration[key.to_sym].fetch(:format) { nil } keys[index] = {key => []} if format == :array next end next if predicate.respond_to?(:call) || PREDICATES_WITH_ARRAY.exclude?(predicate.to_sym) keys[index] = {key => []} end keys end