iry 0.5.1 → 0.6.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
  SHA256:
3
- metadata.gz: 5ca6d5b931545ba2bb0b9f1e9e7ad77da308e7d0ffe8a64d1df2c1e6378cd1a7
4
- data.tar.gz: 4747d18e4a249735907597277bad301e9177dffa5aa00e3410355be13d523683
3
+ metadata.gz: 592290e30f1db830217241ebde319fbf952ee459ac05c3bc1e87b4b47a73e143
4
+ data.tar.gz: '09cabb7faf8e78a91e7d2443bdfd5466d7e8f63bc90fcfeb2abdb72f93bd79bf'
5
5
  SHA512:
6
- metadata.gz: c2b72c6a64b044c606b3940181971a28fd90fdb1ba7859566adb9f5b7ac17f58aa46544908d06715dbc15105972ee0b272ac65d608dd06ee42fd829799c3ff95
7
- data.tar.gz: 2f5c703a19785a8e7fc5689354c80b91d3d3658f00a031edbddad7ca06c36094959f494bbc157c8b40bce4fd3655fd37fa5769ec1fc02e6b7c74524118ebc37b
6
+ metadata.gz: 915d87f39809daa1a0a76ea66c4718e20afe6dbef4ced1853df47e9457927a464a06204cd4c0abd71dad861d8df6f23c974b2a75796ff7136b17f94875fb36ae
7
+ data.tar.gz: f8b10f525eab24f478a3bb6ee2c1039258b65d532eb5475d584f68bec23cf6c2e305e47033b4621dfe49be563da584c488683905d12c9abf529c07ec194d46bc
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.6.0
@@ -30,7 +30,7 @@ module Iry
30
30
  end
31
31
 
32
32
  # @param model [Handlers::Model]
33
- # @return [void]
33
+ # @return [ActiveModel::Error]
34
34
  def apply(model)
35
35
  model.errors.add(key, message)
36
36
  end
@@ -30,7 +30,7 @@ module Iry
30
30
  end
31
31
 
32
32
  # @param model [Handlers::Model]
33
- # @return [void]
33
+ # @return [ActiveModel::Error]
34
34
  def apply(model)
35
35
  model.errors.add(key, message)
36
36
  end
@@ -35,7 +35,7 @@ module Iry
35
35
  end
36
36
 
37
37
  # @param model [Handlers::Model]
38
- # @return [void]
38
+ # @return [ActiveModel::Error]
39
39
  def apply(model)
40
40
  model.errors.add(error_key, message)
41
41
  end
@@ -35,7 +35,7 @@ module Iry
35
35
  end
36
36
 
37
37
  # @param model [Handlers::Model]
38
- # @return [void]
38
+ # @return [ActiveModel::Error]
39
39
  def apply(model)
40
40
  model.errors.add(error_key, message)
41
41
  end
@@ -6,7 +6,7 @@ module Iry
6
6
  # Sets validation errors on the model
7
7
  # @abstract
8
8
  # @param model [Handlers::Model]
9
- # @return [void]
9
+ # @return [ActiveModel::Error]
10
10
  def apply(model)
11
11
  end
12
12
 
@@ -15,9 +15,9 @@ module Iry
15
15
  # Return always false, failing to handle any constraint
16
16
  # @param err [ActiveRecord::StatementInvalid]
17
17
  # @param model [Model] should inherit {ActiveRecord::Base} and`include Iry` to match the interface
18
- # @return [Boolean]
18
+ # @return [nil, ActiveModel::Error]
19
19
  def handle(err, model)
20
- return false
20
+ return nil
21
21
  end
22
22
  end
23
23
  end
@@ -36,7 +36,9 @@ module Iry
36
36
  # Appends constraint errors as model errors
37
37
  # @param err [ActiveRecord::StatementInvalid]
38
38
  # @param model [Model] should inherit {ActiveRecord::Base} and`include Iry` to match the interface
39
- # @return [void]
39
+ # @return [nil, ActiveModel::Error] if handled constraint, returns the
40
+ # error attached to the model. If constraint wasn't handled or handling
41
+ # failed, `nil` is returned
40
42
  def handle(err, model)
