subroutine 0.10.0.beta → 0.10.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
data/test/support/ops.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'subroutine/auth'
4
- require 'subroutine/association'
3
+ require "subroutine/auth"
4
+ require "subroutine/association_fields"
5
5
 
6
6
  ## Models ##
7
7
 
8
8
  class User
9
+
9
10
  include ::ActiveModel::Model
10
11
 
11
12
  attr_accessor :id
@@ -17,15 +18,19 @@ class User
17
18
  def self.find(id)
18
19
  new(id: id)
19
20
  end
21
+
20
22
  end
21
23
 
22
24
  class AdminUser < ::User
23
- validates :email_address, format: { with: /@admin\.com/, message: 'has gotta be @admin.com' }
25
+
26
+ validates :email_address, format: { with: /@admin\.com/, message: "has gotta be @admin.com" }
27
+
24
28
  end
25
29
 
26
30
  ## Ops ##
27
31
 
28
32
  class SignupOp < ::Subroutine::Op
33
+
29
34
  string :email, aka: :email_address
30
35
  string :password
31
36
 
@@ -63,43 +68,57 @@ class SignupOp < ::Subroutine::Op
63
68
  def user_class
64
69
  ::User
65
70
  end
71
+
66
72
  end
67
73
 
68
74
  class AdminSignupOp < ::SignupOp
69
- field :privileges, default: 'min'
75
+
76
+ field :privileges, default: "min"
70
77
 
71
78
  protected
72
79
 
73
80
  def user_class
74
81
  ::AdminUser
75
82
  end
83
+
76
84
  end
77
85
 
78
86
  class BusinessSignupOp < ::Subroutine::Op
87
+
79
88
  string :business_name
80
89
 
81
90
  inputs_from ::SignupOp
91
+
82
92
  end
83
93
 
84
94
  class DefaultsOp < ::Subroutine::Op
85
- field :foo, default: 'foo'
86
- field :bar, default: 'bar'
95
+
96
+ field :foo, default: "foo"
97
+ field :bar, default: "bar"
87
98
  field :baz, default: false
99
+
88
100
  end
89
101
 
90
102
  class ExceptFooBarOp < ::Subroutine::Op
91
- inputs_from ::DefaultsOp, except: [:foo, :bar]
103
+
104
+ inputs_from ::DefaultsOp, except: %i[foo bar]
105
+
92
106
  end
93
107
 
94
108
  class OnlyFooBarOp < ::Subroutine::Op
95
- inputs_from ::DefaultsOp, only: [:foo, :bar]
109
+
110
+ inputs_from ::DefaultsOp, only: %i[foo bar]
111
+
96
112
  end
97
113
 
98
114
  class InheritedDefaultsOp < ::DefaultsOp
99
- field :bar, default: 'barstool'
115
+
116
+ field :bar, default: "barstool", allow_overwrite: true
117
+
100
118
  end
101
119
 
102
120
  class TypeCastOp < ::Subroutine::Op
121
+
103
122
  integer :integer_input
104
123
  number :number_input
105
124
  decimal :decimal_input
@@ -110,39 +129,51 @@ class TypeCastOp < ::Subroutine::Op
110
129
  iso_date :iso_date_input
111
130
  iso_time :iso_time_input
112
131
  object :object_input
113
- array :array_input, default: 'foo'
132
+ array :array_input, default: "foo"
114
133
  array :type_array_input, of: :integer
115
134
  file :file_input
135
+
116
136
  end
117
137
 
118
138
  class OpWithAuth < ::Subroutine::Op
139
+
119
140
  include ::Subroutine::Auth
120
141
  def perform
121
142
  true
122
143
  end
144
+
123
145
  end
124
146
 
125
147
  class MissingAuthOp < OpWithAuth
126
148
  end
127
149
 
128
150
  class RequireUserOp < OpWithAuth
151
+
129
152
  require_user!
153
+
130
154
  end
131
155
 
132
156
  class RequireNoUserOp < OpWithAuth
157
+
133
158
  require_no_user!
159
+
134
160
  end
135
161
 
136
162
  class NoUserRequirementsOp < OpWithAuth
163
+
137
164
  no_user_requirements!
165
+
138
166
  end
139
167
 
140
168
  class DifferentUserClassOp < OpWithAuth
