subroutine 0.3.4 → 0.4.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: d28f248f1e76c10fb53fcbf1fc376a7f2c6800cd
4
- data.tar.gz: b81a6050e1c2245e545b39dd99d396f80925a92e
3
+ metadata.gz: 3ce8addef08d4ac3a2acc33ebd1336e1acbeadf4
4
+ data.tar.gz: 461466c26f1da36c13d468c2cdf7d7251b8ef7f6
5
5
  SHA512:
6
- metadata.gz: 27f2215a662339b46a5bd7a73a1822915d95a9144fc28f09dac0bd632020629d2ca6ec6aab6497a5c7b3452946b816dd8cdb5fbe99e96a359ac11e9f205915c6
7
- data.tar.gz: 260a8d6f175d715175376c8072d25318b0db4c467cff433c95458ede1788bd985c9ef0619e0ad3db4d707ef3978820a259e0af5c22b58edc51a60014533c18d2
6
+ metadata.gz: 3562274bd7a30c17d62530fd4ae8e7031326e44a2d2c6ac94fd329200bac3e9b20f3c13e4fa7aee9b50597b1fd3377fbf04a2f5fbc23978ccbb599ab3b2f30b1
7
+ data.tar.gz: 0ac228d98a9cd17ff9b9dc33649eaaf434579e96c641b2e0560d45c602a98bfad6d04debe89cdf99b2c77aed9217d3657036dbfeb96921b09309888acedefbab
data/lib/subroutine/op.rb CHANGED
@@ -4,6 +4,8 @@ require 'active_model'
4
4
  require "subroutine/failure"
5
5
  require "subroutine/type_caster"
6
6
  require "subroutine/filtered_errors"
7
+ require "subroutine/output_not_set_error"
8
+ require "subroutine/unknown_output_error"
7
9
 
8
10
  module Subroutine
9
11
 
@@ -12,6 +14,10 @@ module Subroutine
12
14
  include ::ActiveModel::Model
13
15
  include ::ActiveModel::Validations::Callbacks
14
16
 
17
+ DEFAULT_OUTPUT_OPTIONS = {
18
+ required: true
19
+ }.freeze
20
+
15
21
  class << self
16
22
 
17
23
  ::Subroutine::TypeCaster::TYPES.values.flatten.each do |caster|
@@ -41,6 +47,18 @@ module Subroutine
41
47
 
42
48
  alias_method :fields, :field
43
49
 