41
43
  pgerr = err.cause
42
44
  constraint_name_msg = pgerr.result.error_field(::PG::Constants::PG_DIAG_MESSAGE_PRIMARY)
@@ -44,12 +46,10 @@ module Iry
44
46
  constraint_name = match[1]
45
47
  constraint = model.class.constraints[constraint_name]
46
48
  if constraint.nil?
47
- return false
49
+ return nil
48
50
  end
49
51
 
50
- constraint.apply(model)
51
-
52
- return true
52
+ return constraint.apply(model)
53
53
  end
54
54
  end
55
55
  end
data/lib/iry/handlers.rb CHANGED
@@ -12,7 +12,8 @@ module Iry
12
12
  # @abstract
13
13
  # @param err [ActiveRecord::StatementInvalid] possible constraint error to handle
14
14
  # @param model [Model]
15
- # @return [Boolean] true if this database handler handled the constraint error
15
+ # @return [nil, ActiveModel::Error] `nil` if couldn't handle the error,
16
+ # otherwise the {ActiveModel::Error} added to the model
16
17
  def handle(err, model)
17
18
  end
18
19
  end
data/lib/iry/patch.rb CHANGED
@@ -6,7 +6,7 @@ module Iry
6
6
  # @return [Boolean] true if successful
7
7
  def create_or_update(...)
8
8
  result = false
9
- Iry.handle_constraints!(self) { result = super }
9
+ TransformConstraints.nested_constraints!(self) { result = super }
10
10
  result
11
11
  end
12
12
  end
@@ -0,0 +1,139 @@
1
+ module Iry
2
+ # Implementation of {Iry} methods, helps ensuring the main module focus on
3
+ # documentation
4
+ module TransformConstraints
5
+ extend self
6
+
7
+ # @param model [Handlers::Model]
8
+ # @yield
9
+ # @return [nil, Handlers::Model]
10
+ def handle_constraints(model, &block)
11
+ handle_constraints!(model, &block)
12
+ rescue StatementInvalid
13
+ return nil
14
+ end
15
+
16
+ # @param model [Handlers::Model]
17
+ # @yield
18
+ # @return [Handlers::Model]
19
+ def handle_constraints!(model, &block)
20
+ # Allows checking if Iry has been activated (handling).
21
+ # Number is used to support nested handle_constraints!
22
+ Thread.current[:iry] ||= 0
23
+ Thread.current[:iry] += 1
24
+
25
+ nested_constraints!(model, &block)
26
+ rescue StatementInvalid => err
27
+ # Imports errors from "nested" models back into the parent, to ensure
28
+ # `errors` is populated and the record is considered invalid
29
+
30
+ # Skip if error has been added to the same object being handled
31
+ if err.record.object_id == model.object_id
32
+ raise
33
+ end
34
+
35
+ # Adds the error only if it hasn't been added already
36
+ already_imported = model
37
+ .errors
38
+ .each
39
+ .lazy
40
+ .select { |ae| ae.respond_to?(:inner_error) }
41
+ .map { |ae| ae.inner_error }
42
+ .include?(err.error)
43
+ if !already_imported
44
+ model.errors.import(err.error)
45
+ end
46
+
47
+ raise
48
+ ensure
49
+ # "Pop" handle_constraints! usage, when 0, no constraint handling should
50
+ # happen
51
+ Thread.current[:iry] -= 1
52
+ end
53
+
54
+ # Tracks constraints of models saved as a consequence of saving another
55
+ # model. This usually represents a situation of model using
56
+ # `accepts_nested_attributes_for`
57
+ # @param model [Handlers::Model]
58
+ # @yield
59
+ # @return [Handlers::Model]
60
+ # @private
61
+ def nested_constraints!(model, &block)
62
+ raise ArgumentError, "Block required" if block.nil?
63
+
64
+ block.()
65
+
66
+ return model
67
+ rescue ActiveRecord::StatementInvalid => err
68
+ # Exit immediately if Iry hasn't been activated
69
+ if Thread.current[:iry].nil? || Thread.current[:iry] == 0
70
+ raise
71
+ end
72
+
73
+ # Exception might be an unknown constraint that is not handled by Iry
74
+ # yet. If that's the case, Null handler will ensure that everything
75
+ # proceeds as if Iry wasn't involved
76
+ handler = Handlers::Null
77
+ case
78
+ when Handlers::PG.handle?(err)
79
+ handler = Handlers::PG
80
+ end
81
+
82
+ model_error = handler.handle(err, model)
83
+
84
+ # This constraint is not handled by Iry and should raise normally
85
+ if model_error.nil?
86
+ raise
87
+ end
88
+
89
+ raise(
90
+ StatementInvalid.new(
91
+ err.message,
92
+ sql: err.sql,
93
+ binds: err.binds,
94
+ record: model,
95
+ error: model_error
96
+ )
97
+ )
98
+ end
99
+
100
+ # @param model [Handlers::Model]
101
+ # @return [Boolean]
102
+ def save(model, ...)
103
+ success = nil
104
+ constraint_model = handle_constraints(model) { success = model.save(...) }
105
+
106
+ if constraint_model
107
+ return success
108
+ end
109
+
110
+ return false
111
+ end
112
+
113
+ # @param model [Handlers::Model]
114
+ # @return [true]
115
+ # @raise [ConstraintViolation]
116
+ # @raise [ActiveRecord::RecordInvalid]
117
+ def save!(model, ...)
118
+ constraint_model = handle_constraints(model) { model.save!(...) }
119
+
120
+ if constraint_model
121
+ return true
122
+ end
123
+
124
+ raise ConstraintViolation.new(model)
125
+ end
126
+
127
+ # @param model [Handlers::Model]
128
+ # @return [Handlers::Model]
129
+ def destroy(model)
130
+ constraint_result = handle_constraints(model) { model.destroy }
131
+
132
+ if constraint_result.nil?
133
+ return false
134
+ end
135
+
136
+ return constraint_result
137
+ end
138
+ end
139
+ end
data/lib/iry.rb CHANGED
@@ -12,6 +12,7 @@ require_relative "iry/constraint/exclusion"
12
12
  require_relative "iry/constraint/foreign_key"
