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 192
def accepts_grouped_inputs?
  false
end
clean(value, context) click to toggle source

Convert a value into the expected type. If no value is given, fall back

to the default value.

@example

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

@example

ActiveInteraction::Filter.new(:example).clean(0, nil)
# => ActiveInteraction::InvalidValueError: example: 0

@example

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

@example

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

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

@return [Object]

@raise [MissingValueError] If the value is missing and there is no

default.

@raise [InvalidValueError] If the value is invalid. @raise (see default)

# File lib/active_interaction/filter.rb, line 101
def clean(value, context)
  value = cast(value, context)
  if value.nil?
    default(context)
  else
    value
  end
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 177
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 128
def default(context = nil)
  raise NoDefaultError, name unless default?

  value = raw_default(context)
  raise InvalidValueError if value.is_a?(GroupedInput)

  cast(value, context)
rescue InvalidNestedValueError => e
  raise InvalidDefaultError, "#{name}: #{value.inspect} (#{e})"
rescue InvalidValueError, MissingValueError
  raise InvalidDefaultError, "#{name}: #{value.inspect}"
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 162
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 148
def desc
  options[:desc]
end

Private Instance Methods

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

rubocop:disable Metrics/MethodLength

# File lib/active_interaction/filter.rb, line 199
def cast(value, context, convert: true, reconstantize: true)
  if matches?(value)
    adjust_output(value, context)
  # we can't use `nil?` because BasicObject doesn't have it
  elsif value == nil # rubocop:disable Style/NilComparison
    raise MissingValueError, name unless default?

    nil
  elsif reconstantize
    send(__method__, value, context,
      convert: convert,
      reconstantize: false
    )
  elsif convert
    send(__method__, convert(value), context,
      convert: false,
      reconstantize: reconstantize
    )
  else
    raise InvalidValueError, "#{name}: #{describe(value)}"
  end
end
convert(value) click to toggle source
# File lib/active_interaction/filter.rb, line 231
def convert(value)
  value
end
describe(value) click to toggle source
# File lib/active_interaction/filter.rb, line 239
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 235
def klass
  @klass ||= Object.const_get(self.class.slug.to_s.camelize, false)
end
matches?(_value) click to toggle source

rubocop:enable Metrics/MethodLength

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

  case value.arity
  when 1 then context.instance_exec(self, &value)
  else context.instance_exec(&value)
  end
end