business_flow 0.10.0 → 0.11.0

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
2
  SHA1:
3
- metadata.gz: e290b1ee2ae04716265134fba7524c9807aca356
4
- data.tar.gz: eac9618cc742dcf1d9414511f16dc9e7b589bfbe
3
+ metadata.gz: 74bfeb7c6a69ab685707ad54578b1d7defcf9965
4
+ data.tar.gz: c7cbebb026219e58f9adcb4ae2ad29de2c813201
5
5
  SHA512:
6
- metadata.gz: e405489e1b36df74ba88023c1a6dab81f70a635caaa0536db9b1939ee5af323e1e1bbc148cb4035af3a51af19c2039e3e553c0b2b3eba31a846fc028d348ae4e
7
- data.tar.gz: 9506dd03a58ee98d3e3d24a453c57b766af2710ecb9ee370b2ccda2a76c2dff482b730614b1d91f7a39742a9e56c2f92fdd5bddfe0925152e49949d8f661b924
6
+ metadata.gz: 816b7e6b843375488b16a19559fdfd64806d0283042a7577a919061f9625a4ddc577a029ff27454ecdf2febb7da04891c8a56fec48dc51c0496fc1e513fcd6f3
7
+ data.tar.gz: cff7f66cab24eca4215ce189bec3c92883c260b0edb84a43a76a3cb22002e5eaa75ef45bd96c39200d31c33bb2c7350916f2a6e4b0d92d3a1da9ca6177677fd7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- business_flow (0.10.0)
4
+ business_flow (0.11.0)
5
5
  activemodel (>= 3.0)
6
6
  activesupport (>= 3.0)
7
7
 
@@ -58,31 +58,37 @@ module BusinessFlow
58
58
  end
59
59
  end
60
60
 
61
- # :reek:TooManyStatements This can't be easily simplified any further,
62
- # as best as I can tell.
63
61
  def execute(flow)
64
- add_cache_key_to_result_class
65
- cache_store.fetch(flow.cache_key,
66
- cache_options.to_store_options(flow)) do
67
- result = add_cache_key(super(flow), flow)
68
- raise FlowFailedException, result if result.errors?
69
- result
62
+ with_cache(flow) do
63
+ super(flow)._business_flow_cacheable_finalize(flow.cache_key)
70
64
  end
71
65
  rescue FlowFailedException => exc
72
66
  exc.flow
73
67
  end
74
68
 
69
+ def with_cache(flow, &blk)
70
+ add_cache_key_to_result_class
71
+ catch(:halt_step) do
72
+ return cache_store.fetch(flow.cache_key,
73
+ cache_options.to_store_options(flow), &blk)
74
+ end
75
+ raise FlowFailedException, flow
76
+ end
77
+
78
+ RESULT_FINALIZE = proc do |cache_key|
79
+ @cache_key = cache_key
80
+ raise FlowFailedException, self if errors?
81
+ self
82
+ end
83
+
75
84
  def add_cache_key_to_result_class
76
85
  return if @cache_key_added
77
- DSL::PublicField.new(:cache_key).add_to(const_get(:Result))
86
+ result_class = const_get(:Result)
87
+ DSL::PublicField.new(:cache_key).add_to(result_class)
88
+ result_class.send(:define_method, :_business_flow_cacheable_finalize,
89
+ RESULT_FINALIZE)
78
90
  @cache_key_added = true
79
91
  end
80
-
81
- # :reek:UtilityFunction Not entirey sure where else to put this.
82
- def add_cache_key(result, flow)
83
- result.instance_variable_set('@cache_key'.freeze, flow.cache_key)
84
- result
85
- end
86
92
  end
87
93
  end
88
94
  end
@@ -25,6 +25,9 @@ module BusinessFlow
25
25
  # Declares that you will expose a field to the outside world.
26
26
  def provides(*fields)
27
27
  @provides ||= FieldList.new([], PublicField, [self, const_get(:Result)])
28
+ @result_copy ||= 'def from_flow(flow)'
29
+ @result_copy += fields.map { |field| "@#{field} = flow.#{field}" }
30
+ .join("\n")
28
31
  @provides.add_fields(fields)
29
32
  end
30
33
 
@@ -55,10 +58,11 @@ module BusinessFlow
55
58
  end
56
59
 
57
60
  def build(parameter_object)
61
+ finalize_initializer
58
62
  allocate.tap do |flow|
59
63
  catch(:halt_step) do
60
64
  flow.send(:_business_flow_dsl_initialize,
61
- ParameterObject.new(parameter_object), needs)
65
+ ParameterObject.new(parameter_object))
62
66
  end
63
67
  end
64
68
  end
