Class: RungerActions::Base

Inherits:
Object
  • Object
show all
Extended by:
MemoWise
Includes:
MemoWise
Defined in:
lib/runger_actions/base.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params = {}) ⇒ Base

We can’t specify keyword arguments for this method because we don’t know which keywords/params the method will need to accept; that’s defined by the user.

rubocop:disable Style/OptionHash



124
125
126
127
128
# File 'lib/runger_actions/base.rb', line 124

def initialize(params = {})
  @params = params
  @errors = ActiveModel::Errors.new(self)
  validate_required_params!
end

Instance Attribute Details

#errorsObject (readonly)

Returns the value of attribute errors.



118
119
120
# File 'lib/runger_actions/base.rb', line 118

def errors
  @errors
end

Class Method Details

.define_reader_method(param_name) ⇒ Object



35
36
37
38
39
# File 'lib/runger_actions/base.rb', line 35

def define_reader_method(param_name)
  define_method(param_name) do
    @params[param_name]
  end
end

.fails_with(error_type) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/runger_actions/base.rb', line 78

def fails_with(error_type)
  result_klass.class_eval do
    define_method(:"#{error_type}!") do |error_message = nil|
      @failure = error_type
      @error_message = error_message
      if @action.raise_on_failure?
        raise(
          RungerActions::RuntimeFailure,
          "#{@action.class.name} action failed with `#{error_type}`",
        )
      end
    end

    define_method(:"#{error_type}?") do
      @failure == error_type
    end
  end
end

.new!(params) ⇒ Object



13
14
15
16
17
18
19
20
# File 'lib/runger_actions/base.rb', line 13

def new!(params)
  action = new(params)
  if action.valid?
    action
  else
    raise(RungerActions::InvalidParam, action.errors.full_messages.join(', '))
  end
end

.register_validator_klass(param_name, param_klass, blk) ⇒ Object



41
42
43
44
45
46
47
# File 'lib/runger_actions/base.rb', line 41

def register_validator_klass(param_name, param_klass, blk)
  validator_klass = const_set(:"#{param_name.to_s.camelize}Validator", Class.new)
  validator_klass.include(ActiveModel::Model)
  validator_klass.attr_accessor(*param_klass.column_names)
  validator_klass.class_eval(&blk)
  validators[param_name] = validator_klass
end

.requires(param_name, *shape_descriptions, &blk) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/runger_actions/base.rb', line 22

def requires(param_name, *shape_descriptions, &blk)
  required_params[param_name] = Shaped::Shape(*shape_descriptions)

  shape_description = shape_descriptions.first if shape_descriptions.size == 1
  if (
    shape_description.is_a?(Class) && (shape_description < ActiveRecord::Base) && blk.present?
  )
    register_validator_klass(param_name, shape_description, blk)
  end

  define_reader_method(param_name)
end

.returns(param_name, *shape_descriptions) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/runger_actions/base.rb', line 49

def returns(param_name, *shape_descriptions)
  shape = Shaped::Shape(*shape_descriptions)
  promised_values[param_name] = shape
  result_klass.class_eval do
    define_method(param_name) do
      @return_values[param_name]
    end

    define_method(:"#{param_name}=") do |value|
      if locked?
        raise(RungerActions::MutatingLockedResult, <<~ERROR.squish)
          You are attempting to assign a value to an instance of #{self.class} outside of the
          #{self.class.module_parent}#execute method. This is not allowed; you may only assign
          values to the `result` within the #execute method.
        ERROR
      end

      if !shape.matched_by?(value)
        raise(RungerActions::TypeMismatch, <<~ERROR.squish)
          Attemted to assign an invalid value for `result.#{param_name}` ; expected an object
          shaped like #{shape} but got #{value.inspect}
        ERROR
      end

      @return_values[param_name] = value
    end
  end
end

.run!(params) ⇒ Object



9
10
11
# File 'lib/runger_actions/base.rb', line 9

def run!(params)
  new!(params).run!
end

Instance Method Details

#raise_on_failure?Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/runger_actions/base.rb', line 159

def raise_on_failure?
  !!@raise_on_failure
end

#run(raise_on_failure: false) ⇒ Object

rubocop:enable Style/OptionHash



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/runger_actions/base.rb', line 131

def run(raise_on_failure: false)
  @raise_on_failure = raise_on_failure
  if !respond_to?(:execute)
    raise(RungerActions::ExecuteNotImplemented, <<~ERROR.squish)
      All RungerActions classes must implement an #execute instance method, but #{self.class}
      fails to do so.
    ERROR
  end

  execute
  result.lock!
  verify_promised_return_values! if result.success?
  result
end

#run!Object



146
147
148
149
150
151
152
# File 'lib/runger_actions/base.rb', line 146

def run!
  if valid?
    run(raise_on_failure: true)
  else
    raise(RungerActions::InvalidParam, @errors.full_messages.join(', '))
  end
end

#valid?Boolean

Returns:

  • (Boolean)


154
155
156
157
# File 'lib/runger_actions/base.rb', line 154

def valid?
  run_custom_validations
  @errors.blank?
end