active_record_compose 0.4.0 → 0.5.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: 8d9e12c3cb3d2e8571d418957576a8cf5b5d3dbedb9e83e2bcd25f172def43f3
4
- data.tar.gz: a991715192e6cb62e8b794860422667811b1fb1f985089e415b444f0b7bc0d4a
3
+ metadata.gz: 7a3112ceb79671ca112aa5dde2222e10a0bd4daed96f82ebaa641746165d8991
4
+ data.tar.gz: e021f41a5e3334b0e91f170712c011679023a384bbfe17c3df2a97858747323e
5
5
  SHA512:
6
- metadata.gz: 837b3d35c903eb0ff4400e5c83c438255d9ee02515407792fd19d24ab9a5a63cea1f9faa1d12a5fd5184d52fee2d662625e7c0d0b2a79e27ebb0866054a6b2a4
7
- data.tar.gz: e245d8380a2d20f0c9bbbc1f24712f1d7982697bf90b172886dcd2c9bd666ace8ddd3b29a20b9bcc709d8a236a1395a41c0f53ccdb3869f66a527d5ad6be08dc
6
+ metadata.gz: 56cb8c6d615cbefb58fc774e96caa9add4cb72a8ca34188ce2d713f6b4f32ef75b7df4f273da2bd6966d08c1a8f1aadbeef838f3c5b436e5f1122efb7af5a961
7
+ data.tar.gz: 0aec57e80f57d0c3d1bf1d45e4cb39c3cebcae47c53a35b630817de592bd3893604ff58563eed2c6b23f4199d2f27bc39804a1a9e6fe20bbdb809defaae30e28
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.0] - 2024-10-09
4
+
5
+ - remove `:context` option. use `:destroy` option instead.
6
+ - remove `:destroy` option from `InnerModelCollection#destroy`.
7
+
8
+ ## [0.4.1] - 2024-09-20
9
+
10
+ - Omitted optional argument for `InnerModelCollection#destroy`.
11
+ `InnerModel` equivalence is always performed based on the instance of the inner `model`.
12
+ Since there are no use cases that depend on the original behavior.
13
+
3
14
  ## [0.4.0] - 2024-09-15
4
15
 
5
16
  - support `destrpy` option. and deprecated `context` option.
data/README.md CHANGED
@@ -31,7 +31,7 @@ A callback is useful to define some processing before or after a save in a parti
31
31
  However, if a callback is written directly in the AR model, it is necessary to consider the case where the model is updated in other contexts.
32
32
  In particular, if you frequently create with test data, previously unnecessary processing will be called at every point of creation.
33
33
  In addition to cost, the more complicated the callbacks you write, the more difficult it will be to create even a single test data.
34
- If the callbacks are written in a class that inherits from `ApplicationRecordCompose::Model`, the AR model itself will not be polluted, and the context can be limited.
34
+ If the callbacks are written in a class that inherits from `ActiveRecordCompose::Model`, the AR model itself will not be polluted, and the context can be limited.
35
35
 
36
36
  ```ruby
37
37
  class AccountRegistration < ActiveRecordCompose::Model
@@ -70,7 +70,7 @@ Validates are basically fired in all cases where the model is manipulated. To av
70
70
  and so on to work only in specific cases. This allows you to create context-sensitive validations for the same model operation.
71
71
  However, this is the first step in making the model more and more complex. You will have to go around with `update(context: :foo)`
72
72
  In some cases, you may have to go around with the context option, such as `update(context: :foo)` everywhere.
73
- By writing validates in a class that extends `ApplicationRecordCompose::Model`, you can define context-specific validation without polluting the AR model itself.
73
+ By writing validates in a class that extends `ActiveRecordCompose::Model`, you can define context-specific validation without polluting the AR model itself.
74
74
 
75
75
  ```ruby
76
76
  class AccountRegistration < ActiveRecordCompose::Model
@@ -116,7 +116,7 @@ account_registration.valid? #=> false
116
116
 
117
117
  In an AR model, you can add, for example, `autosave: true` or `accepts_nested_attributes_for` to an association to update the related models at the same time.