@@ -82,21 +86,48 @@ module BusinessFlow
82
86
  end
83
87
 
84
88
  def result_from(flow)
85
- result_class = const_get(:Result)
86
- provides_hash = Hash[provides.map do |field|
87
- [field, flow.public_send(field)]
88
- end]
89
- result_class.new(flow.instance_variable_get(:@errors), provides_hash)
89
+ finalize_result_provider
90
+ # We use instance_variable_get here instead of making it part of
91
+ # from_flow to ensure that we do not create the errors object unless
92
+ # we need it.
93
+ result = const_get(:Result).new(flow.instance_variable_get(:@errors))
94
+ result.from_flow(flow) if @result_copy
95
+ result
96
+ end
97
+
98
+ def finalize_result_provider
99
+ return if @finalized_result_provider || !@result_copy
100
+ const_get(:Result).class_eval "#{@result_copy}\nend", __FILE__, __LINE__
101
+ @finalized_result_provider = true
102
+ end
103
+
104
+ def needs_code
105
+ needs.map do |need|
106
+ %(if #{need}.nil?
107
+ errors[:#{need}] << 'must not be nil'
108
+ throw :halt_step
109
+ end
110
+ )
111
+ end.join("\n")
112
+ end
113
+
114
+ def finalize_initializer
115
+ return if @finalized_initializer
116
+ class_eval %{
117
+ private def _business_flow_dsl_initialize(parameter_object)
118
+ @parameter_object = parameter_object
119
+ #{needs_code}
120
+ initialize
121
+ end
122
+ }, __FILE__, __LINE__ - 6
123
+ @finalized_initializer = true
90
124
  end
91
125
  end
92
126
 
93
127
  RESULT_DEF = %(
94
128
  class Result
95
- def initialize(errors, provides)
129
+ def initialize(errors)
96
130
  @errors = errors
97
- provides.each do |(name, value)|
98
- instance_variable_set("@" + name.to_s, value)
99
- end
100
131
  end
101
132
 
102
133
  def errors
@@ -121,9 +152,20 @@ module BusinessFlow
121
152
  end
122
153
  ).freeze
123
154
 
155
+ # Provides the minimum necessary methods to support the use of
156
+ # ActiveModel::Errors
157
+ module ErrorSupport
158
+ def human_attribute_name(key, _opts = {})
159
+ key
160
+ end
161
+ end
162
+
163
+ # :reek:ManualDispatch I have no need to actually call human_attribute_name,
164
+ # I just need to know if I have to provide my own.
124
165
  def self.included(klass)
125
166
  klass.extend(ClassMethods)
126
167
  klass.class_eval RESULT_DEF, __FILE__, __LINE__
168
+ klass.extend(ErrorSupport) unless klass.respond_to?(:human_attribute_name)
127
169
  end
128
170
 
129
171
  attr_reader :parameter_object
@@ -35,13 +35,10 @@ module BusinessFlow
35
35
  # Represents the result of a step, and allows setting response values on
36
36
  # an object, and merging error data into the same object.
37
37
  class Result
38
- # :reek:ManualDispatch Checking respond_to? is signficantly faster than
39
- # eating the NoMethodError when grabbing our error object.
40
38
  def initialize(result, output_map, output_callable)
41
39
  @result = result
42
40
  @output_map = output_map
43
41
  @output_callable = output_callable
44
- @result_errors = result.respond_to?(:errors) ? result.errors : nil
45
42
  end
46
43
 
47
44
  def merge_into(object)
@@ -53,8 +50,10 @@ module BusinessFlow
53
50
  true
54
51
  end
55
52
 
53
+ # :reek:ManualDispatch Checking respond_to? is signficantly faster than
54
+ # eating the NoMethodError when grabbing our error object.
56
55
  def errors?
57
- @result_errors.present?
56
+ @result.respond_to?(:errors?) ? @result.errors? : false
58
57
  end
59
58
 
60
59
  def output
@@ -73,8 +72,8 @@ module BusinessFlow
73
72
  private
74
73
 
75
74
  def merge_errors_into(object)
76
- return if @result_errors.blank?
77
- @result_errors.each do |attribute, message|
75
+ return unless errors?
76
+ @result.errors.each do |attribute, message|
78
77
  attribute = "#{@result.class.name.underscore}.#{attribute}"
79
78
  (object.errors[attribute] << message).uniq!
80
79
  end
@@ -1,3 +1,3 @@
1
1
  module BusinessFlow
2
- VERSION = '0.10.0'.freeze
2
+ VERSION = '0.11.0'.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.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Scarborough
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-27 00:00:00.000000000 Z
11
+ date: 2019-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel