active_record_compose 0.8.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 690ecf032eb0a4c59c97394702c838142a4d519145f72e58f9a381d956cad5ce
4
- data.tar.gz: 7133a2f5defa0d1c97dac41b207936512f6d5375e8f534ea77dc6c13c3f61dde
3
+ metadata.gz: dba7d13bf8f2dc9ef449ead00c1a7ae3fff83e216f07b5d11606659a3c1f4650
4
+ data.tar.gz: 883a9480ff3e6bd4c99246c12200a7b5a6e44103c0d1c967ce97c4536aa478b1
5
5
  SHA512:
6
- metadata.gz: 2680382210cf6eb2f8371cca7e656f8b00211361f00bf9aed7d2ee4f006a816eee6298a917e48c67d5b4f6149545f2ebb3e67bd5905946279c9e203e9e378d82
7
- data.tar.gz: 63aa5b0a8abcbcd59eb81aadadf4c8207622988ad417b09d2e8f977615ed8726233ae8f257f8d8847e16e38f400955e0bda1d9340f9c7733f06ea8d76fa4854a
6
+ metadata.gz: 905bf7969733f738e00726f0dc7ed1442bce1f598485a72a0478fd67069c556b5d8299fdc5485636b1194e095649df550ba9f3c01ffb42c107a8a69afcde85ae
7
+ data.tar.gz: 22f44a63d515d31682f22641e112c3bf720c5b3ff29c8fb0a30ceb777b23847a74f053eb3591211c35bfe2e2f96de345523236d08b30365059fc3a7421437bf4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.9.0] - 2025-03-16
4
+
5
+ - removed `persisted_flag_callback_control` support.
6
+ - Omitted `:private` option from `delegate_attribute` because, assuming the
7
+ behavior and use cases of `ActiveModel::Attributes.attribute`, making it private is unnecessary.
8
+ - Added the URL for the sample application to the README
9
+
3
10
  ## [0.8.0] - 2025-02-22
4
11
 
5
12
  - changed `persisted_flag_callback_control` default from `false` to `true`.
data/README.md CHANGED
@@ -286,18 +286,11 @@ end
286
286
 
287
287
  ### Callback ordering by `#persisted?`
288
288
 
289
- The behavior of `(before|after|around)_create` and `(before|after|around)_update` hooks depends on
290
- the state of the `persisted_flag_callback_control` setting.
291
- default value is `true`, behavior when set to `false` will be removed in the next release.
292
-
293
- When `persisted_flag_callback_control` is set to `true`, it behaves almost like callback control in ActiveRecord.
294
- Depending on the evaluation result of `#persisted?`,
289
+ The behavior of `(before|after|around)_create` and `(before|after|around)_update` hooks depending on the evaluation result of `#persisted?`,
295
290
  either the create-related callbacks or the update-related callbacks will be triggered.
296
291
 
297
292
  ```ruby
298
293
  class ComposedModel < ActiveRecordCompose::Model
299
- self.persisted_flag_callback_control = true # In the future, true will be the default and false will no longer be supported.
300
-
301
294
  # ...
302
295
 
303
296
  before_save { puts 'before_save called!' }
@@ -345,48 +338,10 @@ model.save # or `model.update` (the same callbacks will be triggered in all case
345
338
  # after_save called!
346
339
  ```
347
340
 
348
- When `persisted_flag_callback_control` is set to false,
349
- the execution of `#create`, `#update`, or `#save` determines which callbacks will be triggered.
350
- This behavior will no longer be supported in the next release.
351
-
352
- ```ruby
353
- class ComposedModel < ActiveRecordCompose::Model
354
- self.persisted_flag_callback_control = false # Currently defaults to false, but will no longer be supported in the future.
355
-
356
- # ...
357
-
358
- before_save { puts 'before_save called!' }
359
- before_create { puts 'before_create called!' }
360
- before_update { puts 'before_update called!' }
361
- after_save { puts 'after_save called!' }
362
- after_create { puts 'after_create called!' }
363
- after_update { puts 'after_update called!' }
364
- end
365
- ```
366
-
367
- ```ruby
368
- model = ComposedModel.new
369
-
370
- model.save
371
- # before_save called!
372
- # after_save called!
373
-
374
- model.create
375
- # before_save called!
376
- # before_create called!
377
- # after_create called!
378
- # after_save called!
379
-
380
- model.update
381
- # before_save called!
382
- # before_update called!
383
- # after_update called!
384
- # after_save called!
385
- ```
386
-
387
341
  ## Links