13
13
  require_relative "iry/constraint/unique"
14
14
  require_relative "iry/patch"
15
+ require_relative "iry/transform_constraints"
15
16
 
16
17
  # Entrypoint of constraint validation, include in a class inheriting {ActiveRecord::Base} and the following class-level
17
18
  # methods will be available:
@@ -40,7 +41,8 @@ module Iry
40
41
  end
41
42
 
42
43
  # Raised when constraints have been violated and have been converted to
43
- # model errors
44
+ # model errors, on {ActiveRecord::Base#save!} calls, to simulate a behavior
45
+ # similar to {ActiveRecord::RecordInvalid} when it's raised
44
46
  class ConstraintViolation < ActiveRecord::RecordInvalid
45
47
  include Error
46
48
 
@@ -50,8 +52,26 @@ module Iry
50
52
  # @return [Handlers::Model]
51
53
  end
52
54
 
55
+ # Raised when constraints errors happen and go through Iry, even if these
56
+ # are not handled. This class inherits from {ActiveRecord::StatementInvalid}
57
+ # to maximize compatibility with existing code
53
58
  class StatementInvalid < ActiveRecord::StatementInvalid
54
59
  include Error
60
+
61
+ # @return [Handlers::Model] model affected by the constraint violation
62
+ attr_reader :record
63
+ # @return [ActiveModel::Error] error attached to the `record` for the
64
+ # constraint violation
65
+ attr_reader :error
66
+
67
+ # @param message [nil, String]
68
+ # @param record [Handlers::Model]
69
+ # @param error [ActiveModel::Error]
70
+ def initialize(message = nil, record:, error:, **kwargs)
71
+ @record = record
72
+ @error = error
73
+ super(message, **kwargs)
74
+ end
55
75
  end
56
76
 
57
77
  # @param klass [Module]
@@ -88,9 +108,7 @@ module Iry
88
108
  # result #=> nil