118
118
  There are ways to update related models at the same time. The operation is safe because it is transactional.
119
- `ApplicationRecordCompose::Model` has an internal array called models. By adding an AR object to this models array
119
+ `ActiveRecordCompose::Model` has an internal array called models. By adding an AR object to this models array
120
120
  By adding an AR object to the models, the object stored in the models provides an atomic update operation via #save.
121
121
 
122
122
  ```ruby
@@ -167,12 +167,12 @@ class AccountResignation < ActiveRecordCompose::Model
167
167
  models.push(profile, destroy: true)
168
168
  end
169
169
 
170
- attr_reader :account, :profile
171
-
172
170
  before_save :set_resigned_at
173
171
 
174
172
  private
175
173
 
174
+ attr_reader :account, :profile
175
+
176
176
  def set_resigned_at
177
177
  account.resigned_at = Time.zone.now
178
178
  end
@@ -7,65 +7,32 @@ module ActiveRecordCompose
7
7
  # @param model [Object] the model instance.
8
8
  # @param destroy [Boolean] given true, destroy model.
9
9
  # @param destroy [Proc] when proc returning true, destroy model.
10
- def initialize(owner, model, destroy: false, context: nil)
11
- @owner = owner
10
+ def initialize(model, destroy: false)
12
11
  @model = model
13
- @destroy =
14
- if context
15
- c = context
16
-
17
- if c.is_a?(Proc)
18
- # @type var c: ((^() -> (context)) | (^(_ARLike) -> (context)))
19
- if c.arity == 0
20
- deprecator.warn(
21
- '`:context` will be removed in 0.5.0. Use `:destroy` option instead. ' \
22
- 'for example, `models.push(model, context: -> { foo? ? :destroy : :save })` ' \
23
- 'is replaced by `models.push(model, destroy: -> { foo? })`.',
24
- )
25
-
26
- # @type var c: ^() -> (context)
27
- -> { c.call == :destroy }
28
- else
29
- deprecator.warn(
30
- '`:context` will be removed in 0.5.0. Use `:destroy` option instead. ' \
31
- 'for example, `models.push(model, context: ->(m) { m.bar? ? :destroy : :save })` ' \
32
- 'is replaced by `models.push(model, destroy: ->(m) { m.bar? })`.',
33
- )
34
-
35
- # @type var c: ^(_ARLike) -> (context)
36
- ->(model) { c.call(model) == :destroy }
37
- end
38
- elsif %i[save destroy].include?(c)
39
- deprecator.warn(
40
- '`:context` will be removed in 0.5.0. Use `:destroy` option instead. ' \
41
- "for example, `models.push(model, context: #{c.inspect})` " \
42
- "is replaced by `models.push(model, destroy: #{(c == :destroy).inspect})`.",
43
- )
44
-
45
- # @type var c: (:save | :destory)
46
- c == :destroy
47
- else
48
- c
49
- end
50
- else
51
- destroy
52
- end
12
+ @destroy_context_type = destroy
53
13
  end
54
14
 
55
15
  delegate :errors, to: :model
56
16
 
17
+ # Determines whether to save or delete the target object.
18
+ # Depends on the `destroy` value of the InnerModel object initialization option.
19
+ #
20
+ # On the other hand, there are values `mark_for_destruction` and `marked_for_destruction?` in ActiveRecord.
21
+ # However, these values are not substituted here.
22
+ # These values only work if the `autosave` option is enabled for the parent model,
23
+ # and are not appropriate for other cases.
24
+ #
25
+ # @return [Boolean] returns true on destroy, false on save.
57
26
  def destroy_context?
58
- d = destroy
27
+ d = destroy_context_type
59
28
  if d.is_a?(Proc)
60
29
  if d.arity == 0
61
- # @type var d: ^() -> (bool | context)
62
- d.call
30
+ # @type var d: ^() -> bool
31
+ !!d.call
63
32
  else
