business_flow 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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