89
109
  # fail_user.errors.details.fetch(:email) #=> [{error: :taken}]
90
110
  def self.handle_constraints(model, &block)
91
- handle_constraints!(model, &block)
92
- rescue StatementInvalid
93
- return nil
111
+ TransformConstraints.handle_constraints(model, &block)
94
112
  end
95
113
 
96
114
  # Executes block and in case of constraints violations on `model`, block is
@@ -100,26 +118,7 @@ module Iry
100
118
  # @yield block must perform the save operation, usually with `save`
101
119
  # @return [Handlers::Model] returns `model` parameter
102
120
  def self.handle_constraints!(model, &block)
103
- raise ArgumentError, "Block required" if block.nil?
104
-
105
- block.()
106
-
107
- return model
108
- rescue ActiveRecord::StatementInvalid => err
109
- handler = Handlers::Null
110
- case
111
- when Handlers::PG.handle?(err)
112
- handler = Handlers::PG
113
- end
114
-
115
- is_handled = handler.handle(err, model)
116
-
117
- # This constraint is not handled by Iry and should raise normally
118
- if !is_handled
119
- raise
120
- end
121
-
122
- raise StatementInvalid.new(err.message, sql: err.sql, binds: err.binds)
121
+ TransformConstraints.handle_constraints!(model, &block)
123
122
  end
124
123
 
125
124
  # Similar to {ActiveRecord::Base#save} but in case of constraint violations,
@@ -129,14 +128,7 @@ module Iry
129
128
  # @param model [Handlers::Model] model to save
130
129
  # @return [Boolean] `true` if successful
131
130
  def self.save(model, ...)
132
- success = nil
133
- constraint_model = handle_constraints(model) { success = model.save(...) }
134
-
135
- if constraint_model
136
- return success
137
- end
138
-
139
- return false
131
+ TransformConstraints.save(model, ...)
140
132
  end
141
133
 
142
134
  # Similar to {ActiveRecord::Base#save!} but in case of constraint violations,
@@ -151,13 +143,7 @@ module Iry
151
143
  # @raise [ActiveRecord::RecordInvalid] triggered when a validation error is
152
144
  # raised, but not a constraint violation
153
145
  def self.save!(model, ...)
154
- constraint_model = handle_constraints(model) { model.save!(...) }
155
-
156
- if constraint_model
157
- return true
158
- end
159
-
160
- raise ConstraintViolation.new(model)
146
+ TransformConstraints.save!(model, ...)
161
147
  end
162
148
 
163
149
  # Similar to {ActiveRecord::Base#destroy} but in case of constraint
@@ -165,12 +151,6 @@ module Iry
165
151
  # @param model [Handlers::Model] model to destroy
166
152
  # @return [Handlers::Model] the destroyed model
167
153
  def self.destroy(model)
168
- constraint_result = handle_constraints(model) { model.destroy }
169
-
170
- if constraint_result.nil?
171
- return false
172
- end
173
-
174
- return constraint_result
154
+ TransformConstraints.destroy(model)
175
155
  end
176
156
  end
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "iry",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "iry",
9
- "version": "0.5.1",
9
+ "version": "0.6.0",
10
10
  "license": "MIT",
