active_record_compose 1.1.0 → 1.2.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.
@@ -5,7 +5,6 @@ require_relative "composed_collection"
5
5
  module ActiveRecordCompose
6
6
  using ComposedCollection::PackagePrivate
7
7
 
8
- # @private
9
8
  module Validations
10
9
  extend ActiveSupport::Concern
11
10
  include ActiveModel::Validations::Callbacks
@@ -22,27 +21,100 @@ module ActiveRecordCompose
22
21
  perform_validations(options) ? super : raise_validation_error
23
22
  end
24
23
 
24
+ # Runs all the validations and returns the result as true or false.
25
+ #
26
+ # @param context Validation context.
27
+ # @return [Boolean] true on success, false on failure.
25
28
  def valid?(context = nil) = context_for_override_validation.with_override(context) { super }
26
29
 
30
+ # @!method validate(context = nil)
31
+ # Alias for {#valid?}
32
+ # @see #valid? Validation context.
33
+ # @param context
34
+ # @return [Boolean] true on success, false on failure.
35
+
36
+ # @!method validate!(context = nil)
37
+ # @see #valid?
38
+ # Runs all the validations within the specified context.
39
+ # no errors are found, raises `ActiveRecord::RecordInvalid` otherwise.
40
+ # @param context Validation context.
41
+ # @raise ActiveRecord::RecordInvalid
42
+
43
+ # @!method errors
44
+ # Returns the `ActiveModel::Errors` object that holds all information about attribute error messages.
45
+ #
46
+ # The `ActiveModel::Base` implementation itself,
47
+ # but also aggregates error information for objects stored in {#models} when validation is performed.
48
+ #
49
+ # class Account < ActiveRecord::Base
50
+ # validates :name, :email, presence: true
51
+ # end
52
+ #
53
+ # class AccountRegistration < ActiveRecordCompose::Model
54
+ # def initialize(attributes = {})
55
+ # @account = Account.new
56
+ # super(attributes)
57
+ # models << account
58
+ # end
59
+ #
60
+ # attribute :confirmation, :boolean, default: false
61
+ # validates :confirmation, presence: true
62
+ #
63
+ # private
64
+ #
65
+ # attr_reader :account
66
+ # end
67
+ #
68
+ # registration = AccountRegistration
69
+ # registration.valid?
70
+ # #=> false
71
+ #
72
+ # # In addition to the model's own validation error information (`confirmation`), also aggregates
73
+ # # error information for objects stored in `account` (`name`, `email`) when validation is performed.
74
+ #
75
+ # registration.errors.map { _1.attribute } #=> [:name, :email, :confirmation]
76
+ #
77
+ # @return [ActiveModel::Errors]
78
+
79
+ # @private
80
+ def detect_circular_reference(targets = [])
81
+ raise CircularReferenceDetected if targets.include?(object_id)
82
+
83
+ targets += [ object_id ]
84
+ # steep:ignore:start
85
+ models.select { _1.respond_to?(:detect_circular_reference) }.each do |m|
86
+ m.detect_circular_reference(targets)
87
+ end
88
+ # steep:ignore:end
89
+ end
90
+
27
91
  private
28
92
 
93
+ # @private
29
94
  def validate_models
95
+ detect_circular_reference
96
+
30
97
  context = override_validation_context
31
98
  models.__wrapped_models.lazy.select { _1.invalid?(context) }.each { errors.merge!(_1) }
32
99
  end
33
100
 
101
+ # @private
34
102
  def perform_validations(options)
35
103
  options[:validate] == false || valid?(options[:context])
36
104
  end
37
105
 
106
+ # @private
38
107
  def raise_validation_error = raise ActiveRecord::RecordInvalid, self
39
108
 
109
+ # @private
40
110
  def context_for_override_validation
41
111
  @context_for_override_validation ||= OverrideValidationContext.new
42
112
  end
43
113
 
114
+ # @private
44
115
  def override_validation_context = context_for_override_validation.context
45
116
 
117
+ # @private
46
118
  class OverrideValidationContext
47
119
  attr_reader :context
48
120
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordCompose
4
- VERSION = "1.1.0"
4
+ VERSION = "1.2.0"
5
5
  end
@@ -104,19 +104,28 @@ module ActiveRecordCompose
104
104
  # @param [Object] other
105
105
  # @return [Boolean]
106
106
  def ==(other)
107
+ return true if equal?(other)
107
108
  return false unless self.class == other.class
108
- return false unless model == other.model
109
109
 
110
- true
110
+ equality_key == other.equality_key
111
111
  end
112
112
 
113
+ def eql?(other)
114
+ return true if equal?(other)
115
+ return false unless self.class == other.class
116
+
117
+ equality_key.eql?(other.equality_key)
118
+ end
119
+
120
+ def hash = equality_key.hash
121
+
113
122
  protected