169
+
141
170
  self.user_class_name = "AdminUser"
142
171
  require_user!
172
+
143
173
  end
144
174
 
145
175
  class CustomAuthorizeOp < OpWithAuth
176
+
146
177
  require_user!
147
178
  authorize :authorize_user_is_correct
148
179
 
@@ -151,13 +182,17 @@ class CustomAuthorizeOp < OpWithAuth
151
182
  def authorize_user_is_correct
152
183
  unauthorized! unless current_user.email_address.to_s =~ /example\.com$/
153
184
  end
185
+
154
186
  end
155
187
 
156
188
  class PolicyOp < OpWithAuth
189
+
157
190
  class FakePolicy
191
+
158
192
  def user_can_access?
159
193
  false
160
194
  end
195
+
161
196
  end
162
197
 
163
198
  require_user!
@@ -166,13 +201,17 @@ class PolicyOp < OpWithAuth
166
201
  def policy
167
202
  @policy ||= FakePolicy.new
168
203
  end
204
+
169
205
  end
170
206
 
171
207
  class IfConditionalPolicyOp < OpWithAuth
208
+
172
209
  class FakePolicy
210
+
173
211
  def user_can_access?
174
212
  false
175
213
  end
214
+
176
215
  end
177
216
 
178
217
  require_user!
@@ -183,13 +222,17 @@ class IfConditionalPolicyOp < OpWithAuth
183
222
  def policy
184
223
  @policy ||= FakePolicy.new
185
224
  end
225
+
186
226
  end
187
227
 
188
228
  class UnlessConditionalPolicyOp < OpWithAuth
229
+
189
230
  class FakePolicy
231
+
190
232
  def user_can_access?
191
233
  false
192
234
  end
235
+
193
236
  end
194
237
 
195
238
  require_user!
@@ -200,95 +243,149 @@ class UnlessConditionalPolicyOp < OpWithAuth
200
243
  def policy
201
244
  @policy ||= FakePolicy.new
202
245
  end
246
+
203
247
  end
204
248
 
205
249
  class OpWithAssociation < ::Subroutine::Op
206
- include ::Subroutine::Association
250
+
251
+ include ::Subroutine::AssociationFields
252
+
207
253
  end
208
254
 
209
255
  class SimpleAssociationOp < ::OpWithAssociation
256
+
210
257
  association :user
258
+
211
259
  end
212
260
 
213
261
  class UnscopedSimpleAssociationOp < ::OpWithAssociation
214
- association :user, unscoped: true
262
+
263
+ association :user, unscoped: true, allow_overwrite: true
264
+
215
265
  end
216
266
 
217
267
  class PolymorphicAssociationOp < ::OpWithAssociation
268
+
218
269
  association :admin, polymorphic: true
270
+
219
271
  end
220
272
 
221
273
  class AssociationWithClassOp < ::OpWithAssociation
222
- association :admin, class_name: 'AdminUser'
274
+
275
+ association :admin, class_name: "AdminUser"
276
+
223
277
  end
224
278
 
225
279
  class InheritedSimpleAssociation < ::Subroutine::Op
280
+
226
281
  inputs_from SimpleAssociationOp
282
+
227
283
  end
228
284
 
229
285
  class InheritedUnscopedAssociation < ::Subroutine::Op
286
+
230
287
  inputs_from UnscopedSimpleAssociationOp
288
+
231
289
  end
232
290
 
233
291
  class InheritedPolymorphicAssociationOp < ::Subroutine::Op
292
+
234
293
  inputs_from PolymorphicAssociationOp
294
+
235
295
  end
236
296
 
237
297
  class FalsePerformOp < ::Subroutine::Op
298
+
238
299
  def perform
239
300
  false
240
301
  end
302
+
241
303
  end
242
304
 
243
305
  class MissingOutputOp < ::Subroutine::Op
306
+
244
307
  def perform
245
- output :foo, 'bar'
308
+ output :foo, "bar"
246
309
  end
310
+
247
311
  end
248
312
 
249
313
  class MissingOutputSetOp < ::Subroutine::Op
314
+
250
315
  outputs :foo
251
316
  def perform
252
317
  true
253
318
  end
319
+
254
320
  end
255
321
 
