Class: SmashTheState::Operation

Inherits:
Object
  • Object
show all
Extended by:
DryRun
Defined in:
lib/smash_the_state/operation.rb,
lib/smash_the_state/operation/step.rb,
lib/smash_the_state/operation/error.rb,
lib/smash_the_state/operation/state.rb,
lib/smash_the_state/operation/dry_run.rb,
lib/smash_the_state/operation/sequence.rb,
lib/smash_the_state/operation/definition.rb,
lib/smash_the_state/operation/state_type.rb,
lib/smash_the_state/operation/validation_step.rb

Defined Under Namespace

Modules: DryRun Classes: Definition, Error, NotAuthorized, Sequence, State, StateType, Step, ValidationStep

Class Attribute Summary collapse

Class Method Summary collapse

Methods included from DryRun

dry_run, dry_run_sequence, dry_run_sequence?

Class Attribute Details

.state_classObject (readonly)

Returns the value of attribute state_class.



15
16
17
# File 'lib/smash_the_state/operation.rb', line 15

def state_class
  @state_class
end

Class Method Details

.call(params = {}) ⇒ Object Also known as: run

Runs the operation, creating the state based on the provided params, passing it from step to step and returning the last step.



19
20
21
# File 'lib/smash_the_state/operation.rb', line 19

def call(params = {})
  run_sequence(sequence, params)
end

.continues_from(prelude) ⇒ Object

inheritance doesn’t work with class attr_readers, this method is provided to bootstrap an operation as a continuation of a “prelude” operation



26
27
28
29
30
31
32
# File 'lib/smash_the_state/operation.rb', line 26

def continues_from(prelude)
  @state_class = prelude.state_class&.dup
  sequence.steps.concat prelude.sequence.steps

  # also make the dry run sequence continue
  dry_run_sequence.steps.concat(prelude.dry_run_sequence.steps)
end

.custom_validation(&block) ⇒ Object



96
97
98
99
100
101
102
103
# File 'lib/smash_the_state/operation.rb', line 96

def custom_validation(&block)
  # when we add a validation step, all proceeding steps must not produce
  # side-effects (subsequent steps are case-by-case)
  sequence.mark_as_side_effect_free!
  step :custom_validation do |state, original_state|
    Operation::State.eval_custom_validator_block(state, original_state, &block)
  end
end

.dynamic_schema(&block) ⇒ Object



38
39
40
41
42
43
44
45
# File 'lib/smash_the_state/operation.rb', line 38

def dynamic_schema(&block)
  sequence.add_step :_dynamic_schema do |params|
    Operation::State.build(params, &block).new(params)
  end

  # make sure that the dynamic schema step that we just added above is always first
  sequence.steps.unshift sequence.steps.pop
end

.error(*steps, &block) ⇒ Object



60
61
62
63
64
# File 'lib/smash_the_state/operation.rb', line 60

def error(*steps, &block)
  steps.each do |step_name|
    sequence.add_error_handler_for_step(step_name, &block)
  end
end

.inherited(child_class) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/smash_the_state/operation.rb', line 130

def self.inherited(child_class)
  # all steps from the parent first need to be cloned
  new_steps = sequence.steps.map(&:dup)

  # and then we add them to the child's empty sequence
  child_class.sequence.steps.concat(new_steps)

  # also copy the state class over
  child_class.instance_variable_set(:@state_class, state_class && state_class.dup)

  # also copy the dry run sequence
  child_class.dry_run_sequence.steps.concat(dry_run_sequence.steps.map(&:dup))
end

.middleware_class(&block) ⇒ Object



79
80
81
# File 'lib/smash_the_state/operation.rb', line 79

def middleware_class(&block)
  sequence.middleware_class_block = block
end

.middleware_step(step_name, options = {}) ⇒ Object



83
84
85
# File 'lib/smash_the_state/operation.rb', line 83

def middleware_step(step_name, options = {})
  sequence.add_middleware_step(step_name, options)
end

.override_step(step_name, options = {}, &block) ⇒ Object



51
52
53
54
55
56
57
58
# File 'lib/smash_the_state/operation.rb', line 51

def override_step(step_name, options = {}, &block)
  sequence.override_step(step_name, options, &block)

  # also override the dry run step
  return if dry_run_sequence.steps_for_name(step_name).empty?

  dry_run_sequence.override_step(step_name, options, &block)
end

.policy(klass, method_name) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/smash_the_state/operation.rb', line 66

def policy(klass, method_name)
  step :policy do |state, original_state|
    state.tap do
      policy_instance = klass.new(original_state.current_user, state)

      # pass the policy instance back in the NotAuthorized exception so
      # that the state, the user, and the policy can be inspected
      policy_instance.send(method_name) ||
        raise(NotAuthorized, policy_instance)
    end
  end
end

.represent(representer) ⇒ Object



105
106
107
108
109
# File 'lib/smash_the_state/operation.rb', line 105

def represent(representer)
  step :represent, side_effect_free: true do |state|
    representer.represent(state)
  end
end

.schema(&block) ⇒ Object



34
35
36
# File 'lib/smash_the_state/operation.rb', line 34

def schema(&block)
  @state_class = Operation::State.build(&block)
end

.sequenceObject



111
112
113
# File 'lib/smash_the_state/operation.rb', line 111

def sequence
  @sequence ||= Operation::Sequence.new
end

.step(step_name, options = {}, &block) ⇒ Object



47
48
49
# File 'lib/smash_the_state/operation.rb', line 47

def step(step_name, options = {}, &block)
  sequence.add_step(step_name, options, &block)
end

.validate(options = {}, &block) ⇒ Object



87
88
89
90
91
92
93
94
# File 'lib/smash_the_state/operation.rb', line 87

def validate(options = {}, &block)
  # when we add a validation step, all proceeding steps must not produce
  # side-effects (subsequent steps are case-by-case)
  sequence.mark_as_side_effect_free!
  sequence.add_validation_step(options) do |state|
    Operation::State.extend_validation_directives_block(state, &block)
  end
end