11
11
  "devDependencies": {
12
12
  "conventional-changelog-cli": ">= 3.0.0",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iry",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Transform database constraint errors into activerecord validation errors",
5
5
  "private": true,
6
6
  "main": "index.js",
data/rbi/iry.rbi CHANGED
@@ -101,13 +101,44 @@ module Iry
101
101
  end
102
102
 
103
103
  # Raised when constraints have been violated and have been converted to
104
- # model errors
104
+ # model errors, on {ActiveRecord::Base#save!} calls, to simulate a behavior
105
+ # similar to {ActiveRecord::RecordInvalid} when it's raised
105
106
  class ConstraintViolation < ActiveRecord::RecordInvalid
106
107
  include Iry::Error
107
108
  end
108
109
 
110
+ # Raised when constraints errors happen and go through Iry, even if these
111
+ # are not handled. This class inherits from {ActiveRecord::StatementInvalid}
112
+ # to maximize compatibility with existing code
109
113
  class StatementInvalid < ActiveRecord::StatementInvalid
110
114
  include Iry::Error
115
+
116
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
117
+ # sord omit - no YARD type given for "**kwargs", using untyped
118
+ # _@param_ `message`
119
+ #
120
+ # _@param_ `record`
121
+ #
122
+ # _@param_ `error`
123
+ sig do
124
+ params(
125
+ message: T.nilable(String),
126
+ record: Handlers::Model,
127
+ error: ActiveModel::Error,
128
+ kwargs: T.untyped
129
+ ).void
130
+ end
131
+ def initialize(message = nil, record:, error:, **kwargs); end
132
+
133
+ # _@return_ — model affected by the constraint violation
134
+ sig { returns(Handlers::Model) }
135
+ attr_reader :record
136
+
137
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
138
+ # _@return_ — error attached to the `record` for the
139
+ # constraint violation
140
+ sig { returns(ActiveModel::Error) }
141
+ attr_reader :error
111
142
  end
112
143
 
113
144
  # Overrides private API method {ActiveRecord#create_or_update} to handle
@@ -201,8 +232,9 @@ module Iry
201
232
  #
202
233
  # _@param_ `model`
203
234
  #
204
- # _@return_ — true if this database handler handled the constraint error
205
- sig { params(err: ActiveRecord::StatementInvalid, model: Model).returns(T::Boolean) }
235
+ # _@return_ — `nil` if couldn't handle the error,
236
+ # otherwise the {ActiveModel::Error} added to the model
237
+ sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
206
238
  def handle(err, model); end
207
239
  end
208
240
 
@@ -257,6 +289,10 @@ module Iry
257
289
  # _@param_ `err`
258
290
  #
259
291
  # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
292
+ #
293
+ # _@return_ — if handled constraint, returns the
294
+ # error attached to the model. If constraint wasn't handled or handling
295
+ # failed, `nil` is returned
260
296
  sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
261
297
  def handle(err, model); end
262
298
 
@@ -275,6 +311,10 @@ module Iry
275
311
  # _@param_ `err`
276
312
  #
277
313
  # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
314
+ #
315
+ # _@return_ — if handled constraint, returns the
316
+ # error attached to the model. If constraint wasn't handled or handling
317
+ # failed, `nil` is returned
278
318
  sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
279
319
  def self.handle(err, model); end
280
320
  end
@@ -297,7 +337,7 @@ module Iry
297
337
  # _@param_ `err`
298
338
  #
299
339
  # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
300
- sig { params(err: ActiveRecord::StatementInvalid, model: Model).returns(T::Boolean) }
340
+ sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
301
341
  def handle(err, model); end
302
342
 
303
343
  # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
@@ -313,7 +353,7 @@ module Iry
313
353
  # _@param_ `err`
314
354
  #
315
355
  # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
316
- sig { params(err: ActiveRecord::StatementInvalid, model: Model).returns(T::Boolean) }
356
+ sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
317
357
  def self.handle(err, model); end
318
358
  end
319
359
  end
@@ -337,10 +377,11 @@ module Iry
337
377
  # A constraint has a name and can apply errors to an object inheriting from {ActiveRecord::Base}
338
378
  # @abstract
339
379
  module Constraint
380
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
340
381
  # Sets validation errors on the model
341
382
  #
342
383
  # _@param_ `model`
343
- sig { params(model: Handlers::Model).void }
384
+ sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
344
385
  def apply(model); end
345
386
 
346
387
  # Name of the constraint to be caught from the database
@@ -369,8 +410,9 @@ module Iry
369
410
  sig { params(key: Symbol, name: String, message: T.any(Symbol, String)).void }
370
411
  def initialize(key, name:, message: :invalid); end
371
412
 
413
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
372
414
  # _@param_ `model`
373
- sig { params(model: Handlers::Model).void }
415
+ sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
374
416
  def apply(model); end
375
417
 
376
418
  sig { returns(Symbol) }
@@ -409,8 +451,9 @@ module Iry
409
451
  end
410
452
  def initialize(keys, name:, error_key:, message: :taken); end
411
453
 
454
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
412
455
  # _@param_ `model`
413
- sig { params(model: Handlers::Model).void }
456
+ sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
414
457
  def apply(model); end
415
458
 
416
459
  sig { returns(T::Array[Symbol]) }
@@ -443,8 +486,9 @@ module Iry
443
486
  sig { params(key: Symbol, name: String, message: T.any(Symbol, String)).void }
444
487
  def initialize(key, name:, message: :taken); end
445
488
 
489
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
446
490
  # _@param_ `model`
447
- sig { params(model: Handlers::Model).void }
491
+ sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
448
492
  def apply(model); end
449
493
 
450
494
  sig { returns(Symbol) }
@@ -483,8 +527,9 @@ module Iry
483
527
  end
484
528
  def initialize(keys, name:, error_key:, message: :required); end
485
529
 
530
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
486
531
  # _@param_ `model`
487
- sig { params(model: Handlers::Model).void }
532
+ sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
488
533
  def apply(model); end
489
534
 
490
535
  sig { returns(T::Array[Symbol]) }
@@ -500,4 +545,66 @@ module Iry
500
545
  attr_accessor :error_key
501
546
  end
502
547
  end
548
+
549
+ # Implementation of {Iry} methods, helps ensuring the main module focus on
550
+ # documentation
551
+ module TransformConstraints
552
+ extend Iry::TransformConstraints
553
+
554
+ # _@param_ `model`
555
+ sig { params(model: Handlers::Model, block: T.untyped).void }
556
+ def handle_constraints(model, &block); end
557
+
558
+ # _@param_ `model`
559
+ sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
560
+ def handle_constraints!(model, &block); end
561
+
562
+ # Tracks constraints of models saved as a consequence of saving another
563
+ # model. This usually represents a situation of model using
564
+ # `accepts_nested_attributes_for`
565
+ #
566
+ # _@param_ `model`
567
+ sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
568
+ def nested_constraints!(model, &block); end
569
+
570
+ # _@param_ `model`
571
+ sig { params(model: Handlers::Model).returns(T::Boolean) }
572
+ def save(model); end
573
+
574
+ # _@param_ `model`
575
+ sig { params(model: Handlers::Model).returns(T::Boolean) }
576
+ def save!(model); end
577
+
578
+ # _@param_ `model`
579
+ sig { params(model: Handlers::Model).returns(Handlers::Model) }
580
+ def destroy(model); end
581
+
582
+ # _@param_ `model`
583
+ sig { params(model: Handlers::Model, block: T.untyped).void }
584
+ def self.handle_constraints(model, &block); end
585
+
586
+ # _@param_ `model`
587
+ sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
588
+ def self.handle_constraints!(model, &block); end
589
+
590
+ # Tracks constraints of models saved as a consequence of saving another
591
+ # model. This usually represents a situation of model using
592
+ # `accepts_nested_attributes_for`
593
+ #
594
+ # _@param_ `model`
595
+ sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
596
+ def self.nested_constraints!(model, &block); end
597
+
598
+ # _@param_ `model`
599
+ sig { params(model: Handlers::Model).returns(T::Boolean) }
600
+ def self.save(model); end
601
+
602
+ # _@param_ `model`
603
+ sig { params(model: Handlers::Model).returns(T::Boolean) }
604
+ def self.save!(model); end
605
+
606
+ # _@param_ `model`
607
+ sig { params(model: Handlers::Model).returns(Handlers::Model) }
608
+ def self.destroy(model); end
609
+ end
503
610
  end
data/sig/iry.rbs CHANGED
@@ -93,13 +93,39 @@ module Iry
93
93
  end
94
94
 
95
95
  # Raised when constraints have been violated and have been converted to
96
- # model errors
96
+ # model errors, on {ActiveRecord::Base#save!} calls, to simulate a behavior
97
+ # similar to {ActiveRecord::RecordInvalid} when it's raised
97
98
  class ConstraintViolation < ActiveRecord::RecordInvalid
98
99
  include Iry::Error
99
100
  end
100
101
 
102
+ # Raised when constraints errors happen and go through Iry, even if these
103
+ # are not handled. This class inherits from {ActiveRecord::StatementInvalid}
104
+ # to maximize compatibility with existing code
101
105
  class StatementInvalid < ActiveRecord::StatementInvalid
102
106
  include Iry::Error
107
+
108
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
109
+ # sord omit - no YARD type given for "**kwargs", using untyped
110
+ # _@param_ `message`
111
+ #
112
+ # _@param_ `record`
113
+ #
114
+ # _@param_ `error`
115
+ def initialize: (
116
+ ?String? message,
117
+ record: Handlers::Model,
118
+ error: ActiveModel::Error,
119
+ **untyped kwargs
120
+ ) -> void
121
+
122
+ # _@return_ — model affected by the constraint violation
123
+ attr_reader record: Handlers::Model
124
+
125
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
126
+ # _@return_ — error attached to the `record` for the
127
+ # constraint violation
128
+ attr_reader error: ActiveModel::Error
103
129
  end
104
130
 
105
131
  # Overrides private API method {ActiveRecord#create_or_update} to handle
@@ -182,8 +208,9 @@ module Iry
182
208
  #
183
209
  # _@param_ `model`
184
210
  #
185
- # _@return_ — true if this database handler handled the constraint error
186
- def handle: (ActiveRecord::StatementInvalid err, Model model) -> bool
211
+ # _@return_ — `nil` if couldn't handle the error,
212
+ # otherwise the {ActiveModel::Error} added to the model
213
+ def handle: (ActiveRecord::StatementInvalid err, Model model) -> void
187
214
  end
188
215
 
189
216
  # Interface of the model class. This class is usually inherits from {ActiveRecord::Base}
@@ -224,6 +251,10 @@ module Iry
224
251
  # _@param_ `err`
225
252
  #
226
253
  # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
254
+ #
255
+ # _@return_ — if handled constraint, returns the
256
+ # error attached to the model. If constraint wasn't handled or handling
257
+ # failed, `nil` is returned
227
258
  def handle: (ActiveRecord::StatementInvalid err, Model model) -> void
228
259
 
229
260
  # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
@@ -240,6 +271,10 @@ module Iry
240
271
  # _@param_ `err`
241
272
  #
242
273
  # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
274
+ #
275
+ # _@return_ — if handled constraint, returns the
276
+ # error attached to the model. If constraint wasn't handled or handling
277
+ # failed, `nil` is returned
243
278
  def self.handle: (ActiveRecord::StatementInvalid err, Model model) -> void
244
279
  end
245
280
 
@@ -260,7 +295,7 @@ module Iry
260
295
  # _@param_ `err`
261
296
  #
262
297
  # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
263
- def handle: (ActiveRecord::StatementInvalid err, Model model) -> bool
298
+ def handle: (ActiveRecord::StatementInvalid err, Model model) -> void
264
299
 
265
300
  # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
266
301
  # Returns always true, catching any unhandled database exception
@@ -274,7 +309,7 @@ module Iry
274
309
  # _@param_ `err`
275
310
  #
276
311
  # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
277
- def self.handle: (ActiveRecord::StatementInvalid err, Model model) -> bool
312
+ def self.handle: (ActiveRecord::StatementInvalid err, Model model) -> void
278
313
  end
279
314
  end
280
315
 
@@ -295,10 +330,11 @@ module Iry
295
330
  # A constraint has a name and can apply errors to an object inheriting from {ActiveRecord::Base}
296
331
  # @abstract
297
332
  module Constraint
333
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
298
334
  # Sets validation errors on the model
299
335
  #
300
336
  # _@param_ `model`
301
- def apply: (Handlers::Model model) -> void
337
+ def apply: (Handlers::Model model) -> ActiveModel::Error
302
338
 
303
339
  # Name of the constraint to be caught from the database
304
340
  def name: () -> String
@@ -322,8 +358,9 @@ module Iry
322
358
  # _@param_ `name` — constraint name
323
359
  def initialize: (Symbol key, name: String, ?message: (Symbol | String)) -> void
324
360
 
361
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
325
362
  # _@param_ `model`
326
- def apply: (Handlers::Model model) -> void
363
+ def apply: (Handlers::Model model) -> ActiveModel::Error
327
364
 
328
365
  attr_accessor key: Symbol
329
366
 
@@ -354,8 +391,9 @@ module Iry
354
391
  ?message: (Symbol | String)
355
392
  ) -> void