114
123
 
115
- attr_reader :model
124
+ def equality_key = [ model, destroy_context_type, if_option ]
116
125
 
117
126
  private
118
127
 
119
- attr_reader :destroy_context_type, :if_option
128
+ attr_reader :model, :destroy_context_type, :if_option
120
129
 
121
130
  # @private
122
131
  module PackagePrivate
@@ -3,6 +3,7 @@
3
3
  require "active_record"
4
4
 
5
5
  require_relative "active_record_compose/version"
6
+ require_relative "active_record_compose/exceptions"
6
7
  require_relative "active_record_compose/model"
7
8
 
8
9
  # namespaces in gem `active_record_compose`.
@@ -4,19 +4,13 @@ module ActiveRecordCompose
4
4
  include ActiveModel::Attributes
5
5
  include Querying
6
6
 
7
+ def self.delegate_attribute: (*untyped methods, to: untyped, ?allow_nil: bool) -> untyped
8
+ def self.delegated_attributes: () -> Array[Delegation]
9
+ def self.delegated_attributes=: (Array[Delegation]) -> untyped
7
10
  def delegated_attributes: () -> Array[Delegation]
8
11
 
9
12
  @attributes: untyped
10
13
 
11
- module ClassMethods : Module
12
- include ActiveModel::Attributes::ClassMethods
13
- include ActiveModel::AttributeMethods::ClassMethods
14
-
15
- def delegate_attribute: (*untyped methods, to: untyped, ?allow_nil: bool) -> untyped
16
- def delegated_attributes: () -> Array[Delegation]
17
- def delegated_attributes=: (Array[Delegation]) -> untyped
18
- end
19
-
20
14
  class AttributePredicate
21
15
  def initialize: (untyped value) -> void
22
16
  def call: -> bool
@@ -70,16 +64,20 @@ module ActiveRecordCompose
70
64
  class ComposedCollection
71
65
  def initialize: (Model) -> void
72
66
 
67
+ @symbol_proc_map: Hash[Symbol, (destroy_context_type | condition_type)]
68
+
73
69
  private
74
70
  attr_reader owner: Model
75
- attr_reader models: Array[WrappedModel]
71
+ attr_reader models: Set[WrappedModel]
76
72
  def wrap: (ar_like, ?destroy: (bool | Symbol | destroy_context_type), ?if: (nil | Symbol | condition_type)) -> WrappedModel
73
+ def symbol_proc_map: () -> Hash[Symbol, (destroy_context_type | condition_type)]
74
+ def instance_variables_to_inspect: () -> Array[Symbol]
77
75
 
78
76
  module PackagePrivate
79
- def __wrapped_models: () -> Array[WrappedModel]
77
+ def __wrapped_models: () -> Enumerable[WrappedModel]
80
78
 
81
79
  private
82
- def models: () -> Array[WrappedModel]
80
+ def models: () -> Set[WrappedModel]
83
81
  end
84
82
 
85
83
  include PackagePrivate
@@ -88,31 +86,20 @@ module ActiveRecordCompose
88
86
  module Inspectable
89
87
  extend ActiveSupport::Concern
90
88
  include Attributes
91
- extend Inspectable::ClassMethods
92
89
 
90
+ def self.inspection_filter: () -> ActiveSupport::ParameterFilter
91
+ def self.filter_attributes: () -> Array[untyped]
92
+ def self.filter_attributes=: (Array[untyped]) -> void
93
93
  def inspect: () -> String
94
94
  def pretty_print: (untyped q) -> void
95
95
 
96
96
  private
97
97
  def format_for_inspect: (String name, untyped value) -> String
98
-
99
- module ClassMethods
100
- FILTERED_MASK: String
101
-
102
- def inspection_filter: () -> ActiveSupport::ParameterFilter
103
- def filter_attributes: () -> Array[untyped]
104
- def filter_attributes=: (Array[untyped]) -> void
105
-
106
- @inspection_filter: ActiveSupport::ParameterFilter?
107
- @filter_attributes: untyped
108
- end
109
98
  end
110
99
 
111
100
  class Model
112
101
  include Attributes
113
- extend Attributes::ClassMethods
114
102
  include TransactionSupport
115
- extend TransactionSupport::ClassMethods
116
103
  include Callbacks
117
104
 
118
105
  @__models: ComposedCollection
@@ -125,19 +112,12 @@ module ActiveRecordCompose
125
112
  module TransactionSupport
126
113
  extend ActiveSupport::Concern
127
114
  include ActiveRecord::Transactions
128
- extend TransactionSupport::ClassMethods
129
-
130
- module ClassMethods
131
- include ActiveSupport::Callbacks::ClassMethods
115
+ include ActiveSupport::Callbacks
116
+ extend ActiveSupport::Callbacks::ClassMethods
132
117
 