256
322
  class OutputNotRequiredOp < ::Subroutine::Op
323
+
257
324
  outputs :foo, required: false
258
325
  def perform
259
326
  true
260
327
  end
328
+
261
329
  end
262
330
 
263
331
  class NoOutputNoSuccessOp < ::Subroutine::Op
332
+
264
333
  outputs :foo
265
334
  def perform
266
- errors.add(:foo, 'bar')
335
+ errors.add(:foo, "bar")
267
336
  end
337
+
268
338
  end
269
339
 
270
340
  class ErrorTraceOp < ::Subroutine::Op
341
+
271
342
  class SomeObject
343
+
272
344
  include ::ActiveModel::Model
273
345
  include ::ActiveModel::Validations::Callbacks
274
346
 
275
347
  def foo
276
- errors.add(:base, 'Failure of things')
348
+ errors.add(:base, "Failure of things")
277
349
  raise Subroutine::Failure, self
278
350
  end
279
351
 
280
352
  def bar
281
353
  foo
282
354
  end
355
+
283
356
  end
284
357
 
285
358
  class SubOp < ::Subroutine::Op
359
+
286
360
  def perform
287
361
  SomeObject.new.bar
288
362
  end
363
+
289
364
  end
290
365
 
291
366
  def perform
292
367
  SubOp.submit!
293
368
  end
369
+
370
+ end
371
+
372
+ class CustomFailureClassOp < ::Subroutine::Op
373
+
374
+ class Failure < StandardError
375
+
376
+ attr_reader :record
377
+ def initialize(record)
378
+ @record = record
379
+ errors = @record.errors.full_messages.join(", ")
380
+ super(errors)
381
+ end
382
+
383
+ end
384
+
385
+ failure_class Failure
386
+
387
+ def perform
388
+ errors.add(:base, "Will never work")
389
+ end
390
+
294
391
  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.10.0.beta
4
+ version: 0.10.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Nelson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-14 00:00:00.000000000 Z
11
+ date: 2019-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -144,14 +144,20 @@ files:
144
144
  - gemfiles/am52.gemfile
145
145
  - gemfiles/am60.gemfile
146
146
  - lib/subroutine.rb
147
- - lib/subroutine/association.rb
147
+ - lib/subroutine/association_fields.rb
148
+ - lib/subroutine/association_fields/component_configuration.rb
149
+ - lib/subroutine/association_fields/configuration.rb
148
150
  - lib/subroutine/auth.rb
149
151
  - lib/subroutine/failure.rb
150
152
  - lib/subroutine/fields.rb
153
+ - lib/subroutine/fields/configuration.rb
154
+ - lib/subroutine/fields/mass_assignment_error.rb
151
155
  - lib/subroutine/op.rb
152
- - lib/subroutine/output_not_set_error.rb
156
+ - lib/subroutine/outputs.rb
157
+ - lib/subroutine/outputs/configuration.rb
158
+ - lib/subroutine/outputs/output_not_set_error.rb
159
+ - lib/subroutine/outputs/unknown_output_error.rb
153
160
  - lib/subroutine/type_caster.rb
154
- - lib/subroutine/unknown_output_error.rb
155
161
  - lib/subroutine/version.rb
156
162
  - subroutine.gemspec
157
163
  - test/subroutine/association_test.rb
@@ -180,8 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
186
  - !ruby/object:Gem::Version
181
187
  version: 1.3.1
182
188
  requirements: []
183
- rubyforge_project:
184
- rubygems_version: 2.6.14.4
189
+ rubygems_version: 3.0.6
185
190
  signing_key:
186
191
  specification_version: 4
187
192
  summary: Feature-driven operation objects.