356
393
 
394
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
357
395
  # _@param_ `model`
358
- def apply: (Handlers::Model model) -> void
396
+ def apply: (Handlers::Model model) -> ActiveModel::Error
359
397
 
360
398
  attr_accessor keys: ::Array[Symbol]
361
399
 
@@ -381,8 +419,9 @@ module Iry
381
419
  # _@param_ `name` — constraint name
382
420
  def initialize: (Symbol key, name: String, ?message: (Symbol | String)) -> void
383
421
 
422
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
384
423
  # _@param_ `model`
385
- def apply: (Handlers::Model model) -> void
424
+ def apply: (Handlers::Model model) -> ActiveModel::Error
386
425
 
387
426
  attr_accessor key: Symbol
388
427
 
@@ -413,8 +452,9 @@ module Iry
413
452
  ?message: (Symbol | String)
414
453
  ) -> void
415
454
 
455
+ # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
416
456
  # _@param_ `model`
417
- def apply: (Handlers::Model model) -> void
457
+ def apply: (Handlers::Model model) -> ActiveModel::Error
418
458
 
419
459
  attr_accessor keys: ::Array[Symbol]
420
460
 
@@ -425,4 +465,54 @@ module Iry
425
465
  attr_accessor error_key: Symbol
426
466
  end
