business_flow 0.15.1 → 0.17.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f138e6ec77fc0cbcada6bc02b282310b22db7cfb
4
- data.tar.gz: 473e3b3afa5b3af4b78eb6ee92475b77150a56e3
2
+ SHA256:
3
+ metadata.gz: e3e82021d8909a6bc2e1506eabcc81e311eadb03b799146c8ff0731519ce6700
4
+ data.tar.gz: acc5d1ccc792d66d9ea1562f7fa3549af9c06600cfca35178118e08a8635a3cb
5
5
  SHA512:
6
- metadata.gz: c5f6d16dd0671e965ddc9415cf47868c7ba1a01c41af9360ed8c2c9f9cb76fa7ac3cb6f6953fa58388a24f199b53b4c15e5f7902560a7ca5e6feb77c0782f94c
7
- data.tar.gz: 8d95b1ebf703d4bcf4663f2fccd86c8bb0058f0faa4bde05ea3ff17d41104d172123a26ebe423d5c5a8f2f6ab15c566a48dcadfbf09f6cecffcc74114e4bedfe
6
+ metadata.gz: bd4a457dbaf1cd943db479b585379d0f8b1391890e956a265eea09fa9f0badea95fcc8857223a451759844dfe419e661c43324e5db13bcb9fe6ccdd07d741684
7
+ data.tar.gz: '08f2debe4942321aaca7896c99a05147a56a8a2cde31fda83f9c2bfaf1fc8873b5e78a58e6c65b47aa94dfe794040da7be65f049527119147a959040ad940ac1'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- business_flow (0.15.1)
4
+ business_flow (0.17.2)
5
5
  activemodel (>= 3.0)
6
6
  activesupport (>= 3.0)
7
7
 
@@ -16,16 +16,19 @@ module BusinessFlow
16
16
 
17
17
  def add_needs(fields)
18
18
  @all += fields
19
+ @all.uniq!
19
20
  @needs.add_fields(fields)
20
21
  end
21
22
 
22
23
  def add_optional(fields)
23
24
  @all += fields
25
+ @all.uniq!
24
26
  @optionals.add_fields(fields)
25
27
  end
26
28
 
27
29
  def add_wants(field)
28
30
  @all << field.name
31
+ @all.uniq!
29
32
  @optionals.add_field(field)
30
33
  end
31
34
  end
@@ -46,10 +49,23 @@ module BusinessFlow
46
49
  inputs.add_optional(fields)
47
50
  end
48
51
 
52
+ # Provides an alternate way to look up the value for a field. This can be
53
+ # thought of as using a 'wants' combined with an expectation of presence,
54
+ # without having to check for whether or not the wants can be executed.
55
+ #
56
+ # :reek:NilCheck This is one of the places where we eliminate nil.
57
+ def lookup(field, by:, with:)
58
+ by = Array.wrap(by)
59
+ optional(*by)
60
+ wants field, with, unless: -> { by.any? { |input| send(input).nil? } },
61
+ default_output: field
62
+ end
63
+
49
64
  # Allows a field to be retrieved from the initialiaztion parameters
50
- def wants(field, default = proc { nil }, opts = {})
65
+ def wants(field, default = nil, opts = {}, &blk)
51
66
  internal_name = "wants_#{field}".to_sym
52
- uses(internal_name, default, opts)
67
+ default = proc { nil } unless default || block_given?
68
+ uses(internal_name, default, opts, &blk)
53
69
  inputs.add_wants(ParameterField.new(field, internal_name))
54
70
  end
55
71
 
@@ -60,7 +76,7 @@ module BusinessFlow
60
76
  # Declares that you will expose a field to the outside world.
61
77
  def provides(*fields)
62
78
  @provides ||= FieldList.new([], PublicField, [self, const_get(:Result)])
63
- @result_copy ||= 'def from_flow(flow)'
79
+ @result_copy ||= FROM_FLOW_PREAMBLE
64
80
  @result_copy += fields.map { |field| "\n@#{field} = flow.#{field}" }
65
81
  .join
66
82
  @provides.add_fields(fields)
@@ -71,16 +87,16 @@ module BusinessFlow
71
87
  def uses(field, klass = nil, opts = {}, &blk)
72
88
  step = Step.new(Callable.new(klass || blk),
73
89
  { default_output: field }.merge(opts))
74
- retriever = proc { step.call(self).output }
90
+ retriever = proc { step.call(self).merge_into(self) }
75
91
  UsesField.new(field, retriever).add_to(self)
76
92
  end
77
93
 
78
- def step(klass, opts = {})
79
- step = Step.new(Callable.new(klass), opts)
94
+ # :reek:ControlParameter It's just nicer to have this fall back to a
95
+ # block than have a different DSL method when using/not using blocks
96
+ def step(klass, opts = {}, &blk)
97
+ step = Step.new(Callable.new(blk || klass), opts)
80
98
  step_queue.push(step)
81
- step.outputs
82
- .values
83
- .select { |field| field.is_a?(Symbol) }
99
+ step.output_fields
84
100
  .each { |field| Field.new(field).add_to(self) }
85
101
  end
86
102
 
@@ -127,7 +143,7 @@ module BusinessFlow
127
143
  end
128
144
 
129
145
  def result_from(flow)