133
- def before_commit: (*untyped) -> untyped
134
- def after_commit: (*untyped) -> untyped
135
- def after_rollback: (*untyped) -> untyped
136
-
137
- private
138
- def prepend_option: -> ({ prepend: true } | {})
139
- def set_options_for_callbacks!: (untyped, ?({ prepend: true } | {})) -> untyped
140
- end
118
+ def self.before_commit: (*untyped) -> untyped
119
+ def self.after_commit: (*untyped) -> untyped
120
+ def self.after_rollback: (*untyped) -> untyped
141
121
 
142
122
  def save: (**untyped options) -> bool
143
123
  def save!: (**untyped options) -> untyped
@@ -154,7 +134,6 @@ module ActiveRecordCompose
154
134
  module Persistence
155
135
  include Callbacks
156
136
  include TransactionSupport
157
- extend TransactionSupport::ClassMethods
158
137
 
159
138
  def save: (**untyped options) -> bool
160
139
  def save!: (**untyped options) -> untyped
@@ -168,10 +147,6 @@ module ActiveRecordCompose
168
147
  def raise_on_save_error_message: -> String
169
148
  end
170
149
 
171
- class Railtie < Rails::Railtie
172
- extend Rails::Initializable::ClassMethods
173
- end
174
-
175
150
  module Validations : Model
176
151
  extend ActiveSupport::Concern
177
152
  extend ActiveModel::Validations::ClassMethods
@@ -179,6 +154,7 @@ module ActiveRecordCompose
179
154
  def save: (**untyped options) -> bool
180
155
  def save!: (**untyped options) -> untyped
181
156
  def valid?: (?validation_context context) -> bool
157
+ def detect_circular_reference: (?Array[Integer])-> untyped
182
158
 
183
159
  @context_for_override_validation: OverrideValidationContext
184
160
 
@@ -212,6 +188,7 @@ module ActiveRecordCompose
212
188
  attr_reader model: ar_like
213
189
  attr_reader destroy_context_type: (bool | destroy_context_type)
214
190
  attr_reader if_option: (nil | condition_type)
191
+ def equality_key: () -> [ar_like, (bool | destroy_context_type), (nil | condition_type)]
215
192
 
216
193
  module PackagePrivate
217
194
  def __raw_model: () -> ar_like
@@ -47,6 +47,9 @@ module ActiveRecordCompose
47
47
  def delete: (ar_like) -> ComposedCollection?
48
48
  end
49
49
 
50
+ class CircularReferenceDetected < StandardError
51
+ end
52
+
50
53
  class Model
51
54
  include ActiveModel::Model
52
55
  include ActiveModel::Validations::Callbacks
@@ -68,6 +71,7 @@ module ActiveRecordCompose
68
71
  def self.around_update: (*around_callback[instance], ?if: condition[instance], ?unless: condition[instance], **untyped) ?{ () [self: instance] -> void } -> void
69
72
  def self.after_update: (*callback[instance], ?if: condition[instance], ?unless: condition[instance], **untyped) ?{ () [self: instance] -> void } -> void
70
73
 
74
+ def self.before_commit: (*callback[instance], ?if: condition[instance], ?unless: condition[instance], **untyped) ?{ () [self: instance] -> void } -> void
71
75
  def self.after_commit: (*callback[instance], ?if: condition[instance], ?unless: condition[instance], **untyped) ?{ () [self: instance] -> void } -> void
72
76
  def self.after_rollback: (*callback[instance], ?if: condition[instance], ?unless: condition[instance], **untyped) ?{ () [self: instance] -> void } -> void
73
77
 
@@ -90,4 +94,8 @@ module ActiveRecordCompose
90
94
  private
91
95
  def models: -> ComposedCollection
92
96
  end
97
+
98
+ class Railtie < Rails::Railtie
99
+ extend Rails::Initializable::ClassMethods
100
+ end
93
101
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_compose
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hamajyotan
@@ -50,6 +50,7 @@ files:
50
50
  - lib/active_record_compose/attributes/querying.rb
51
51
  - lib/active_record_compose/callbacks.rb
52
52
  - lib/active_record_compose/composed_collection.rb
53
+ - lib/active_record_compose/exceptions.rb
53
54
  - lib/active_record_compose/inspectable.rb
54
55
  - lib/active_record_compose/model.rb
55
56
  - lib/active_record_compose/persistence.rb
@@ -83,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
84
  - !ruby/object:Gem::Version
84
85
  version: '0'
85
86
  requirements: []
86
- rubygems_version: 3.7.2
87
+ rubygems_version: 4.0.3
87
88
  specification_version: 4
88
89
  summary: activemodel form object pattern
89
90
  test_files: []