module DataFilter::FilterSet::DSL

A DSL for creating a series of filters that can be called

Provides a cleaner way to define a {DataFilter::FilterSet} with a bunch of different filters

Conditionally adds filters to the set based on whether or not any valid search terms are provided (useful for Controller params)

@example Office365::Mail::MessagesController

filter_set = DataFilter::FilterSet.create do
  like_filter :to,        by: params[:to]
  like_filter :from,      by: params[:from]
  like_filter :cc,        by: params[:cc]
  like_filter :bcc,       by: params[:bcc]
  like_filter :subject,   by: params[:subject]

  keyword_filter [:to, :from, :cc, :bcc, :subject], by: params[:keyword]

  range_filter :date, floor: start_date, ceiling: end_date

  if params[:has_attachment] === true
    range_filter :attachment_count, floor: 1
  elsif params[:has_attachment] === false
    range_filter :attachment_count, ceiling: 0, nil_default: 0
  end
end

Public Class Methods

included(base) click to toggle source
# File lib/data_filter/filter_set.rb, line 68
def self.included(base)
  base.extend(ClassMethods)
end

Public Instance Methods

keyword_filter(field_syms, opts = {}) click to toggle source

Adds a {DataFilter::KeywordFilter} to the filter set

@param field_syms [Array<Symbol>] a collection of all of the data

methods we want to inspect when filtering

@option opts [Object] :by the value we want to use when filtering

the data item
# File lib/data_filter/filter_set.rb, line 120
def keyword_filter(field_syms, opts = {})
  if opts[:by]
    @filters << KeywordFilter.new(field_syms, opts[:by])
  end
end
like_filter(field_sym, opts = {}) click to toggle source

Adds a {DataFilter::LikeFilter} to the filter set

@param field_sym [Symbol] name of the data method we want

to filter

@option opts [Object] :by the value we want to use when

filtering the data item, :normalize_regex the regular
expression used to normalize the string
# File lib/data_filter/filter_set.rb, line 96
def like_filter(field_sym, opts = {})
  if opts[:by]
    @filters << LikeFilter.new(field_sym, opts[:by], opts[:normalize_regex])
  end
end
method_missing(sym, *args, &block) click to toggle source

Used to support the DSL. Calls out to the parent scope if we receive a message we can't respond to

# File lib/data_filter/filter_set.rb, line 177
def method_missing(sym, *args, &block)
  @original_self.send(sym, *args, &block)
end
prefix_filter(field_sym, opts = {}) click to toggle source

Adds a {DataFilter::PrefixFilter} to the filter set

@param field_sym [Symbol] name of the data method we want

to filter

@option opts [Object] :by the value we want to use when

filtering the data item
# File lib/data_filter/filter_set.rb, line 108
def prefix_filter(field_sym, opts = {})
  if opts[:by]
    @filters << PrefixFilter.new(field_sym, opts[:by])
  end
end
range_filter(field_sym, opts = {}) click to toggle source

Adds a {DataFilter::RangeFilter} to the filter set

@param field_sym [Symbol] name of the data method we want to

filter

@option opts [Comparable] :floor the range beginning we want to

filter the data item by

@option opts [Comparable] :ceiling the range end we want to filter

the data item by

@option opts [Comparable] :nil_default the value to use if the

data item has no field value
# File lib/data_filter/filter_set.rb, line 136
def range_filter(field_sym, opts = {})
  if opts[:floor] || opts[:ceiling]
    @filters << RangeFilter.new(field_sym, **opts)
  end
end
range_overlap_filter(start_sym, end_sym, opts = {}) click to toggle source

Adds a {DataFilter::RangeOverlapFilter} to the filter set

@param start_sym [Symbol] name of the start field we want to

filter

@param end_sym [Symbol] name of the end field we want to

filter

@option opts [Comparable] :floor the range beginning we want to

filter the data item by

@option opts [Comparable] :ceiling the range end we want to filter

the data item by

@option opts [Comparable] :nil_default the value to use if the

data item has no field value
# File lib/data_filter/filter_set.rb, line 154
def range_overlap_filter(start_sym, end_sym, opts = {})
  if opts[:floor] || opts[:ceiling]
    @filters << RangeOverlapFilter.new(start_sym, end_sym, **opts)
  end
end
respond_to_missing?(sym, include_all = false) click to toggle source

Used to support the DSL. Calls out to the parent scope if we receive a message we can't respond to

# File lib/data_filter/filter_set.rb, line 183
def respond_to_missing?(sym, include_all = false)
  @original_self.respond_to?(sym, include_all)
end
truthy_filter(field_sym, match: nil) click to toggle source

Adds a {DataFilter::TruthyFilter} to the filter set

@param field_sym [Symbol] name of the field to match on @param match [Object] truthy/falsey value to use to determine whether

the filter should match/filter truthy fields or falsey fields
# File lib/data_filter/filter_set.rb, line 165
def truthy_filter(field_sym, match: nil)
  # Skip filter if match is not specified
  return if match.nil?
  if is_falsey?(match)
    @filters << TruthyFilter.new(field_sym, invert: true)
  else
    @filters << TruthyFilter.new(field_sym)
  end
end

Private Instance Methods

is_falsey?(val) click to toggle source

TODO DRY up

# File lib/data_filter/filter_set.rb, line 191
def is_falsey?(val)
  [false, 'false'].include?(val)
end