130
- finalize_result_provider
146
+ finalize_result_provider unless @finalized_result_provider
131
147
  # We use instance_variable_get here instead of making it part of
132
148
  # from_flow to ensure that we do not create the errors object unless
133
149
  # we need it.
@@ -165,6 +181,11 @@ module BusinessFlow
165
181
  end
166
182
  end
167
183
 
184
+ FROM_FLOW_PREAMBLE = %(
185
+ def from_flow(flow)
186
+ return if errors?
187
+ ).freeze
188
+
168
189
  RESULT_DEF = %(
169
190
  class Result
170
191
  def initialize(errors)
@@ -178,7 +199,7 @@ module BusinessFlow
178
199
  def errors?
179
200
  # We're explicitly using the instance variable here so that if no
180
201
  # errors have been created, we don't initialize the error object.
181
- @errors.present?
202
+ !!@errors && @errors.present?
182
203
  end
183
204
 
184
205
  def valid?(_context = nil)
@@ -267,7 +288,7 @@ module BusinessFlow
267
288
  def errors?
268
289
  # We're explicitly using the instance variable here so that if no
269
290
  # errors have been created, we don't initialize the error object.
270
- @errors.present?
291
+ @errors && @errors.present?
271
292
  end
272
293
 
273
294
  def valid?(_context = nil)
@@ -296,6 +317,7 @@ module BusinessFlow
296
317
  fields.each do |field|
297
318
  add_field(@field_klass.new(field))
298
319
  end
320
+ @field_list.uniq! if fields.present?
299
321
  @field_list
300
322
  end
301
323
 
@@ -44,8 +44,8 @@ module BusinessFlow
44
44
  end
45
45
 
46
46
  def merge_into(object)
47
- merge_errors_into(object)
48
- merge_outputs_into(object)
47
+ merge_errors_into(object) if mergeable_errors?
48
+ merge_outputs_into(object) if @output_map
49
49
  output
50
50
  end
51
51
 
@@ -62,9 +62,11 @@ module BusinessFlow
62
62
  # because that will run validations and a step may return a partially
63
63
  # constructed model. By instead pulling out the errors instance variable
64
64
  # we'll only merge errors if validations have already been run.
65
- elsif @result.class.include?(ActiveModel::Validations) &&
65
+ elsif @result.class.ancestors.include?(ActiveModel::Validations) &&
66
66
  @result.instance_variable_defined?(:@errors)
67
67
  @result.instance_variable_get(:@errors).present?
68
+ elsif @result.respond_to?(:errors)
69
+ @result.errors.present?
68
70
  else
69
71
  false
70
72
  end
@@ -88,9 +90,7 @@ module BusinessFlow
88
90
  end
89
91
 
90
92
  def merge_errors_into(object)
91
- return unless mergeable_errors?
92
93
  @result.errors.each do |attribute, message|
93
- attribute = "#{@result.class.name.underscore}.#{attribute}"
94
94
  (object.errors[attribute] << message).uniq!
95
95
  end
96
96
  throw :halt_step
@@ -175,7 +175,7 @@ module BusinessFlow
175
175
  end
176
176
 
177
177
  def result_factory
178
- ResultFactory.new(opts[:outputs] || {},
178
+ ResultFactory.new(opts[:outputs],
179
179
  opts[:output],
180
180
  opts[:default_output])
181
181
  end
@@ -201,6 +201,8 @@ module BusinessFlow
201
201
  update_call_method
202
202
  end
203
203
 
204
+ # This will show up as not covered in coverage reports, because it is
205
+ # dynamically redefined by #update_call_method below.
204
206
  def call(parameter_source)
205
207
  parameters = @input_object.parameters_from_source(parameter_source)
206
208
  if !@condition || @condition.call(parameter_source, parameters)
@@ -219,6 +221,11 @@ module BusinessFlow
219
221
  @result_factory.outputs
220
222
  end
221
223
 
224
+ def output_fields
225
+ return [] unless outputs
226
+ outputs.values.select { |field| field.is_a?(Symbol) }
227
+ end
228
+
222
229
  def to_s
223
230
  @callable.to_s
224
231
  end
@@ -1,3 +1,3 @@
1
1
  module BusinessFlow
2
- VERSION = '0.15.1'.freeze
2
+ VERSION = '0.17.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: business_flow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.1
4
+ version: 0.17.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Scarborough
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-04-14 00:00:00.000000000 Z
11
+ date: 2021-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -164,7 +164,7 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: 0.9.1
167
- description:
167
+ description:
168
168
  email:
169
169
  - alex@teak.io
170
170
  executables: []
@@ -200,7 +200,7 @@ homepage: https://teak.io
200
200
  licenses:
201
201
  - MIT
202
202
  metadata: {}
203
- post_install_message:
203
+ post_install_message:
204
204
  rdoc_options: []
205
205
  require_paths:
206
206
  - lib
@@ -215,9 +215,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
215
  - !ruby/object:Gem::Version
216
216
  version: '0'
217
217
  requirements: []
218
- rubyforge_project:
219
- rubygems_version: 2.6.11
220
- signing_key:
218
+ rubygems_version: 3.1.2
219
+ signing_key:
221
220
  specification_version: 4
222
221
  summary: General purpose management of service object flows
223
222
  test_files: []