iry 0.5.0 → 0.6.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 +4 -4
- data/VERSION +1 -1
- data/lib/iry/constraint/check.rb +1 -1
- data/lib/iry/constraint/exclusion.rb +1 -1
- data/lib/iry/constraint/foreign_key.rb +1 -1
- data/lib/iry/constraint/unique.rb +1 -1
- data/lib/iry/constraint.rb +1 -1
- data/lib/iry/handlers/null.rb +2 -2
- data/lib/iry/handlers/pg.rb +5 -5
- data/lib/iry/handlers.rb +2 -1
- data/lib/iry/patch.rb +1 -1
- data/lib/iry/transform_constraints.rb +139 -0
- data/lib/iry.rb +26 -46
- data/package-lock.json +2 -2
- data/package.json +1 -1
- data/rbi/iry.rbi +150 -11
- data/sig/iry.rbs +129 -10
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 592290e30f1db830217241ebde319fbf952ee459ac05c3bc1e87b4b47a73e143
|
4
|
+
data.tar.gz: '09cabb7faf8e78a91e7d2443bdfd5466d7e8f63bc90fcfeb2abdb72f93bd79bf'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 915d87f39809daa1a0a76ea66c4718e20afe6dbef4ced1853df47e9457927a464a06204cd4c0abd71dad861d8df6f23c974b2a75796ff7136b17f94875fb36ae
|
7
|
+
data.tar.gz: f8b10f525eab24f478a3bb6ee2c1039258b65d532eb5475d584f68bec23cf6c2e305e47033b4621dfe49be563da584c488683905d12c9abf529c07ec194d46bc
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/lib/iry/constraint/check.rb
CHANGED
data/lib/iry/constraint.rb
CHANGED
data/lib/iry/handlers/null.rb
CHANGED
@@ -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 [
|
18
|
+
# @return [nil, ActiveModel::Error]
|
19
19
|
def handle(err, model)
|
20
|
-
return
|
20
|
+
return nil
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
data/lib/iry/handlers/pg.rb
CHANGED
@@ -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 [
|
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
|
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 [
|
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
@@ -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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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.
|
9
|
+
"version": "0.6.0",
|
10
10
|
"license": "MIT",
|
11
11
|
"devDependencies": {
|
12
12
|
"conventional-changelog-cli": ">= 3.0.0",
|
data/package.json
CHANGED
data/rbi/iry.rbi
CHANGED
@@ -57,6 +57,15 @@ module Iry
|
|
57
57
|
sig { params(model: Handlers::Model, block: T.untyped).void }
|
58
58
|
def self.handle_constraints(model, &block); end
|
59
59
|
|
60
|
+
# Executes block and in case of constraints violations on `model`, block is
|
61
|
+
# halted, errors are appended to `model` and {StatementInvalid} is raised
|
62
|
+
#
|
63
|
+
# _@param_ `model` — model object for which constraints should be monitored and for which errors should be added to
|
64
|
+
#
|
65
|
+
# _@return_ — returns `model` parameter
|
66
|
+
sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
|
67
|
+
def self.handle_constraints!(model, &block); end
|
68
|
+
|
60
69
|
# Similar to {ActiveRecord::Base#save} but in case of constraint violations,
|
61
70
|
# `false` is returned and `errors` are populated.
|
62
71
|
# Aside from `model`, it takes the same arguments as
|
@@ -77,17 +86,71 @@ module Iry
|
|
77
86
|
sig { params(model: Handlers::Model).returns(T::Boolean) }
|
78
87
|
def self.save!(model); end
|
79
88
|
|
89
|
+
# Similar to {ActiveRecord::Base#destroy} but in case of constraint
|
90
|
+
# violations, `false` is returned and `errors` are populated.
|
91
|
+
#
|
92
|
+
# _@param_ `model` — model to destroy
|
93
|
+
#
|
94
|
+
# _@return_ — the destroyed model
|
95
|
+
sig { params(model: Handlers::Model).returns(Handlers::Model) }
|
96
|
+
def self.destroy(model); end
|
97
|
+
|
80
98
|
# Included in all exceptions triggered by Iry, this allows to rescue any
|
81
99
|
# gem-related exception by rescuing {Iry::Error}
|
82
100
|
module Error
|
83
101
|
end
|
84
102
|
|
85
103
|
# Raised when constraints have been violated and have been converted to
|
86
|
-
# model errors
|
104
|
+
# model errors, on {ActiveRecord::Base#save!} calls, to simulate a behavior
|
105
|
+
# similar to {ActiveRecord::RecordInvalid} when it's raised
|
87
106
|
class ConstraintViolation < ActiveRecord::RecordInvalid
|
88
107
|
include Iry::Error
|
89
108
|
end
|
90
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
|
113
|
+
class StatementInvalid < ActiveRecord::StatementInvalid
|
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
|
142
|
+
end
|
143
|
+
|
144
|
+
# Overrides private API method {ActiveRecord#create_or_update} to handle
|
145
|
+
# constraints and attach errors to the including model
|
146
|
+
module Patch
|
147
|
+
# Takes attributes as named arguments
|
148
|
+
#
|
149
|
+
# _@return_ — true if successful
|
150
|
+
sig { returns(T::Boolean) }
|
151
|
+
def create_or_update; end
|
152
|
+
end
|
153
|
+
|
91
154
|
# Class-level methods available to classes executing `include Iry`
|
92
155
|
module Macros
|
93
156
|
# Constraints by name
|
@@ -169,8 +232,9 @@ module Iry
|
|
169
232
|
#
|
170
233
|
# _@param_ `model`
|
171
234
|
#
|
172
|
-
# _@return_ —
|
173
|
-
|
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 }
|
174
238
|
def handle(err, model); end
|
175
239
|
end
|
176
240
|
|
@@ -207,7 +271,7 @@ module Iry
|
|
207
271
|
exclusion\sconstraint|
|
208
272
|
foreign\skey\sconstraint
|
209
273
|
)
|
210
|
-
\s"(
|
274
|
+
\s"([^"]+)"
|
211
275
|
}x, T.untyped)
|
212
276
|
|
213
277
|
# sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
|
@@ -225,6 +289,10 @@ module Iry
|
|
225
289
|
# _@param_ `err`
|
226
290
|
#
|
227
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
|
228
296
|
sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
|
229
297
|
def handle(err, model); end
|
230
298
|
|
@@ -243,6 +311,10 @@ module Iry
|
|
243
311
|
# _@param_ `err`
|
244
312
|
#
|
245
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
|
246
318
|
sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
|
247
319
|
def self.handle(err, model); end
|
248
320
|
end
|
@@ -265,7 +337,7 @@ module Iry
|
|
265
337
|
# _@param_ `err`
|
266
338
|
#
|
267
339
|
# _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
|
268
|
-
sig { params(err: ActiveRecord::StatementInvalid, model: Model).
|
340
|
+
sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
|
269
341
|
def handle(err, model); end
|
270
342
|
|
271
343
|
# sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
|
@@ -281,7 +353,7 @@ module Iry
|
|
281
353
|
# _@param_ `err`
|
282
354
|
#
|
283
355
|
# _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
|
284
|
-
sig { params(err: ActiveRecord::StatementInvalid, model: Model).
|
356
|
+
sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
|
285
357
|
def self.handle(err, model); end
|
286
358
|
end
|
287
359
|
end
|
@@ -305,10 +377,11 @@ module Iry
|
|
305
377
|
# A constraint has a name and can apply errors to an object inheriting from {ActiveRecord::Base}
|
306
378
|
# @abstract
|
307
379
|
module Constraint
|
380
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
308
381
|
# Sets validation errors on the model
|
309
382
|
#
|
310
383
|
# _@param_ `model`
|
311
|
-
sig { params(model: Handlers::Model).
|
384
|
+
sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
|
312
385
|
def apply(model); end
|
313
386
|
|
314
387
|
# Name of the constraint to be caught from the database
|
@@ -337,8 +410,9 @@ module Iry
|
|
337
410
|
sig { params(key: Symbol, name: String, message: T.any(Symbol, String)).void }
|
338
411
|
def initialize(key, name:, message: :invalid); end
|
339
412
|
|
413
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
340
414
|
# _@param_ `model`
|
341
|
-
sig { params(model: Handlers::Model).
|
415
|
+
sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
|
342
416
|
def apply(model); end
|
343
417
|
|
344
418
|
sig { returns(Symbol) }
|
@@ -377,8 +451,9 @@ module Iry
|
|
377
451
|
end
|
378
452
|
def initialize(keys, name:, error_key:, message: :taken); end
|
379
453
|
|
454
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
380
455
|
# _@param_ `model`
|
381
|
-
sig { params(model: Handlers::Model).
|
456
|
+
sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
|
382
457
|
def apply(model); end
|
383
458
|
|
384
459
|
sig { returns(T::Array[Symbol]) }
|
@@ -411,8 +486,9 @@ module Iry
|
|
411
486
|
sig { params(key: Symbol, name: String, message: T.any(Symbol, String)).void }
|
412
487
|
def initialize(key, name:, message: :taken); end
|
413
488
|
|
489
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
414
490
|
# _@param_ `model`
|
415
|
-
sig { params(model: Handlers::Model).
|
491
|
+
sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
|
416
492
|
def apply(model); end
|
417
493
|
|
418
494
|
sig { returns(Symbol) }
|
@@ -451,8 +527,9 @@ module Iry
|
|
451
527
|
end
|
452
528
|
def initialize(keys, name:, error_key:, message: :required); end
|
453
529
|
|
530
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
454
531
|
# _@param_ `model`
|
455
|
-
sig { params(model: Handlers::Model).
|
532
|
+
sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
|
456
533
|
def apply(model); end
|
457
534
|
|
458
535
|
sig { returns(T::Array[Symbol]) }
|
@@ -468,4 +545,66 @@ module Iry
|
|
468
545
|
attr_accessor :error_key
|
469
546
|
end
|
470
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
|
471
610
|
end
|
data/sig/iry.rbs
CHANGED
@@ -53,6 +53,14 @@ module Iry
|
|
53
53
|
# ```
|
54
54
|
def self.handle_constraints: (Handlers::Model model) -> void
|
55
55
|
|
56
|
+
# Executes block and in case of constraints violations on `model`, block is
|
57
|
+
# halted, errors are appended to `model` and {StatementInvalid} is raised
|
58
|
+
#
|
59
|
+
# _@param_ `model` — model object for which constraints should be monitored and for which errors should be added to
|
60
|
+
#
|
61
|
+
# _@return_ — returns `model` parameter
|
62
|
+
def self.handle_constraints!: (Handlers::Model model) -> Handlers::Model
|
63
|
+
|
56
64
|
# Similar to {ActiveRecord::Base#save} but in case of constraint violations,
|
57
65
|
# `false` is returned and `errors` are populated.
|
58
66
|
# Aside from `model`, it takes the same arguments as
|
@@ -71,17 +79,64 @@ module Iry
|
|
71
79
|
# _@param_ `model` — model to save
|
72
80
|
def self.save!: (Handlers::Model model) -> bool
|
73
81
|
|
82
|
+
# Similar to {ActiveRecord::Base#destroy} but in case of constraint
|
83
|
+
# violations, `false` is returned and `errors` are populated.
|
84
|
+
#
|
85
|
+
# _@param_ `model` — model to destroy
|
86
|
+
#
|
87
|
+
# _@return_ — the destroyed model
|
88
|
+
def self.destroy: (Handlers::Model model) -> Handlers::Model
|
89
|
+
|
74
90
|
# Included in all exceptions triggered by Iry, this allows to rescue any
|
75
91
|
# gem-related exception by rescuing {Iry::Error}
|
76
92
|
module Error
|
77
93
|
end
|
78
94
|
|
79
95
|
# Raised when constraints have been violated and have been converted to
|
80
|
-
# model errors
|
96
|
+
# model errors, on {ActiveRecord::Base#save!} calls, to simulate a behavior
|
97
|
+
# similar to {ActiveRecord::RecordInvalid} when it's raised
|
81
98
|
class ConstraintViolation < ActiveRecord::RecordInvalid
|
82
99
|
include Iry::Error
|
83
100
|
end
|
84
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
|
105
|
+
class StatementInvalid < ActiveRecord::StatementInvalid
|
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
|
129
|
+
end
|
130
|
+
|
131
|
+
# Overrides private API method {ActiveRecord#create_or_update} to handle
|
132
|
+
# constraints and attach errors to the including model
|
133
|
+
module Patch
|
134
|
+
# Takes attributes as named arguments
|
135
|
+
#
|
136
|
+
# _@return_ — true if successful
|
137
|
+
def create_or_update: () -> bool
|
138
|
+
end
|
139
|
+
|
85
140
|
# Class-level methods available to classes executing `include Iry`
|
86
141
|
module Macros
|
87
142
|
# Constraints by name
|
@@ -153,8 +208,9 @@ module Iry
|
|
153
208
|
#
|
154
209
|
# _@param_ `model`
|
155
210
|
#
|
156
|
-
# _@return_ —
|
157
|
-
|
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
|
158
214
|
end
|
159
215
|
|
160
216
|
# Interface of the model class. This class is usually inherits from {ActiveRecord::Base}
|
@@ -195,6 +251,10 @@ module Iry
|
|
195
251
|
# _@param_ `err`
|
196
252
|
#
|
197
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
|
198
258
|
def handle: (ActiveRecord::StatementInvalid err, Model model) -> void
|
199
259
|
|
200
260
|
# sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
|
@@ -211,6 +271,10 @@ module Iry
|
|
211
271
|
# _@param_ `err`
|
212
272
|
#
|
213
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
|
214
278
|
def self.handle: (ActiveRecord::StatementInvalid err, Model model) -> void
|
215
279
|
end
|
216
280
|
|
@@ -231,7 +295,7 @@ module Iry
|
|
231
295
|
# _@param_ `err`
|
232
296
|
#
|
233
297
|
# _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
|
234
|
-
def handle: (ActiveRecord::StatementInvalid err, Model model) ->
|
298
|
+
def handle: (ActiveRecord::StatementInvalid err, Model model) -> void
|
235
299
|
|
236
300
|
# sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
|
237
301
|
# Returns always true, catching any unhandled database exception
|
@@ -245,7 +309,7 @@ module Iry
|
|
245
309
|
# _@param_ `err`
|
246
310
|
#
|
247
311
|
# _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
|
248
|
-
def self.handle: (ActiveRecord::StatementInvalid err, Model model) ->
|
312
|
+
def self.handle: (ActiveRecord::StatementInvalid err, Model model) -> void
|
249
313
|
end
|
250
314
|
end
|
251
315
|
|
@@ -266,10 +330,11 @@ module Iry
|
|
266
330
|
# A constraint has a name and can apply errors to an object inheriting from {ActiveRecord::Base}
|
267
331
|
# @abstract
|
268
332
|
module Constraint
|
333
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
269
334
|
# Sets validation errors on the model
|
270
335
|
#
|
271
336
|
# _@param_ `model`
|
272
|
-
def apply: (Handlers::Model model) ->
|
337
|
+
def apply: (Handlers::Model model) -> ActiveModel::Error
|
273
338
|
|
274
339
|
# Name of the constraint to be caught from the database
|
275
340
|
def name: () -> String
|
@@ -293,8 +358,9 @@ module Iry
|
|
293
358
|
# _@param_ `name` — constraint name
|
294
359
|
def initialize: (Symbol key, name: String, ?message: (Symbol | String)) -> void
|
295
360
|
|
361
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
296
362
|
# _@param_ `model`
|
297
|
-
def apply: (Handlers::Model model) ->
|
363
|
+
def apply: (Handlers::Model model) -> ActiveModel::Error
|
298
364
|
|
299
365
|
attr_accessor key: Symbol
|
300
366
|
|
@@ -325,8 +391,9 @@ module Iry
|
|
325
391
|
?message: (Symbol | String)
|
326
392
|
) -> void
|
327
393
|
|
394
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
328
395
|
# _@param_ `model`
|
329
|
-
def apply: (Handlers::Model model) ->
|
396
|
+
def apply: (Handlers::Model model) -> ActiveModel::Error
|
330
397
|
|
331
398
|
attr_accessor keys: ::Array[Symbol]
|
332
399
|
|
@@ -352,8 +419,9 @@ module Iry
|
|
352
419
|
# _@param_ `name` — constraint name
|
353
420
|
def initialize: (Symbol key, name: String, ?message: (Symbol | String)) -> void
|
354
421
|
|
422
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
355
423
|
# _@param_ `model`
|
356
|
-
def apply: (Handlers::Model model) ->
|
424
|
+
def apply: (Handlers::Model model) -> ActiveModel::Error
|
357
425
|
|
358
426
|
attr_accessor key: Symbol
|
359
427
|
|
@@ -384,8 +452,9 @@ module Iry
|
|
384
452
|
?message: (Symbol | String)
|
385
453
|
) -> void
|
386
454
|
|
455
|
+
# sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
|
387
456
|
# _@param_ `model`
|
388
|
-
def apply: (Handlers::Model model) ->
|
457
|
+
def apply: (Handlers::Model model) -> ActiveModel::Error
|
389
458
|
|
390
459
|
attr_accessor keys: ::Array[Symbol]
|
391
460
|
|
@@ -396,4 +465,54 @@ module Iry
|
|
396
465
|
attr_accessor error_key: Symbol
|
397
466
|
end
|
398
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
|
399
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.
|
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
|
+
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
|