50
+ def output(name, options = {})
51
+ self._outputs = self._outputs.merge({
52
+ name.to_sym => DEFAULT_OUTPUT_OPTIONS.merge(options)
53
+ })
54
+
55
+ class_eval <<-EV, __FILE__, __LINE__ + 1
56
+ def #{name}
57
+ @outputs[:#{name}]
58
+ end
59
+ EV
60
+ end
61
+
44
62
  def ignore_error(*field_names)
45
63
  field_names.each do |f|
46
64
  _ignore_errors(f)
@@ -124,6 +142,9 @@ module Subroutine
124
142
  end
125
143
 
126
144
 
145
+ class_attribute :_outputs
146
+ self._outputs = {}
147
+
127
148
  class_attribute :_fields
128
149
  self._fields = {}
129
150
 
@@ -141,12 +162,20 @@ module Subroutine
141
162
  @original_params = inputs.with_indifferent_access
142
163
  @params = sanitize_params(@original_params)
143
164
  @defaults = sanitize_defaults
165
+ @outputs = {}
144
166
  end
145
167
 
146
168
  def errors
147
169
  @filtered_errors ||= Subroutine::FilteredErrors.new(super)
148
170
  end
149
171
 
172
+ def output(name, value)
173
+ unless _outputs.key?(name.to_sym)
174
+ raise ::Subroutine::UnknownOutputError.new(name)
175
+ end
176
+ @outputs[name.to_sym] = value
177
+ end
178
+
150
179
  def submit!
151
180
  unless submit
152
181
  raise ::Subroutine::Failure.new(self)
@@ -156,10 +185,20 @@ module Subroutine
156
185
 
157
186
  # the action which should be invoked upon form submission (from the controller)
158
187
  def submit
159
- observe_submission do
188
+ result = observe_submission do
160
189
  validate_and_perform
161
190
  end
162
191
 
192
+ if result
193
+ _outputs.each_pair do |name, config|
194
+ if config[:required] && !@outputs.key?(name)
195
+ raise ::Subroutine::OutputNotSetError.new(name)
196
+ end
197
+ end
198
+ end
199
+
200
+ result
201
+
163
202
  rescue Exception => e
164
203
 
165
204
  if e.respond_to?(:record)
@@ -0,0 +1,8 @@
1
+ module Subroutine
2
+ class OutputNotSetError < StandardError
3
+ def initialize(name)
4
+ super("Expected output '#{name}' to be set upon completion of perform but was not.")
5
+ end
6
+ end
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ module Subroutine
2
+ class UnknownOutputError < StandardError
3
+ def initialize(name)
4
+ super("Unknown output '#{name}'")
5
+ end
6
+ end
7
+
8
+ end
@@ -1,8 +1,8 @@
1
1
  module Subroutine
2
2
 
3
3
  MAJOR = 0
4
- MINOR = 3
5
- PATCH = 4
4
+ MINOR = 4
5
+ PATCH = 0
6
6
  PRE = nil
7
7
 
8
8
  VERSION = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
@@ -195,5 +195,36 @@ module Subroutine
195
195
  assert_equal(BigDecimal("25.3"), op.params_with_defaults["decimal_input"])
196
196
  end
197
197
 
198
+ def test_it_allow_retrival_of_outputs
199
+ op = ::SignupOp.submit!(:email => 'foo@bar.com', :password => 'password123')
200
+ u = op.created_user
201
+
202
+ assert_equal "foo@bar.com", u.email_address
203
+ end
204
+
205
+ def test_it_raises_an_error_if_an_output_is_not_defined_but_is_set
206
+ op = ::MissingOutputOp.new
207
+ assert_raises ::Subroutine::UnknownOutputError do
208
+ op.submit
209
+ end
210
+ end
211
+
212
+ def test_it_raises_an_error_if_not_all_outputs_were_set
213
+ op = ::MissingOutputSetOp.new
214
+ assert_raises ::Subroutine::OutputNotSetError do
215
+ op.submit
216
+ end
217
+ end
218
+
219
+ def test_it_does_not_raise_an_error_if_output_is_not_set_and_is_not_required
220
+ op = ::OutputNotRequiredOp.new
221
+ op.submit
222
+ end
223
+
224
+ def test_it_does_not_raise_an_error_if_the_perform_is_not_a_success
225
+ op = ::NoOutputNoSuccessOp.new
226
+ refute op.submit
227
+ end
228
+
198
229
  end
199
230
  end
@@ -164,6 +164,9 @@ module Subroutine
164
164
  assert_equal 2020, op.date_input.year
165
165
  assert_equal 5, op.date_input.month
166
166
  assert_equal 3, op.date_input.day
167
+
168
+ op.date_input = false
169
+ assert_nil op.date_input
167
170
  end
168
171
 
169
172
 
data/test/support/ops.rb CHANGED
@@ -28,15 +28,15 @@ class SignupOp < ::Subroutine::Op
28
28
  validates :email, :presence => true
29
29
  validates :password, :presence => true
30
30
 
31
- attr_reader :perform_called
32
- attr_reader :perform_finished
31
+ output :perform_called
32
+ output :perform_finished
33
33
 
34
- attr_reader :created_user
34
+ output :created_user
35
35
 
36
36
  protected
37
37
 
38
38
  def perform
39
- @perform_called = true
39
+ output :perform_called, true
40
40
  u = build_user
41
41
 
42
42
  unless u.valid?
@@ -44,9 +44,8 @@ class SignupOp < ::Subroutine::Op
44
44
  return false
45
45
  end
46
46
 
47
- @perform_finished = true
48
- @created_user = u
49
-
47
+ output :perform_finished, true
48
+ output :created_user, u
50
49
  true
51
50
  end
52
51
 
@@ -201,3 +200,30 @@ end
201
200
  class InheritedPolymorphicAssociationOp < ::Subroutine::Op
202
201
  inputs_from PolymorphicAssociationOp
203
202
  end
203
+
204
+ class MissingOutputOp < ::Subroutine::Op
205
+ def perform
206
+ output :foo, "bar"
207
+ end
208
+ end
209
+
210
+ class MissingOutputSetOp < ::Subroutine::Op
211
+ output :foo
212
+ def perform
213
+ true
214
+ end
215
+ end
216
+
217
+ class OutputNotRequiredOp < ::Subroutine::Op
218
+ output :foo, required: false
219
+ def perform
220
+ true
221
+ end
222
+ end
223
+
224
+ class NoOutputNoSuccessOp < ::Subroutine::Op
225
+ output :foo
226
+ def perform
227
+ false
228
+ end
229
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: subroutine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Nelson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-04 00:00:00.000000000 Z
11
+ date: 2017-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -119,7 +119,9 @@ files:
119
119
  - lib/subroutine/failure.rb
120
120
  - lib/subroutine/filtered_errors.rb
121
121
  - lib/subroutine/op.rb
122
+ - lib/subroutine/output_not_set_error.rb
122
123
  - lib/subroutine/type_caster.rb
124
+ - lib/subroutine/unknown_output_error.rb
123
125
  - lib/subroutine/version.rb
124
126
  - subroutine.gemspec
125
127
  - test/subroutine/association_test.rb