class SmashTheState::Operation::State

Attributes

representer[RW]
current_user[RW]

Public Class Methods

build(params = nil, &block) click to toggle source
# File lib/smash_the_state/operation/state.rb, line 20
def build(params = nil, &block)
  Class.new(self).tap do |k|
    k.class_exec(params, &block)
  end
end
eval_custom_validator_block(state, original_state = nil) { |state, original_state| ... } click to toggle source

for non-ActiveModel states we will just evaluate the block as a validator

# File lib/smash_the_state/operation/state.rb, line 58
def eval_custom_validator_block(state, original_state = nil)
  yield(state, original_state)
  invalid!(state) if state.errors.present?
  state
end
eval_validation_directives_block(state, &block) click to toggle source

for ActiveModel states we will treat the block as a collection of ActiveModel validator directives

# File lib/smash_the_state/operation/state.rb, line 41
def eval_validation_directives_block(state, &block)
  state.tap do |s|
    # each validate block should be a "fresh start" and not interfere with the
    # previous blocks
    s.class.clear_validators!
    s.class_eval(&block)
    s.validate || invalid!(s)
  end
end
extend_validation_directives_block(state, &block) click to toggle source
# File lib/smash_the_state/operation/state.rb, line 51
def extend_validation_directives_block(state, &block)
  state.tap do |s|
    s.class_eval(&block)
  end
end
model_name() click to toggle source
# File lib/smash_the_state/operation/state.rb, line 64
def model_name
  ActiveModel::Name.new(self, nil, "State")
end
new(attributes = {}) click to toggle source
Calls superclass method
# File lib/smash_the_state/operation/state.rb, line 82
def initialize(attributes = {})
  @current_user = attributes.delete(:current_user) ||
                  attributes.delete("current_user")

  indifferent_whitelisted_attributes = self.
                                         class.
                                         attributes_registry.
                                         with_indifferent_access

  # ActiveModel will raise an ActiveRecord::UnknownAttributeError if any unexpected
  # attributes are passed in. since operations are meant to replace strong
  # parameters and enforce against arbitrary mass assignment, we should filter the
  # params to inclide only the whitelisted attributes.
  # TODO: what about nested attributes?
  whitelisted_attributes = attributes.select do |attribute|
    indifferent_whitelisted_attributes.key? attribute
  end

  super(whitelisted_attributes)
end
schema(key, options = {}, &block) click to toggle source

defines a nested schema inside of a state. can be nested arbitrarily deep. schemas may be described inline via a block or can be a reference to a definition

# File lib/smash_the_state/operation/state.rb, line 29
def schema(key, options = {}, &block)
  attribute key,
            :state_for_smashing,
            options.merge(
              # allow for schemas to be provided inline *or* as a reference to a
              # type definition
              schema: attribute_options_to_ref_block(options) || block
            )
end

Private Class Methods

attribute_options_to_ref_block(options) click to toggle source

if a reference to a definition is provided, use the reference schema block

# File lib/smash_the_state/operation/state.rb, line 71
def attribute_options_to_ref_block(options)
  options[:ref] && options[:ref].schema_block
end
invalid!(state) click to toggle source
# File lib/smash_the_state/operation/state.rb, line 75
def invalid!(state)
  raise Invalid, state
end

Public Instance Methods

as_json() click to toggle source
# File lib/smash_the_state/operation/state.rb, line 103
def as_json
  Hash[self.class.attributes_registry.keys.map do |key|
    [key, send(key).as_json]
  end]
end