64
- # @type var d: ^(_ARLike) -> (bool | context)
65
- d.call(model)
33
+ # @type var d: ^(_ARLike) -> bool
34
+ !!d.call(model)
66
35
  end
67
- elsif d.is_a?(Symbol)
68
- owner.send(d)
69
36
  else
70
37
  !!d
71
38
  end
@@ -94,35 +61,20 @@ module ActiveRecordCompose
94
61
  # @return [Boolean]
95
62
  def ==(other)
96
63
  return false unless self.class == other.class
97
- return false unless __raw_model == other.__raw_model
98
- return false unless __destroy == other.__destroy
64
+ return false unless __raw_model == other.__raw_model # steep:ignore
99
65
 
100
66
  true
101
67
  end
102
68
 
69
+ # @private
103
70
  # Returns a model instance of raw, but it should
104
71
  # be noted that application developers are not expected to use this interface.
105
72
  #
106
73
  # @return [Object] raw model instance
107
74
  def __raw_model = model
108
75
 
109
- # Returns a model instance of raw, but it should
110
- # be noted that application developers are not expected to use this interface.
111
- #
112
- # @return [Boolean] raw destroy instance
113
- # @return [Proc] raw destroy instance
114
- def __destroy = destroy
115
-
116
76
  private
117
77
 
118
- attr_reader :owner, :model, :destroy
119
-
120
- def deprecator
121
- if ActiveRecord.respond_to?(:deprecator)
122
- ActiveRecord.deprecator
123
- else # for rails 7.0.x or lower
124
- ActiveSupport::Deprecation
125
- end
126
- end
78
+ attr_reader :model, :destroy_context_type
127
79
  end
128
80
  end
@@ -8,6 +8,7 @@ module ActiveRecordCompose
8
8
 
9
9
  def initialize(owner)
10
10
  @owner = owner
11
+ @models = []
11
12
  end
12
13
 
13
14
  # Enumerates model objects.
@@ -35,10 +36,11 @@ module ActiveRecordCompose
35
36
  #
36
37
  # @param model [Object] the model instance
37
38
  # @param destroy [Boolean] given true, destroy model.
38
- # @param context [Symbol] :save or :destroy
39
+ # @param destroy [Proc] when proc returning true, destroy model.
40
+ # @param destroy [Symbol] applies boolean value of result of sending a message to `owner` to evaluation.
39
41
  # @return [self] returns itself.
40
- def push(model, destroy: false, context: nil)
41
- models << wrap(model, destroy:, context:)
42
+ def push(model, destroy: false)
43
+ models << wrap(model, destroy:)
42
44
  self
43
45
  end
44
46
 
@@ -59,17 +61,16 @@ module ActiveRecordCompose
59
61
  # Returns nil if the deletion fails, self if it succeeds.
60
62
  #
61
63
  # @param model [Object] the model instance
62
- # @param destroy [Boolean] given true, destroy model.
63
- # @param context [Symbol] :save or :destroy
64
64
  # @return [self] Successful deletion
65
65
  # @return [nil] If deletion fails
66
- def delete(model, destroy: false, context: nil)
67
- wrapped = wrap(model, destroy:, context:)
66
+ def delete(model)
67
+ wrapped = wrap(model)
68
68
  return nil unless models.delete(wrapped)
69
69
 
70
70
  self
71
71
  end
72
72
 
73
+ # @private
73
74
  # Enumerates model objects, but it should be noted that
74
75
  # application developers are not expected to use this interface.
75
76
  #
@@ -85,17 +86,19 @@ module ActiveRecordCompose
85
86
 
86
87
  private
87
88
 
88
- attr_reader :owner
89
-
90
- def models = @models ||= []
89
+ attr_reader :owner, :models
91
90
 
92
- def wrap(model, destroy:, context: nil)
91
+ def wrap(model, destroy: false)
93
92
  if model.is_a?(ActiveRecordCompose::InnerModel) # steep:ignore
94
93
  # @type var model: ActiveRecordCompose::InnerModel
95
94
  model
96
95
  else