427
467
  end
468
+
469
+ # Implementation of {Iry} methods, helps ensuring the main module focus on
470
+ # documentation
471
+ module TransformConstraints
472
+ extend Iry::TransformConstraints
473
+
474
+ # _@param_ `model`
475
+ def handle_constraints: (Handlers::Model model) -> void
476
+
477
+ # _@param_ `model`
478
+ def handle_constraints!: (Handlers::Model model) -> Handlers::Model
479
+
480
+ # Tracks constraints of models saved as a consequence of saving another
481
+ # model. This usually represents a situation of model using
482
+ # `accepts_nested_attributes_for`
483
+ #
484
+ # _@param_ `model`
485
+ def nested_constraints!: (Handlers::Model model) -> Handlers::Model
486
+
487
+ # _@param_ `model`
488
+ def save: (Handlers::Model model) -> bool
489
+
490
+ # _@param_ `model`
491
+ def save!: (Handlers::Model model) -> bool
492
+
493
+ # _@param_ `model`
494
+ def destroy: (Handlers::Model model) -> Handlers::Model
495
+
496
+ # _@param_ `model`
497
+ def self.handle_constraints: (Handlers::Model model) -> void
498
+
499
+ # _@param_ `model`
500
+ def self.handle_constraints!: (Handlers::Model model) -> Handlers::Model
501
+
502
+ # Tracks constraints of models saved as a consequence of saving another
503
+ # model. This usually represents a situation of model using
504
+ # `accepts_nested_attributes_for`
505
+ #
506
+ # _@param_ `model`
507
+ def self.nested_constraints!: (Handlers::Model model) -> Handlers::Model
508
+
509
+ # _@param_ `model`
510
+ def self.save: (Handlers::Model model) -> bool
511
+
512
+ # _@param_ `model`
513
+ def self.save!: (Handlers::Model model) -> bool
514
+
515
+ # _@param_ `model`
516
+ def self.destroy: (Handlers::Model model) -> Handlers::Model
517
+ end
428
518
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francesco Belladonna
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-11 00:00:00.000000000 Z
11
+ date: 2023-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -107,6 +107,7 @@ files:
107
107
  - lib/iry/handlers/pg.rb
108
108
  - lib/iry/macros.rb
109
109
  - lib/iry/patch.rb
110
+ - lib/iry/transform_constraints.rb
110
111
  - lib/iry/version.rb
111
112
  - package-lock.json
112
113
  - package.json