@@ -1,131 +0,0 @@
1
- # frozen_string_literal: true
2
- require "active_support/concern"
3
-
4
- module Subroutine
5
- module Association
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- class << self
10
- alias_method :field_without_associations, :field
11
- alias_method :field, :field_with_associations
12
- end
13
-
14
- alias_method :setup_fields_without_association, :setup_fields
15
- alias_method :setup_fields, :setup_fields_with_association
16
- end
17
-
18
- module ClassMethods
19
- def field_with_associations(*args)
20
- opts = args.extract_options!
21
- if opts[:association]
22
- args.each do |arg|
23
- association(arg, opts)
24
- end
25
- else
26
- field_without_associations(*args, opts)
27
- end
28
- end
29
-
30
- # association :user
31
- # - user_id
32
- # - user_type => "User"
33
-
34
- # association :user, polymorphic: true
35
- # - user_id
36
- # - user_type
37
- # - user => polymorphic_lookup(user_type, user_id)
38
-
39
- # association :inbound_user_request, as: :request
40
- # - inbound_user_request_id
41
- # - inbound_user_request_type => "InboundUserRequest"
42
- # - request => polymorphic_lookup(inbound_user_request_type, inbound_user_request_id)
43
-
44
- # association :inbound_user_request, foreign_key: :request_id
45
- # - request_id
46
- # - request_type
47
- # - inbound_user_request => polymorphic_lookup(request_type, request_id)
48
-
49
- # Other options:
50
- # - unscoped => set true if the record should be looked up via Type.unscoped
51
-
52
- def association(field, options = {})
53
- if options[:as] && options[:foreign_key]
54
- raise ArgumentError, ':as and :foreign_key options should be provided together to an association invocation'
55
- end
56
-
57
- class_name = options[:class_name]
58
-
59
- poly = options[:polymorphic] || !class_name.nil?
60
- as = options[:as] || field
61
- unscoped = !!options[:unscoped]
62
-
63
- klass = class_name.to_s if class_name
64
-
65
- foreign_key_method = (options[:foreign_key] || "#{field}_id").to_s
66
- foreign_type_method = foreign_key_method.gsub(/_id$/, '_type')
67
-
68
- if poly
69
- string foreign_type_method
70
- else
71
- class_eval <<-EV, __FILE__, __LINE__ + 1
72
- def #{foreign_type_method}
73
- #{as.to_s.camelize.inspect}
74
- end
75
- EV
76
- end
77
-
78
- integer foreign_key_method
79
-
80
- field_without_associations as, options.merge(association: true, field_writer: false, field_reader: false)
81
-
82
- class_eval <<-EV, __FILE__, __LINE__ + 1
83
- try(:silence_redefinition_of_method, :#{as})
84
- def #{as}
85
- return @#{as} if defined?(@#{as})
86
- @#{as} = polymorphic_instance(#{klass.nil? ? foreign_type_method : klass.to_s}, #{foreign_key_method}, #{unscoped.inspect})
87
- end
88
-
89
- try(:silence_redefinition_of_method, :#{as}=)
90
- def #{as}=(r)
91
- @#{as} = r
92
- #{poly || klass ? "send('#{foreign_type_method}=', r.nil? ? nil : #{klass.nil? ? 'r.class.name' : klass.to_s.inspect})" : ''}
93
- send('#{foreign_key_method}=', r.nil? ? nil : r.id)
94
- r
95
- end
96
-
97
- try(:silence_redefinition_of_method, :#{as}_field_provided?)
98
- def #{as}_field_provided?
99
- field_provided?('#{foreign_key_method}')#{poly ? "&& field_provided?('#{foreign_type_method}')" : ""}
100
- end
101
- EV
102
- end
103
- end
104
-
105
- def setup_fields_with_association(*args)
106
- setup_fields_without_association(*args)
107
-
108
- _fields.each_pair do |field, config|
109
- next unless config[:association]
110
- next if config[:mass_assignable] == false
111
- next unless @original_params.key?(field)
112
-
113
- send("#{field}=", @original_params[field]) # this gets the _id and _type into the params hash
114
- end
115
- end
116
-
117
- def polymorphic_instance(_type, _id, _unscoped = false)
118
- return nil unless _type && _id
119
-
120
- klass = _type
121
- klass = klass.classify.constantize if klass.is_a?(String)
122
-
123
- return nil unless klass
124
-
125
- scope = klass.all
126
- scope = scope.unscoped if _unscoped
127
-
128
- scope.find(_id)
129
- end
130
- end
131
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Subroutine
4
- class OutputNotSetError < StandardError
5
- def initialize(name)
6
- super("Expected output '#{name}' to be set upon completion of perform but was not.")
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Subroutine
4
- class UnknownOutputError < StandardError
5
- def initialize(name)
6
- super("Unknown output '#{name}'")
7
- end
8
- end
9
- end