96
+ if destroy.is_a?(Symbol)
97
+ method = destroy
98
+ destroy = -> { owner.__send__(method) }
99
+ end
97
100
  # @type var model: ActiveRecordCompose::_ARLike
98
- ActiveRecordCompose::InnerModel.new(owner, model, destroy:, context:)
101
+ ActiveRecordCompose::InnerModel.new(model, destroy:)
99
102
  end
100
103
  end
101
104
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordCompose
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0'
5
5
  end
@@ -3,8 +3,6 @@
3
3
  require 'active_record'
4
4
 
5
5
  require_relative 'active_record_compose/version'
6
- require_relative 'active_record_compose/inner_model'
7
- require_relative 'active_record_compose/inner_model_collection'
8
6
  require_relative 'active_record_compose/model'
9
7
 
10
8
  module ActiveRecordCompose
@@ -15,8 +15,7 @@ module ActiveRecordCompose
15
15
  end
16
16
 
17
17
  type attribute_name = (String | Symbol)
18
- type context = (:save | :destroy)
19
- type context_proc = ((^() -> context) | (^(_ARLike) -> context))
18
+ type destroy_context_type = (bool | Symbol | (^() -> boolish) | (^(_ARLike) -> boolish))
20
19
 
21
20
  module DelegateAttribute
22
21
  extend ActiveSupport::Concern
@@ -30,28 +29,23 @@ module ActiveRecordCompose
30
29
 
31
30
  class InnerModelCollection
32
31
  include ::Enumerable[_ARLike]
33
- @owner: Model
34
- @models: Array[InnerModel]
35
32
 
36
33
  def initialize: (Model) -> void
37
34
  def each: () { (_ARLike) -> void } -> InnerModelCollection | () -> Enumerator[_ARLike, self]
38
35
  def <<: (_ARLike) -> self
39
- def push: (_ARLike, ?destroy: bool, ?context: (nil | context | context_proc)) -> self
36
+ def push: (_ARLike, ?destroy: destroy_context_type) -> self
40
37
  def empty?: -> bool
41
38
  def clear: -> self
42
- def delete: (_ARLike | InnerModel, ?destroy: bool, ?context: (nil | context | context_proc)) -> InnerModelCollection?
39
+ def delete: (_ARLike | InnerModel) -> InnerModelCollection?
43
40
 
44
41
  private
45
42
  attr_reader owner: Model
46
- def models: -> Array[InnerModel]
47
- def wrap: (_ARLike | InnerModel, destroy: bool, ?context: (nil | context | context_proc)) -> InnerModel
43
+ attr_reader models: Array[InnerModel]
44
+ def wrap: (_ARLike | InnerModel, ?destroy: destroy_context_type) -> InnerModel
48
45
  end
49
46
 
50
47
  class InnerModel
51
- @owner: Model
52
- @context: (context | context_proc)
53
-
54
- def initialize: (Model, _ARLike, ?destroy: bool, ?context: (nil | context | context_proc)) -> void
48
+ def initialize: (_ARLike, ?destroy: destroy_context_type) -> void
55
49
  def destroy_context?: -> bool
56
50
  def save: -> bool
57
51
  def save!: -> untyped
@@ -60,8 +54,8 @@ module ActiveRecordCompose
60
54
  def ==: (untyped) -> bool
61
55
 
62
56
  private
63
- attr_reader owner: Model
64
57
  attr_reader model: _ARLike
58
+ attr_reader destroy_context_type: destroy_context_type
65
59
  end
66
60
 
67
61
  class Model
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_compose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hamajyotan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-14 00:00:00.000000000 Z
11
+ date: 2024-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  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.4.0
55
+ documentation_uri: https://www.rubydoc.info/gems/active_record_compose/0.5.0
56
56
  rubygems_mfa_required: 'true'
57
57
  post_install_message:
58
58
  rdoc_options: []
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
71
  requirements: []
72
- rubygems_version: 3.5.18
72
+ rubygems_version: 3.5.11
73
73
  signing_key:
74
74
  specification_version: 4
75
75
  summary: activemodel form object pattern