class ActiveInteraction::Inputs

Holds inputs passed to the interaction.

Constants

GROUPED_INPUT_PATTERN

matches inputs like “key(1i)”

Public Class Methods

new(raw_inputs, base) { |name, inputs| ... } click to toggle source

@private

# File lib/active_interaction/inputs.rb, line 39
def initialize(raw_inputs, base)
  @base = base
  @normalized_inputs = normalize(raw_inputs)
  @inputs = base.class.filters.each_with_object({}) do |(name, filter), inputs|
    inputs[name] = filter.process(@normalized_inputs[name], base)

    yield name, inputs[name] if block_given?
  end
end
reserved?(name) click to toggle source

Checking ‘syscall` is the result of what appears to be a bug in Ruby. bugs.ruby-lang.org/issues/15597 @private

# File lib/active_interaction/inputs.rb, line 24
def reserved?(name)
  name.to_s.start_with?('_interaction_') ||
    name == :syscall ||
    (
      Base.method_defined?(name) &&
      !Object.method_defined?(name)
    ) ||
    (
      Base.private_method_defined?(name) &&
      !Object.private_method_defined?(name)
    )
end

Public Instance Methods

given?(input, *rest) click to toggle source

Returns ‘true` if the given key was in the hash passed to {.run}. Otherwise returns `false`. Use this to figure out if an input was given, even if it was `nil`. Keys within nested hash filter can also be checked by passing them in series. Arrays can be checked in the same manor as hashes by passing an index.

@example

class Example < ActiveInteraction::Base
  integer :x, default: nil
  def execute; given?(:x) end
end
Example.run!()        # => false
Example.run!(x: nil)  # => true
Example.run!(x: rand) # => true

@example Nested checks

class Example < ActiveInteraction::Base
  hash :x, default: {} do
    integer :y, default: nil
  end
  array :a, default: [] do
    integer
  end
  def execute; given?(:x, :y) || given?(:a, 2) end
end
Example.run!()               # => false
Example.run!(x: nil)         # => false
Example.run!(x: {})          # => false
Example.run!(x: { y: nil })  # => true
Example.run!(x: { y: rand }) # => true
Example.run!(a: [1, 2])      # => false
Example.run!(a: [1, 2, 3])   # => true

@param input [#to_sym]

@return [Boolean]

rubocop:disable all

# File lib/active_interaction/inputs.rb, line 134
def given?(input, *rest)
  filter_level = @base.class
  input_level = @normalized_inputs

  [input, *rest].each do |key_or_index|
    if key_or_index.is_a?(Symbol) || key_or_index.is_a?(String)
      key = key_or_index.to_sym
      key_to_s = key_or_index.to_s
      filter_level = filter_level.filters[key]

      break false if filter_level.nil? || input_level.nil?
      break false unless input_level.key?(key) || input_level.key?(key_to_s)

      input_level = input_level[key] || input_level[key_to_s]
    else
      index = key_or_index
      filter_level = filter_level.filters.first.last

      break false if filter_level.nil? || input_level.nil?
      break false unless index.between?(-input_level.size, input_level.size - 1)

      input_level = input_level[index]
    end
  end && true
end
normalized() click to toggle source

@private

# File lib/active_interaction/inputs.rb, line 50
def normalized
  @normalized_inputs
end
to_h() click to toggle source

Turn the inputs into a Hash.

@return [Hash]

# File lib/active_interaction/inputs.rb, line 57
def to_h
  @to_h ||= @inputs.transform_values(&:value).freeze
end

Private Instance Methods

assign_to_grouped_input!(inputs, key, index, value) click to toggle source
# File lib/active_interaction/inputs.rb, line 188
def assign_to_grouped_input!(inputs, key, index, value)
  key = key.to_sym

  inputs[key] = GroupedInput.new unless inputs[key].is_a?(GroupedInput)
  inputs[key][index] = value
end
convert(inputs) click to toggle source
# File lib/active_interaction/inputs.rb, line 177
def convert(inputs)
  return inputs if inputs.is_a?(self.class)
  return inputs.stringify_keys if inputs.is_a?(Hash)

  parameters = 'ActionController::Parameters'
  klass = parameters.safe_constantize
  return inputs.to_unsafe_h.stringify_keys if klass && inputs.is_a?(klass)

  raise ArgumentError, 'inputs must be a hash, ActiveInteraction::Inputs, or ActionController::Parameters'
end
normalize(inputs) click to toggle source

rubocop:enable all

# File lib/active_interaction/inputs.rb, line 163
def normalize(inputs)
  convert(inputs)
    .sort
    .each_with_object({}) do |(k, v), h|
      next if self.class.reserved?(k)

      if (group = GROUPED_INPUT_PATTERN.match(k))
        assign_to_grouped_input!(h, group[:key], group[:index], v)
      else
        h[k.to_sym] = v
      end
    end
end