388
342
 
389
343
  - [Smart way to update multiple models simultaneously in Rails](https://dev.to/hamajyotan/smart-way-to-update-multiple-models-simultaneously-in-rails-51b6)
344
+ - [Sample application as an example](https://github.com/hamajyotan/active_record_compose-example)
390
345
 
391
346
  ## Development
392
347
 
@@ -45,7 +45,7 @@ module ActiveRecordCompose
45
45
  module ClassMethods
46
46
  # Defines the reader and writer for the specified attribute.
47
47
  #
48
- def delegate_attribute(*attributes, to:, allow_nil: nil, private: nil)
48
+ def delegate_attribute(*attributes, to:, allow_nil: nil)
49
49
  delegates = attributes.flat_map do |attribute|
50
50
  reader = attribute.to_s
51
51
  writer = "#{attribute}="
@@ -53,7 +53,7 @@ module ActiveRecordCompose
53
53
  [reader, writer]
54
54
  end
55
55
 
56
- delegate(*delegates, to:, allow_nil:, private:)
56
+ delegate(*delegates, to:, allow_nil:)
57
57
  self.delegated_attributes = delegated_attributes.to_a + attributes.map { _1.to_s }
58
58
  end
59
59
  end
@@ -15,46 +15,6 @@ module ActiveRecordCompose
15
15
  include ActiveRecordCompose::DelegateAttribute
16
16
  include ActiveRecordCompose::TransactionSupport
17
17
 
18
- # This flag controls the callback sequence for models.
19
- # The current default value is `true`, behavior when set to `false` will be removed in the next release.
20
- #
21
- # When `persisted_flag_callback_control` is set to `true`,
22
- # the occurrence of callbacks depends on the evaluation result of `#persisted?`.
23
- # Additionally, the definition of `#persisted?` itself can be appropriately overridden in subclasses.
24
- #
25
- # if `#persisted?` returns `false`:
26
- # * before_save
27
- # * before_create
28
- # * after_create
29
- # * after_save
30
- #
31
- # if `#persisted?` returns `true`:
32
- # * before_save
33
- # * before_update
34
- # * after_update
35
- # * after_save
36
- #
37
- # On the other hand, when `persisted_flag_callback_control` is set to `false`,
38
- # the invoked methods during saving operations vary depending on the method used.
39
- #
40
- # when performing `#save` or `#save!`:
41
- # * before_save
42
- # * after_save
43
- #
44
- # when performing `#update` or `#update!`:
45
- # * before_save
46
- # * before_update
47
- # * after_update
48
- # * after_save
49
- #
50
- # when performing `#create` or `#create!`:
51
- # * before_save
52
- # * before_create
53
- # * after_create
54
- # * after_save
55
- #
56
- class_attribute :persisted_flag_callback_control, instance_accessor: false, default: true
57
-
58
18
  define_model_callbacks :save
59
19
  define_model_callbacks :create
60
20
  define_model_callbacks :update
@@ -70,23 +30,16 @@ module ActiveRecordCompose
70
30
  #
71
31
  # The save is performed within a single transaction.
72
32
  #
33
+ # Options like `:validate` and `:context` are not accepted as arguments.
34
+ # The need for such values indicates that operations from multiple contexts are being handled.
35
+ # However, if the contexts are different, it is recommended to separate them into different model definitions.
36
+ #
73
37
  # @return [Boolean] returns true on success, false on failure.
74
38
  def save
75
39
  return false if invalid?
76
40
 
77
41
  with_transaction_returning_status do
78
- if self.class.persisted_flag_callback_control
79
- with_callbacks { save_models(bang: false) }
80
- else
81
- # steep:ignore:start
82
- deprecator.warn(
83
- 'The behavior with `persisted_flag_callback_control` set to `false` will be removed in 0.9.0. ' \
84
- 'Use `self.persisted_flag_callback_control = true` set to `true`. ' \
85
- '(Alternatively, exclude statements that set `false`)',
86
- )
87
- # steep:ignore:end
88
- run_callbacks(:save) { save_models(bang: false) }
89
- end
42
+ with_callbacks { save_models(bang: false) }
90
43
  rescue ActiveRecord::RecordInvalid
91
44
  false
92
45
  end
@@ -97,165 +50,31 @@ module ActiveRecordCompose
97
50
  #
98
51
  # Saving, like `#save`, is performed within a single transaction.
99
52
  #
100
- def save!
101
- valid? || raise_validation_error
102
-
103
- with_transaction_returning_status do
104
- if self.class.persisted_flag_callback_control
105
- with_callbacks { save_models(bang: true) }
106
- else
107
- # steep:ignore:start
108
- deprecator.warn(
109
- 'The behavior with `persisted_flag_callback_control` set to `false` will be removed in 0.9.0. ' \
110
- 'Use `self.persisted_flag_callback_control = true` set to `true`. ' \
111
- '(Alternatively, exclude statements that set `false`)',
112
- )
113
- # steep:ignore:end
114
- run_callbacks(:save) { save_models(bang: true) }
115
- end
116
- end || raise_on_save_error
117
- end
118
-
119
- # Behavior is same to `#save`, but `before_create` and `after_create` hooks fires.
120
- #
121
- # class ComposedModel < ActiveRecordCompose::Model
122
- # # ...
123
- #
124
- # before_save { puts 'before_save called!' }
125
- # before_create { puts 'before_create called!' }
126
- # before_update { puts 'before_update called!' }
127
- # after_save { puts 'after_save called!' }
128
- # after_create { puts 'after_create called!' }
129
- # after_update { puts 'after_update called!' }
130
- # end
131
- #
132
- # model = ComposedModel.new
53
+ # Options like `:validate` and `:context` are not accepted as arguments.
54
+ # The need for such values indicates that operations from multiple contexts are being handled.
55
+ # However, if the contexts are different, it is recommended to separate them into different model definitions.
133
56
  #
134
- # model.save
135
- # # before_save called!
136
- # # after_save called!
137
- #
138
- # model.create
139
- # # before_save called!
140
- # # before_create called!
141
- # # after_create called!
142
- # # after_save called!
143
- #
144
- # @deprecated
145
- def create(attributes = {})
146
- if self.class.persisted_flag_callback_control
147
- raise '`#create` cannot be called. The context for creation or update is determined by the `#persisted` flag.'
148
- end
149
-
150
- # steep:ignore:start
151
- deprecator.warn(
152
- 'The behavior with `persisted_flag_callback_control` set to `false` will be removed in 0.9.0. ' \
153
- 'Use `self.persisted_flag_callback_control = true` set to `true`. ' \
154
- '(Alternatively, exclude statements that set `false`)',
155
- )
156
- # steep:ignore:end
157
-
158
- assign_attributes(attributes)
159
- return false if invalid?
160
-
161
- with_transaction_returning_status do
162
- with_callbacks(context: :create) { save_models(bang: false) }
163
- rescue ActiveRecord::RecordInvalid
164
- false
165
- end
166
- end
167
-
168
- # Behavior is same to `#create`, but raises an exception prematurely on failure.
169
- #
170
- # @deprecated
171
- def create!(attributes = {})
172
- if self.class.persisted_flag_callback_control
173
- raise '`#create` cannot be called. The context for creation or update is determined by the `#persisted` flag.'
174
- end
175
-
176
- # steep:ignore:start
177
- deprecator.warn(
178
- 'The behavior with `persisted_flag_callback_control` set to `false` will be removed in 0.9.0. ' \
179
- 'Use `self.persisted_flag_callback_control = true` set to `true`. ' \
180
- '(Alternatively, exclude statements that set `false`)',
181
- )
182
- # steep:ignore:end
183
-
184
- assign_attributes(attributes)
57
+ def save!
185
58
  valid? || raise_validation_error
186
59
 
187
60
  with_transaction_returning_status do
188
- with_callbacks(context: :create) { save_models(bang: true) }
61
+ with_callbacks { save_models(bang: true) }
189
62
  end || raise_on_save_error
190
63
  end
191
64
 
192
- # Behavior is same to `#save`, but `before_update` and `after_update` hooks fires.
193
- #
194
- # class ComposedModel < ActiveRecordCompose::Model
195
- # # ...
196
- #
197
- # before_save { puts 'before_save called!' }
198
- # before_create { puts 'before_create called!' }
199
- # before_update { puts 'before_update called!' }
200
- # after_save { puts 'after_save called!' }
201
- # after_create { puts 'after_create called!' }
202
- # after_update { puts 'after_update called!' }
203
- # end
204
- #
205
- # model = ComposedModel.new
206
- #
207
- # model.save
208
- # # before_save called!
209
- # # after_save called!
210
- #
211
- # model.update
212
- # # before_save called!
213
- # # before_update called!
214
- # # after_update called!
215
- # # after_save called!
65
+ # Assign attributes and save.
216
66
  #
67
+ # @return [Boolean] returns true on success, false on failure.
217
68
  def update(attributes = {})
218
69
  assign_attributes(attributes)
219
- return false if invalid?
220
-
221
- with_transaction_returning_status do
222
- if self.class.persisted_flag_callback_control
223
- with_callbacks { save_models(bang: false) }
224
- else
225
- # steep:ignore:start
226
- deprecator.warn(
227
- 'The behavior with `persisted_flag_callback_control` set to `false` will be removed in 0.9.0. ' \
228
- 'Use `self.persisted_flag_callback_control = true` set to `true`. ' \
229
- '(Alternatively, exclude statements that set `false`)',
230
- )
231
- # steep:ignore:end
232
- with_callbacks(context: :update) { save_models(bang: false) }
233
- end
234
- rescue ActiveRecord::RecordInvalid
235
- false
236
- end
70
+ save
237
71
  end
238
72
 
239
73
  # Behavior is same to `#update`, but raises an exception prematurely on failure.
240
74
  #
241
75
  def update!(attributes = {})
242
76
  assign_attributes(attributes)
243
- valid? || raise_validation_error
244
-
245
- with_transaction_returning_status do
246
- if self.class.persisted_flag_callback_control
247
- with_callbacks { save_models(bang: true) }
248
- else
249
- # steep:ignore:start
250
- deprecator.warn(
251
- 'The behavior with `persisted_flag_callback_control` set to `false` will be removed in 0.9.0. ' \
252
- 'Use `self.persisted_flag_callback_control = true` set to `true`. ' \
253
- '(Alternatively, exclude statements that set `false`)',
254
- )
255
- # steep:ignore:end
256
- with_callbacks(context: :update) { save_models(bang: true) }
257
- end
258
- end || raise_on_save_error
77
+ save!
259
78
  end
260
79
 
261
80
  # Returns true if model is persisted.
@@ -275,13 +94,9 @@ module ActiveRecordCompose
275
94
  models.__wrapped_models.lazy.select { _1.invalid? }.each { errors.merge!(_1) }
276
95
  end
277
96
 
278
- def with_callbacks(context: nil, &block)
279
- run_callbacks(:save) { run_callbacks(callback_context(context:), &block) }
280
- end
97
+ def with_callbacks(&block) = run_callbacks(:save) { run_callbacks(callback_context, &block) }
281
98
 
282
- def callback_context(context: nil)
283
- context || (persisted? ? :update : :create)
284
- end
99
+ def callback_context = persisted? ? :update : :create
285
100
 
286
101
  def save_models(bang:)
287
102
  models.__wrapped_models.all? { bang ? _1.save! : _1.save }
@@ -292,13 +107,5 @@ module ActiveRecordCompose
292
107
  def raise_on_save_error = raise ActiveRecord::RecordNotSaved.new(raise_on_save_error_message, self)
293
108
 
294
109
  def raise_on_save_error_message = 'Failed to save the model.'
295
-
296
- def deprecator
297
- if ActiveRecord.respond_to?(:deprecator)
298
- ActiveRecord.deprecator # steep:ignore
299
- else # for rails 7.0.x or lower
300
- ActiveSupport::Deprecation
301
- end
302
- end
303
110
  end
304
111
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordCompose
4
- VERSION = '0.8.0'
4
+ VERSION = '0.9.0'
5
5
  end
@@ -24,7 +24,7 @@ module ActiveRecordCompose
24
24
  def delegated_attributes: () -> Array[String]
25
25
 
26
26
  module ClassMethods : Module
27
- def delegate_attribute: (*untyped methods, to: untyped, ?allow_nil: untyped?, ?private: untyped?) -> untyped
27
+ def delegate_attribute: (*untyped methods, to: untyped, ?allow_nil: untyped?) -> untyped
28
28
  def delegated_attributes: () -> Array[String]
29
29
  def delegated_attributes=: (Array[String]) -> untyped
30
30
  end
@@ -69,10 +69,7 @@ module ActiveRecordCompose
69
69
  def self.after_commit: (*callback[instance], ?if: condition[instance], ?unless: condition[instance], **untyped) ?{ () [self: instance] -> void } -> void
70
70
  def self.after_rollback: (*callback[instance], ?if: condition[instance], ?unless: condition[instance], **untyped) ?{ () [self: instance] -> void } -> void
71
71
 
72
- def self.persisted_flag_callback_control: () -> boolish
73
- def self.persisted_flag_callback_control=: (boolish) -> untyped
74
-
75
- def self.delegate_attribute: (*untyped methods, to: untyped, ?allow_nil: untyped?, ?private: untyped?) -> untyped
72
+ def self.delegate_attribute: (*untyped methods, to: untyped, ?allow_nil: untyped?) -> untyped
76
73
  def self.connection: -> ActiveRecord::ConnectionAdapters::AbstractAdapter
77
74
  def self.lease_connection: -> ActiveRecord::ConnectionAdapters::AbstractAdapter
78
75
  def self.with_connection: [T] () { () -> T } -> T
@@ -88,8 +85,8 @@ module ActiveRecordCompose
88
85
 
89
86
  private
90
87
  def models: -> ComposedCollection
91
- def with_callbacks: (?context: (nil | :create | :update)) { () -> bool } -> bool
92
- def callback_context: (?context: (nil | :create | :update)) -> (:create | :update)
88
+ def with_callbacks: { () -> bool } -> bool
89
+ def callback_context: -> (:create | :update)
93
90
  def validate_models: -> void
94
91
  def save_models: (bang: bool) -> bool
95
92
  def raise_validation_error: -> bot
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_compose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hamajyotan
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-02-22 00:00:00.000000000 Z
10
+ date: 2025-03-16 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activerecord
@@ -52,7 +52,7 @@ metadata:
52
52
  homepage_uri: https://github.com/hamajyotan/active_record_compose
53
53
  source_code_uri: https://github.com/hamajyotan/active_record_compose
54
54
  changelog_uri: https://github.com/hamajyotan/active_record_compose/blob/main/CHANGELOG.md
55
- documentation_uri: https://www.rubydoc.info/gems/active_record_compose/0.8.0
55
+ documentation_uri: https://www.rubydoc.info/gems/active_record_compose/0.9.0
56
56
  rubygems_mfa_required: 'true'
57
57
  rdoc_options: []
58
58
  require_paths: