Module: BusinessFlow::DSL::ClassMethods
- Defined in:
- lib/business_flow/dsl.rb
Overview
Contains the DSL for BusinessFlow
Defined Under Namespace
Classes: Inputs
Instance Method Summary collapse
- #build(parameter_object) ⇒ Object
- #call(parameter_object = {}) ⇒ Object
- #call!(*args) ⇒ Object
-
#execute(flow) ⇒ Object
:reek:UtilityFunction This is a function on us so that other modules can change execution behavior.
- #finalize_initializer ⇒ Object
- #finalize_result_provider ⇒ Object
- #inputs ⇒ Object
- #instrument(_name, _flow) {|nil| ... } ⇒ Object
-
#lookup(field, by:, with:, inputs: nil, output: nil) ⇒ Object
Provides an alternate way to look up the value for a field.
-
#needs(*fields) ⇒ Object
Requires that a field be retrievable from the initialization parameters.
- #needs_code ⇒ Object
-
#optional(*fields) ⇒ Object
Allows a field to be retieved form the initialization paramters, but does not require it to be non-nil.
-
#provides(*fields) ⇒ Object
Declares that you will expose a field to the outside world.
- #result_from(flow) ⇒ Object
-
#step(klass, opts = {}, &blk) ⇒ Object
:reek:ControlParameter It’s just nicer to have this fall back to a block than have a different DSL method when using/not using blocks.
- #step_executor(executor_class = nil) ⇒ Object
- #step_queue ⇒ Object
-
#uses(field, klass = nil, opts = {}, &blk) ⇒ Object
:reek:ControlParameter It’s just nicer to have this fall back to a block than have a different DSL method when using/not using blocks.
-
#wants(field, default = nil, opts = {}, &blk) ⇒ Object
Allows a field to be retrieved from the initialiaztion parameters.
Instance Method Details
#build(parameter_object) ⇒ Object
119 120 121 122 123 124 125 126 |
# File 'lib/business_flow/dsl.rb', line 119 def build(parameter_object) finalize_initializer allocate.tap do |flow| catch(:halt_step) do flow.send(:_business_flow_dsl_initialize, parameter_object) end end end |
#call(parameter_object = {}) ⇒ Object
106 107 108 109 110 |
# File 'lib/business_flow/dsl.rb', line 106 def call(parameter_object = {}) flow = build(parameter_object) return result_from(flow) if flow.errors? execute(flow) end |
#call!(*args) ⇒ Object
128 129 130 131 132 |
# File 'lib/business_flow/dsl.rb', line 128 def call!(*args) flow = call(*args) raise FlowFailedException, flow if flow.errors? flow end |
#execute(flow) ⇒ Object
:reek:UtilityFunction This is a function on us so that other modules can change execution behavior.
114 115 116 117 |
# File 'lib/business_flow/dsl.rb', line 114 def execute(flow) catch(:halt_step) { flow.call } unless flow.errors? result_from(flow) end |
#finalize_initializer ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/business_flow/dsl.rb', line 176 def finalize_initializer return if @finalized_initializer class_eval %{ private def _business_flow_dsl_initialize(parameter_object) @parameter_object = parameter_object #{needs_code} initialize end }, __FILE__, __LINE__ - 6 @finalized_initializer = true end |
#finalize_result_provider ⇒ Object
160 161 162 163 164 |
# File 'lib/business_flow/dsl.rb', line 160 def finalize_result_provider return if @finalized_result_provider || !@result_copy const_get(:Result).class_eval "#{@result_copy}\nend", __FILE__, __LINE__ @finalized_result_provider = true end |
#inputs ⇒ Object
75 76 77 |
# File 'lib/business_flow/dsl.rb', line 75 def inputs @inputs ||= Inputs.new(self) end |
#instrument(_name, _flow) {|nil| ... } ⇒ Object
146 147 148 |
# File 'lib/business_flow/dsl.rb', line 146 def instrument(_name, _flow) yield nil end |
#lookup(field, by:, with:, inputs: nil, output: nil) ⇒ Object
Provides an alternate way to look up the value for a field. This can be thought of as using a ‘wants’ combined with an expectation of presence, without having to check for whether or not the wants can be executed.
:reek:NilCheck This is one of the places where we eliminate nil. :reek:LongParameterList Deal with it
60 61 62 63 64 65 |
# File 'lib/business_flow/dsl.rb', line 60 def lookup(field, by:, with:, inputs: nil, output: nil) by = Array.wrap(by) optional(*by) wants field, with, unless: -> { by.any? { |input| send(input).nil? } }, default_output: field, inputs: inputs, output: output end |
#needs(*fields) ⇒ Object
Requires that a field be retrievable from the initialization parameters
This will only require that the field is not nil. The field may still be #empty?
44 45 46 |
# File 'lib/business_flow/dsl.rb', line 44 def needs(*fields) inputs.add_needs(fields) end |
#needs_code ⇒ Object
166 167 168 169 170 171 172 173 174 |
# File 'lib/business_flow/dsl.rb', line 166 def needs_code needs.map do |need| %(if #{need}.nil? errors.add(:#{need}, :invalid, message: 'must not be nil') throw :halt_step end ) end.join("\n") end |
#optional(*fields) ⇒ Object
Allows a field to be retieved form the initialization paramters, but does not require it to be non-nil
50 51 52 |
# File 'lib/business_flow/dsl.rb', line 50 def optional(*fields) inputs.add_optional(fields) end |
#provides(*fields) ⇒ Object
Declares that you will expose a field to the outside world.
80 81 82 83 84 85 86 |
# File 'lib/business_flow/dsl.rb', line 80 def provides(*fields) @provides ||= FieldList.new([], PublicField, [self, const_get(:Result)]) @result_copy ||= FROM_FLOW_PREAMBLE @result_copy += fields.map { |field| "\n@#{field} = flow.#{field}" } .join @provides.add_fields(fields) end |
#result_from(flow) ⇒ Object
150 151 152 153 154 155 156 157 158 |
# File 'lib/business_flow/dsl.rb', line 150 def result_from(flow) finalize_result_provider unless @finalized_result_provider # We use instance_variable_get here instead of making it part of # from_flow to ensure that we do not create the errors object unless # we need it. result = const_get(:Result).new(flow.instance_variable_get(:@errors)) result.from_flow(flow) if @result_copy result end |
#step(klass, opts = {}, &blk) ⇒ Object
:reek:ControlParameter It’s just nicer to have this fall back to a block than have a different DSL method when using/not using blocks
99 100 101 102 103 104 |
# File 'lib/business_flow/dsl.rb', line 99 def step(klass, opts = {}, &blk) step = Step.new(Callable.new(blk || klass), opts) step_queue.push(step) step.output_fields .each { |field| Field.new(field).add_to(self) } end |
#step_executor(executor_class = nil) ⇒ Object
138 139 140 141 142 143 144 |
# File 'lib/business_flow/dsl.rb', line 138 def step_executor(executor_class = nil) if executor_class @executor_class = executor_class else @executor_class ||= ::BusinessFlow::DefaultStepExecutor end end |
#step_queue ⇒ Object
134 135 136 |
# File 'lib/business_flow/dsl.rb', line 134 def step_queue @step_queue ||= [] end |
#uses(field, klass = nil, opts = {}, &blk) ⇒ Object
:reek:ControlParameter It’s just nicer to have this fall back to a block than have a different DSL method when using/not using blocks
90 91 92 93 94 95 |
# File 'lib/business_flow/dsl.rb', line 90 def uses(field, klass = nil, opts = {}, &blk) step = Step.new(Callable.new(klass || blk), { default_output: field }.merge(opts)) retriever = proc { step.call(self).merge_into(self) } UsesField.new(field, retriever).add_to(self) end |
#wants(field, default = nil, opts = {}, &blk) ⇒ Object
Allows a field to be retrieved from the initialiaztion parameters
68 69 70 71 72 73 |
# File 'lib/business_flow/dsl.rb', line 68 def wants(field, default = nil, opts = {}, &blk) internal_name = "wants_#{field}".to_sym default = proc { nil } unless default || block_given? uses(internal_name, default, opts, &blk) inputs.add_wants(ParameterField.new(field, internal_name)) end |