class ActiveInteraction::Filter

Describes an input filter for an interaction.

Constants

CLASSES

@return [Hash{Symbol => Class}]

Attributes

slug[R]

@return [Symbol]

filters[R]

@return [Hash{Symbol => Filter}]

name[R]

@return [Symbol]

options[R]

@return [Hash{Symbol => Object}]

Public Class Methods

factory(slug) click to toggle source

Get the filter associated with a symbol.

@example

ActiveInteraction::Filter.factory(:boolean)
# => ActiveInteraction::BooleanFilter

@example

ActiveInteraction::Filter.factory(:invalid)
# => ActiveInteraction::MissingFilterError: :invalid

@param slug [Symbol]

@return [Class]

@raise [MissingFilterError] If the slug doesn’t map to a filter.

@see .slug

# File lib/active_interaction/filter.rb, line 50
def factory(slug)
  CLASSES.fetch(slug) { raise MissingFilterError, slug.inspect }
end
new(name, options = {}, &block) click to toggle source

@param name [Symbol] @param options [Hash{Symbol => Object}]

@option options [Object] :default Fallback value to use when given ‘nil`.

# File lib/active_interaction/filter.rb, line 68
def initialize(name, options = {}, &block)
  @name = name
  @options = options.dup
  @filters = {}

  instance_eval(&block) if block_given?
end

Private Class Methods

register(slug) click to toggle source

@param slug [Symbol]

@return [Class]

# File lib/active_interaction/filter.rb, line 59
def register(slug)
  CLASSES[@slug = slug] = self
end

Public Instance Methods

accepts_grouped_inputs?() click to toggle source

Tells whether or not the filter accepts a group of parameters to form a single input.

@example

ActiveInteraction::TimeFilter.new(Time.now).accepts_grouped_inputs?
# => true

@example

ActiveInteraction::Filter.new(:example).accepts_grouped_inputs?
# => false

@return [Boolean]

# File lib/active_interaction/filter.rb, line 183
def accepts_grouped_inputs?
  false
end
database_column_type() click to toggle source

Gets the type of database column that would represent the filter data.

@example

ActiveInteraction::TimeFilter.new(Time.now).database_column_type
# => :datetime

@example

ActiveInteraction::Filter.new(:example).database_column_type
# => :string

@return [Symbol] A database column type. If no sensible mapping exists,

returns `:string`.
# File lib/active_interaction/filter.rb, line 168
def database_column_type
  :string
end
default(context = nil) click to toggle source

Get the default value.

@example

ActiveInteraction::Filter.new(:example).default
# => ActiveInteraction::NoDefaultError: example

@example

ActiveInteraction::Filter.new(:example, default: nil).default
# => nil

@example

ActiveInteraction::Filter.new(:example, default: 0).default
# => ActiveInteraction::InvalidDefaultError: example: 0

@param context [Base, nil]

@return [Object]

@raise [NoDefaultError] If the default is missing. @raise [InvalidDefaultError] If the default is invalid.

# File lib/active_interaction/filter.rb, line 114
def default(context = nil)
  raise NoDefaultError, name unless default?

  value = raw_default(context)
  raise InvalidDefaultError, "#{name}: #{value.inspect}" if value.is_a?(GroupedInput)

  if value.nil?
    nil
  else
    default = process(value, context)
    if default.errors.any? && default.errors.first.is_a?(Filter::Error)
      raise InvalidDefaultError, "#{name}: #{value.inspect}"
    end

    default.value
  end
end
default?() click to toggle source

Tells if this filter has a default value.

@example

ActiveInteraction::Filter.new(:example).default?
# => false

@example

ActiveInteraction::Filter.new(:example, default: nil).default?
# => true

@return [Boolean]

# File lib/active_interaction/filter.rb, line 153
def default?
  options.key?(:default)
end
desc() click to toggle source

Get the description.

@example

ActiveInteraction::Filter.new(:example, desc: 'Description!').desc
# => "Description!"

@return [String, nil]

# File lib/active_interaction/filter.rb, line 139
def desc
  options[:desc]
end
process(value, context) click to toggle source

Processes the input through the filter and returns a variety of data

about the input.

@example

input = ActiveInteraction::Filter.new(:example, default: nil).process(nil, nil)
input.value
# => nil

@param value [Object] @param context [Base, nil]

@return [Input, ArrayInput, HashInput]

@raise (see default)

# File lib/active_interaction/filter.rb, line 90
def process(value, context)
  value, error = cast(value, context)

  Input.new(self, value: value, error: error)
end

Private Instance Methods

adjust_output(value, _context) click to toggle source
# File lib/active_interaction/filter.rb, line 214
def adjust_output(value, _context)
  value
end
cast(value, context, convertize: true, reconstantize: true) click to toggle source

rubocop:disable Metrics/PerceivedComplexity

# File lib/active_interaction/filter.rb, line 190
def cast(value, context, convertize: true, reconstantize: true)
  if matches?(value)
    [adjust_output(value, context), nil]
  elsif value == nil # rubocop:disable Style/NilComparison - BasicObject does not have `nil?`
    default? ? [default(context), nil] : [value, Filter::Error.new(self, :missing)]
  elsif reconstantize
    send(__method__, value, context, convertize: convertize, reconstantize: false)
  elsif convertize
    value, error = convert(value)
    if error
      [value, error]
    else
      send(__method__, value, context, convertize: false, reconstantize: reconstantize)
    end
  else
    [value, Filter::Error.new(self, :invalid_type)]
  end
end
convert(value) click to toggle source
# File lib/active_interaction/filter.rb, line 218
def convert(value)
  [value, nil]
end
describe(value) click to toggle source
# File lib/active_interaction/filter.rb, line 226
def describe(value)
  value.inspect
rescue NoMethodError
  "(Object doesn't support #inspect)"
end
klass() click to toggle source
# File lib/active_interaction/filter.rb, line 222
def klass
  @klass ||= Object.const_get(self.class.slug.to_s.camelize, false)
end
matches?(_value) click to toggle source

rubocop:enable Metrics/PerceivedComplexity

# File lib/active_interaction/filter.rb, line 210
def matches?(_value)
  false
end
raw_default(context) click to toggle source
# File lib/active_interaction/filter.rb, line 232
def raw_default(context)
  value = options.fetch(:default)
  return value unless value.is_a?(Proc)

  if value.arity == 1
    context.instance_exec(self, &value)
  else
    context.instance_exec(&value)
  end
end