iry 0.8.0 → 0.9.1

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.
data/rbi/iry.rbi DELETED
@@ -1,612 +0,0 @@
1
- # typed: strong
2
- # Entrypoint of constraint validation, include in a class inheriting {ActiveRecord::Base} and the following class-level
3
- # methods will be available:
4
- # - {Macros#constraints}
5
- # - {Macros#check_constraint}
6
- # - {Macros#exclusion_constraint}
7
- # - {Macros#foreign_key_constraint}
8
- # - {Macros#unique_constraint}
9
- #
10
- # @example User unique constraint validation
11
- # # The database schema has a unique constraint on email field
12
- # class User < ActiveRecord::Base
13
- # include Iry
14
- #
15
- # unique_constraint :email
16
- # end
17
- #
18
- # user = User.create!(email: "user@example.com")
19
- # fail_user = User.new(email: "user@example.com")
20
- # Iry.save(fail_user)
21
- # fail_user.errors.details.fetch(:email) #=> [{error: :taken}]
22
- module Iry
23
- VERSION = T.let(File.read(File.expand_path("../../VERSION", __dir__)).strip.freeze, T.untyped)
24
-
25
- # Inherited from {ActiveRecord::RecordInvalid}, returns the model for
26
- # which the constraint violations have been detected
27
- sig { returns(Handlers::Model) }
28
- def record; end
29
-
30
- # _@param_ `klass`
31
- sig { params(klass: Module).void }
32
- def self.included(klass); end
33
-
34
- # Executes block and in case of constraints violations on `model`, block is
35
- # halted and errors are appended to `model`
36
- #
37
- # _@param_ `model` — model object for which constraints should be monitored and for which errors should be added to
38
- #
39
- # _@return_ — the `model` or `nil` if a a constraint is
40
- # violated
41
- #
42
- # Handle constraints for unique user
43
- # ```ruby
44
- # # The database schema has a unique constraint on email field
45
- # class User < ActiveRecord::Base
46
- # include Iry
47
- #
48
- # unique_constraint :email
49
- # end
50
- #
51
- # user = User.create!(email: "user@example.com")
52
- # fail_user = User.new(email: "user@example.com")
53
- # result = Iry.handle_constraints(fail_user) { fail_user.save }
54
- # result #=> nil
55
- # fail_user.errors.details.fetch(:email) #=> [{error: :taken}]
56
- # ```
57
- sig { params(model: Handlers::Model, block: T.untyped).void }
58
- def self.handle_constraints(model, &block); end
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
-
69
- # Similar to {ActiveRecord::Base#save} but in case of constraint violations,
70
- # `false` is returned and `errors` are populated.
71
- # Aside from `model`, it takes the same arguments as
72
- # {ActiveRecord::Base#save}
73
- #
74
- # _@param_ `model` — model to save
75
- #
76
- # _@return_ — `true` if successful
77
- sig { params(model: Handlers::Model).returns(T::Boolean) }
78
- def self.save(model); end
79
-
80
- # Similar to {ActiveRecord::Base#save!} but in case of constraint violations,
81
- # it raises {ConstraintViolation} and `errors` are populated.
82
- # Aside from `model`, it takes the same arguments as
83
- # {ActiveRecord::Base#save!}
84
- #
85
- # _@param_ `model` — model to save
86
- sig { params(model: Handlers::Model).returns(T::Boolean) }
87
- def self.save!(model); end
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
-
98
- # Included in all exceptions triggered by Iry, this allows to rescue any
99
- # gem-related exception by rescuing {Iry::Error}
100
- module Error
101
- end
102
-
103
- # Raised when constraints have been violated and have been converted to
104
- # model errors, on {ActiveRecord::Base#save!} calls, to simulate a behavior
105
- # similar to {ActiveRecord::RecordInvalid} when it's raised
106
- class ConstraintViolation < ActiveRecord::RecordInvalid
107
- include Iry::Error
108
- end
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
-
154
- # Class-level methods available to classes executing `include Iry`
155
- module Macros
156
- # Constraints by name
157
- sig { returns(T::Hash[String, Constraint]) }
158
- def constraints; end
159
-
160
- # Tracks check constraint for the given key and convert constraint errors into validation errors
161
- #
162
- # _@param_ `key` — key to apply validation errors to
163
- #
164
- # _@param_ `message` — the validation error message
165
- #
166
- # _@param_ `name` — constraint name. If omitted, it will be inferred using table name + key
167
- sig { params(key: Symbol, name: T.nilable(String), message: T.any(Symbol, String)).void }
168
- def check_constraint(key, name: nil, message: :invalid); end
169
-
170
- # Tracks exclusion constraint for the given key and convert constraint errors into validation errors
171
- #
172
- # _@param_ `key` — key to apply validation errors to
173
- #
174
- # _@param_ `message` — the validation error message
175
- #
176
- # _@param_ `name` — constraint name. If omitted, it will be inferred using table name + key
177
- sig { params(key: Symbol, name: T.nilable(String), message: T.any(Symbol, String)).void }
178
- def exclusion_constraint(key, name: nil, message: :taken); end
179
-
180
- # Tracks foreign key constraint for the given key (or keys) and convert constraint errors into validation errors
181
- #
182
- # _@param_ `key_or_keys` — key or array of keys to track the foreign key constraint of
183
- #
184
- # _@param_ `message` — the validation error message
185
- #
186
- # _@param_ `name` — constraint name. If omitted, it will be inferred using table name + keys
187
- #
188
- # _@param_ `error_key` — key to which the validation error will be applied to. If omitted, it will be applied to the first key
189
- sig do
190
- params(
191
- key_or_keys: T.any(Symbol, T::Array[Symbol]),
192
- name: T.nilable(String),
193
- message: T.any(Symbol, String),
194
- error_key: T.nilable(Symbol)
195
- ).void
196
- end
197
- def foreign_key_constraint(key_or_keys, name: nil, message: :required, error_key: nil); end
198
-
199
- # Tracks uniqueness constraint for the given key (or keys) and convert constraint errors into validation errors
200
- #
201
- # _@param_ `key_or_keys` — key or array of keys to track the uniqueness constraint of
202
- #
203
- # _@param_ `message` — the validation error message
204
- #
205
- # _@param_ `name` — constraint name. If omitted, it will be inferred using table name + keys
206
- #
207
- # _@param_ `error_key` — key to which the validation error will be applied to. If omitted, it will be applied to the first key
208
- sig do
209
- params(
210
- key_or_keys: T.any(Symbol, T::Array[Symbol]),
211
- name: T.nilable(String),
212
- message: T.any(Symbol, String),
213
- error_key: T.nilable(Symbol)
214
- ).void
215
- end
216
- def unique_constraint(key_or_keys, name: nil, message: :taken, error_key: nil); end
217
- end
218
-
219
- module Handlers
220
- # Interface for handlers of different database types
221
- # @abstract
222
- module Handler
223
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
224
- # _@param_ `err` — possible constraint error to handle
225
- #
226
- # _@return_ — true if this database handler is the correct one for this exception
227
- sig { params(err: ActiveRecord::StatementInvalid).returns(T::Boolean) }
228
- def handle?(err); end
229
-
230
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
231
- # _@param_ `err` — possible constraint error to handle
232
- #
233
- # _@param_ `model`
234
- #
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 }
238
- def handle(err, model); end
239
- end
240
-
241
- # Interface of the model class. This class is usually inherits from {ActiveRecord::Base}
242
- # @abstract
243
- module ModelClass
244
- sig { returns(String) }
245
- def table_name; end
246
-
247
- sig { returns(T::Hash[String, Constraint]) }
248
- def constraints; end
249
- end
250
-
251
- # Interface of the model that should be used to handle constraints.
252
- # This object is an instance of {ActiveRecord::Base}
253
- # @abstract
254
- module Model
255
- # sord warn - ActiveModel::Errors wasn't able to be resolved to a constant in this project
256
- sig { returns(ActiveModel::Errors) }
257
- def errors; end
258
-
259
- sig { returns(ModelClass) }
260
- def class; end
261
- end
262
-
263
- # PostgreSQL handler through `pg` gem
264
- # @private
265
- module PG
266
- extend Iry::Handlers::PG
267
- REGEX = T.let(%r{
268
- (?:
269
- unique\sconstraint|
270
- check\sconstraint|
271
- exclusion\sconstraint|
272
- foreign\skey\sconstraint
273
- )
274
- \s"([^"]+)"
275
- }x, T.untyped)
276
-
277
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
278
- # When true, the handler is able to handle this exception, representing a constraint error in PostgreSQL.
279
- # This method must ensure not to raise exception in case the postgresql adapter is missing and as such, the
280
- # postgres constant is undefined
281
- #
282
- # _@param_ `err`
283
- sig { params(err: ActiveRecord::StatementInvalid).returns(T::Boolean) }
284
- def handle?(err); end
285
-
286
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
287
- # Appends constraint errors as model errors
288
- #
289
- # _@param_ `err`
290
- #
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
296
- sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
297
- def handle(err, model); end
298
-
299
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
300
- # When true, the handler is able to handle this exception, representing a constraint error in PostgreSQL.
301
- # This method must ensure not to raise exception in case the postgresql adapter is missing and as such, the
302
- # postgres constant is undefined
303
- #
304
- # _@param_ `err`
305
- sig { params(err: ActiveRecord::StatementInvalid).returns(T::Boolean) }
306
- def self.handle?(err); end
307
-
308
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
309
- # Appends constraint errors as model errors
310
- #
311
- # _@param_ `err`
312
- #
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
318
- sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
319
- def self.handle(err, model); end
320
- end
321
-
322
- # Catch-all handler for unrecognized database adapters
323
- # @private
324
- module Null
325
- extend Iry::Handlers::Null
326
-
327
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
328
- # Returns always true, catching any unhandled database exception
329
- #
330
- # _@param_ `err`
331
- sig { params(err: T.any(StandardError, ActiveRecord::StatementInvalid)).returns(T::Boolean) }
332
- def handle?(err); end
333
-
334
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
335
- # Return always false, failing to handle any constraint
336
- #
337
- # _@param_ `err`
338
- #
339
- # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
340
- sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
341
- def handle(err, model); end
342
-
343
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
344
- # Returns always true, catching any unhandled database exception
345
- #
346
- # _@param_ `err`
347
- sig { params(err: T.any(StandardError, ActiveRecord::StatementInvalid)).returns(T::Boolean) }
348
- def self.handle?(err); end
349
-
350
- # sord warn - ActiveRecord::StatementInvalid wasn't able to be resolved to a constant in this project
351
- # Return always false, failing to handle any constraint
352
- #
353
- # _@param_ `err`
354
- #
355
- # _@param_ `model` — should inherit {ActiveRecord::Base} and`include Iry` to match the interface
356
- sig { params(err: ActiveRecord::StatementInvalid, model: Model).void }
357
- def self.handle(err, model); end
358
- end
359
- end
360
-
361
- # Main function to kick-off **Iry** constraint-checking mechanism
362
- # If interested in adding support for other databases beside Postgres, modify this file.
363
- # @private
364
- module Callbacks
365
- extend Iry::Callbacks
366
-
367
- # _@param_ `model`
368
- sig { params(model: Handlers::Model).void }
369
- def around_save(model); end
370
-
371
- # _@param_ `model`
372
- sig { params(model: Handlers::Model).void }
373
- def self.around_save(model); end
374
- end
375
-
376
- # Interface representing a constraint.
377
- # A constraint has a name and can apply errors to an object inheriting from {ActiveRecord::Base}
378
- # @abstract
379
- module Constraint
380
- # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
381
- # Sets validation errors on the model
382
- #
383
- # _@param_ `model`
384
- sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
385
- def apply(model); end
386
-
387
- # Name of the constraint to be caught from the database
388
- sig { returns(String) }
389
- def name; end
390
-
391
- # Message to be attached as validation error to the model
392
- # (see Handlers::Model)
393
- sig { returns(T.any(Symbol, String)) }
394
- def message; end
395
-
396
- class Check
397
- # Infers the check constraint name based on key and table name
398
- #
399
- # _@param_ `key`
400
- #
401
- # _@param_ `table_name`
402
- sig { params(key: Symbol, table_name: String).returns(String) }
403
- def self.infer_name(key, table_name); end
404
-
405
- # _@param_ `key` — key to apply error message for check constraint to
406
- #
407
- # _@param_ `message` — the validation error message
408
- #
409
- # _@param_ `name` — constraint name
410
- sig { params(key: Symbol, name: String, message: T.any(Symbol, String)).void }
411
- def initialize(key, name:, message: :invalid); end
412
-
413
- # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
414
- # _@param_ `model`
415
- sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
416
- def apply(model); end
417
-
418
- sig { returns(Symbol) }
419
- attr_accessor :key
420
-
421
- sig { returns(T.any(Symbol, String)) }
422
- attr_accessor :message
423
-
424
- sig { returns(String) }
425
- attr_accessor :name
426
- end
427
-
428
- class Unique
429
- MAX_INFER_NAME_BYTE_SIZE = T.let(62, T.untyped)
430
-
431
- # Infers the unique constraint name based on keys and table name
432
- #
433
- # _@param_ `keys`
434
- #
435
- # _@param_ `table_name`
436
- sig { params(keys: T::Array[Symbol], table_name: String).returns(String) }
437
- def self.infer_name(keys, table_name); end
438
-
439
- # _@param_ `keys` — array of keys to track the uniqueness constraint of
440
- #
441
- # _@param_ `message` — the validation error message
442
- #
443
- # _@param_ `name` — constraint name
444
- #
445
- # _@param_ `error_key` — key to which the validation error will be applied to
446
- sig do
447
- params(
448
- keys: T::Array[Symbol],
449
- name: String,
450
- error_key: Symbol,
451
- message: T.any(Symbol, String)
452
- ).void
453
- end
454
- def initialize(keys, name:, error_key:, message: :taken); end
455
-
456
- # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
457
- # _@param_ `model`
458
- sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
459
- def apply(model); end
460
-
461
- sig { returns(T::Array[Symbol]) }
462
- attr_accessor :keys
463
-
464
- sig { returns(T.any(Symbol, String)) }
465
- attr_accessor :message
466
-
467
- sig { returns(String) }
468
- attr_accessor :name
469
-
470
- sig { returns(Symbol) }
471
- attr_accessor :error_key
472
- end
473
-
474
- class Exclusion
475
- # Infers the exclusion constraint name based on key and table name
476
- #
477
- # _@param_ `key`
478
- #
479
- # _@param_ `table_name`
480
- sig { params(key: Symbol, table_name: String).returns(String) }
481
- def self.infer_name(key, table_name); end
482
-
483
- # _@param_ `key` — key to apply error message for exclusion constraint to
484
- #
485
- # _@param_ `message` — the validation error message
486
- #
487
- # _@param_ `name` — constraint name
488
- sig { params(key: Symbol, name: String, message: T.any(Symbol, String)).void }
489
- def initialize(key, name:, message: :taken); end
490
-
491
- # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
492
- # _@param_ `model`
493
- sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
494
- def apply(model); end
495
-
496
- sig { returns(Symbol) }
497
- attr_accessor :key
498
-
499
- sig { returns(T.any(Symbol, String)) }
500
- attr_accessor :message
501
-
502
- sig { returns(String) }
503
- attr_accessor :name
504
- end
505
-
506
- class ForeignKey
507
- # Infers the unique constraint name based on keys and table name
508
- #
509
- # _@param_ `keys`
510
- #
511
- # _@param_ `table_name`
512
- sig { params(keys: T::Array[Symbol], table_name: String).returns(String) }
513
- def self.infer_name(keys, table_name); end
514
-
515
- # _@param_ `keys` — array of keys to track the uniqueness constraint of
516
- #
517
- # _@param_ `message` — the validation error message
518
- #
519
- # _@param_ `name` — constraint name
520
- #
521
- # _@param_ `error_key` — key to which the validation error will be applied to
522
- sig do
523
- params(
524
- keys: T::Array[Symbol],
525
- name: String,
526
- error_key: Symbol,
527
- message: T.any(Symbol, String)
528
- ).void
529
- end
530
- def initialize(keys, name:, error_key:, message: :required); end
531
-
532
- # sord warn - ActiveModel::Error wasn't able to be resolved to a constant in this project
533
- # _@param_ `model`
534
- sig { params(model: Handlers::Model).returns(ActiveModel::Error) }
535
- def apply(model); end
536
-
537
- sig { returns(T::Array[Symbol]) }
538
- attr_accessor :keys
539
-
540
- sig { returns(T.any(Symbol, String)) }
541
- attr_accessor :message
542
-
543
- sig { returns(String) }
544
- attr_accessor :name
545
-
546
- sig { returns(Symbol) }
547
- attr_accessor :error_key
548
- end
549
- end
550
-
551
- # Implementation of {Iry} methods, helps ensuring the main module focus on
552
- # documentation
553
- module TransformConstraints
554
- extend Iry::TransformConstraints
555
-
556
- # _@param_ `model`
557
- sig { params(model: Handlers::Model, block: T.untyped).void }
558
- def handle_constraints(model, &block); end
559
-
560
- # _@param_ `model`
561
- sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
562
- def handle_constraints!(model, &block); end
563
-
564
- # Tracks constraints of models saved as a consequence of saving another
565
- # model. This usually represents a situation of model using
566
- # `accepts_nested_attributes_for`
567
- #
568
- # _@param_ `model`
569
- sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
570
- def nested_constraints!(model, &block); end
571
-
572
- # _@param_ `model`
573
- sig { params(model: Handlers::Model).returns(T::Boolean) }
574
- def save(model); end
575
-
576
- # _@param_ `model`
577
- sig { params(model: Handlers::Model).returns(T::Boolean) }
578
- def save!(model); end
579
-
580
- # _@param_ `model`
581
- sig { params(model: Handlers::Model).returns(Handlers::Model) }
582
- def destroy(model); end
583
-
584
- # _@param_ `model`
585
- sig { params(model: Handlers::Model, block: T.untyped).void }
586
- def self.handle_constraints(model, &block); end
587
-
588
- # _@param_ `model`
589
- sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
590
- def self.handle_constraints!(model, &block); end
591
-
592
- # Tracks constraints of models saved as a consequence of saving another
593
- # model. This usually represents a situation of model using
594
- # `accepts_nested_attributes_for`
595
- #
596
- # _@param_ `model`
597
- sig { params(model: Handlers::Model, block: T.untyped).returns(Handlers::Model) }
598
- def self.nested_constraints!(model, &block); end
599
-
600
- # _@param_ `model`
601
- sig { params(model: Handlers::Model).returns(T::Boolean) }
602
- def self.save(model); end
603
-
604
- # _@param_ `model`
605
- sig { params(model: Handlers::Model).returns(T::Boolean) }
606
- def self.save!(model); end
607
-
608
- # _@param_ `model`
609
- sig { params(model: Handlers::Model).returns(Handlers::Model) }
610
- def self.destroy(model); end
611
- end
612
- end