active_record_compose 0.1.0 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f87118b489cd061b4912c625ec2b9bdc91ad4b024e69cd6a6c45ab9c884018f3
4
- data.tar.gz: 22eec41668831a5f97d5935502d4c4d61de723b78dd2f70d2dca2bbfb4d9fa52
3
+ metadata.gz: b6881ca78dfbf9fc5fc15cf72ac6073c4780d4b7b32747fc1b58a0147adce3fe
4
+ data.tar.gz: 37a7dfa3d4de10d2a35ea6a10a9d3e131809eba27ef60cb5b917b1b736f209e7
5
5
  SHA512:
6
- metadata.gz: 180d9e45c2e18dc362d0169a22040759614882e09254c4fc8ad80ead07302c280446cab288c5042f81f33d339ab00b114d888536f691ab817063dc5dc6765cc0
7
- data.tar.gz: a4ba3164829709bbdbb38f0232b555ef210b6ce0783348317c430ffb9d1931f9b9b48bec3f28fefe757ee9ce6f9c8b3dcfb3a53ec557650eab4d6e7a8870e13f
6
+ metadata.gz: abc371fd146961cec4f4b8d234367734e772aaab9b08450debb1a79adba4fa5703fd169090d1d636c95f56a89ec0184e5c7db2f4bb04f61609dc925e5fe08ffa
7
+ data.tar.gz: 427c2bd3151f1fba2541795aa36f645952a87930ccd92fb0d1d7a9a1144d7486c30180cd0b021c1660aab380dd1cb887191fe37c1dc069b0d3cd5197f7c3ace0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2023-07-29
3
+ ## [0.1.1] - 2024-01-08
4
+
5
+ - fix 0.1.0 release date.
6
+ - add doc.
7
+ - Make it easier for application developers to work with `#models`
8
+
9
+ ## [0.1.0] - 2024-01-06
4
10
 
5
11
  - Initial release
data/README.md CHANGED
@@ -199,7 +199,7 @@ It provides a macro description that expresses access to the attributes of the A
199
199
 
200
200
  ```ruby
201
201
  class AccountRegistration < ActiveRecordCompose::Model
202
- def initialize(account)
202
+ def initialize(account, attributes = {})
203
203
  @account = account
204
204
  super(attributes)
205
205
  models.push(account)
@@ -1,6 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordCompose
4
+ # = Delegate \Attribute
5
+ #
6
+ # It provides a macro description that expresses access to the attributes of the AR model through delegation.
7
+ #
8
+ # class AccountRegistration < ActiveRecordCompose::Model
9
+ # def initialize(account, attributes = {})
10
+ # @account = account
11
+ # super(attributes)
12
+ # models.push(account)
13
+ # end
14
+ #
15
+ # attribute :original_attribute, :string, default: 'qux'
16
+ #
17
+ # # like a `delegate :name, :name=, to: :account`
18
+ # delegate_attribute :name, to: :account
19
+ #
20
+ # private
21
+ #
22
+ # attr_reader :account
23
+ # end
24
+ #
25
+ # account = Account.new
26
+ # account.name = 'foo'
27
+ #
28
+ # registration = AccountRegistration.new(account)
29
+ # registration.name #=> 'foo' # delegate to account#name
30
+ #
31
+ # registration.name = 'bar' # delegate to account#name=
32
+ # account.name #=> 'bar'
33
+ #
34
+ # # Attributes defined in delegate_attribute will be included in the original `#attributes`.
35
+ # registration.attributes #=> { 'original_attribute' => 'qux', 'name' => 'bar' }
36
+ #
4
37
  module DelegateAttribute
5
38
  extend ActiveSupport::Concern
6
39
 
@@ -1,40 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/object'
4
+
3
5
  module ActiveRecordCompose
4
6
  class InnerModel
5
- def initialize(inner_model, context: :save)
6
- @inner_model = inner_model
7
+ # @param model [Object] the model instance.
8
+ # @param context [Symbol] :save or :destroy
9
+ def initialize(model, context: :save)
10
+ @model = model
7
11
  @context = context
8
12
  end
9
13
 
10
- delegate :errors, to: :inner_model
14
+ delegate :errors, to: :model
11
15
 
16
+ # @return [Symbol] :save or :destroy
12
17
  def context
13
- @context.respond_to?(:call) ? @context.call(inner_model) : @context
18
+ ret = @context.respond_to?(:call) ? @context.call(model) : @context
19
+ ret.presence_in(%i[save destroy]) || :save
14
20
  end
15
21
 
22
+ # @return [InnerModel] self
16
23
  def save!
17
24
  case context
18
25
  when :destroy
19
- inner_model.destroy!
26
+ model.destroy!
20
27
  else
21
- inner_model.save!
28
+ model.save!
22
29
  end
23
30
  end
24
31
 
32
+ # @return [Boolean]
25
33
  def invalid?
26
34
  case context
27
35
  when :destroy
28
36
  false
29
37
  else
30
- inner_model.invalid?
38
+ model.invalid?
31
39
  end
32
40
  end
33
41
 
42
+ # @return [Boolean]
34
43
  def valid? = !invalid?
35
44
 
45
+ # Returns a model instance of raw, but it should
46
+ # be noted that application developers are not expected to use this interface.
47
+ #
48
+ # @return [Object] raw model instance
49
+ def __raw_model = model
50
+
36
51
  private
37
52
 
38
- attr_reader :inner_model
53
+ attr_reader :model
39
54
  end
40
55
  end
@@ -6,36 +6,59 @@ module ActiveRecordCompose
6
6
  class InnerModelCollection
7
7
  include Enumerable
8
8
 
9
- def initialize
10
- @inner_models = []
11
- end
12
-
9
+ # Enumerates model objects.
10
+ #
11
+ # @yieldparam [Object] the model instance
12
+ # @return [Enumerator] when not block given.
13
+ # @return [InnerModelCollection] self
13
14
  def each
14
15
  return enum_for(:each) unless block_given?
15
16
 
16
- inner_models.each { yield _1 }
17
+ models.each { yield _1.__raw_model }
18
+ self
19
+ end
20
+
21
+ # Appends model to collection.
22
+ #
23
+ # @param model [Object] the model instance
24
+ # @param context [Symbol] :save or :destroy
25
+ # @return [InnerModelCollection] self
26
+ def <<(model)
27
+ models << wrap(model, context: :save)
17
28
  self
18
29
  end
19
30
 
20
- def <<(inner_model)
21
- inner_models << wrap(inner_model, context: :save)
31
+ # Appends model to collection.
32
+ #
33
+ # @param model [Object] the model instance
34
+ # @return [InnerModelCollection] self
35
+ def push(model, context: :save)
36
+ models << wrap(model, context:)
22
37
  self
23
38
  end
24
39
 
25
- def push(inner_model, context: :save)
26
- inner_models << wrap(inner_model, context:)
40
+ # Enumerates model objects, but it should be noted that
41
+ # application developers are not expected to use this interface.
42
+ #
43
+ # @yieldparam [InnerModel] rawpped model instance.
44
+ # @return [Enumerator] when not block given.
45
+ # @return [InnerModelCollection] self
46
+ def __each_by_wrapped
47
+ return enum_for(:__each_by_wrapped) unless block_given?
48
+
49
+ models.each { yield _1 }
27
50
  self
28
51
  end
29
52
 
30
53
  private
31
54
 
32
- attr_reader :inner_models
55
+ def models = @models ||= []
33
56
 
34
- def wrap(inner_model, context:)
35
- if inner_model.is_a?(ActiveRecordCompose::InnerModel)
36
- inner_model
57
+ def wrap(model, context:)
58
+ if model.is_a?(ActiveRecordCompose::InnerModel)
59
+ model
37
60
  else
38
- ActiveRecordCompose::InnerModel.new(inner_model, context:)
61
+ ActiveRecordCompose::InnerModel.new(model, context:)
39
62
  end
40
63
  end
41
64
  end
@@ -32,6 +32,31 @@ module ActiveRecordCompose
32
32
 
33
33
  def save! = save || raise(error_class_on_save_error.new('Failed to save the model.', self))
34
34
 
35
+ # Behavior is same to `#save`, but `before_create` and `after_create` hooks fires.
36
+ #
37
+ # class ComposedModel < ActiveRecordCompose::Model
38
+ # # ...
39
+ #
40
+ # before_save { puts 'before_save called!' }
41
+ # before_create { puts 'before_create called!' }
42
+ # before_update { puts 'before_update called!' }
43
+ # after_save { puts 'after_save called!' }
44
+ # after_create { puts 'after_create called!' }
45
+ # after_update { puts 'after_update called!' }
46
+ # end
47
+ #
48
+ # model = ComposedModel.new
49
+ #
50
+ # model.save
51
+ # # before_save called!
52
+ # # after_save called!
53
+ #
54
+ # model.create
55
+ # # before_save called!
56
+ # # before_create called!
57
+ # # after_create called!
58
+ # # after_save called!
59
+ #
35
60
  def create(attributes = {})
36
61
  assign_attributes(attributes)
37
62
  return false if invalid?
@@ -39,10 +64,37 @@ module ActiveRecordCompose
39
64
  save_in_transaction { run_callbacks(:save) { run_callbacks(:create) { save_models } } }
40
65
  end
41
66
 
67
+ # Behavior is same to `#create`, but raises an exception prematurely on failure.
68
+ #
42
69
  def create!(attributes = {})
43
70
  create(attributes) || raise(error_class_on_save_error.new('Failed to create the model.', self))
44
71
  end
45
72
 
73
+ # Behavior is same to `#save`, but `before_update` and `after_update` hooks fires.
74
+ #
75
+ # class ComposedModel < ActiveRecordCompose::Model
76
+ # # ...
77
+ #
78
+ # before_save { puts 'before_save called!' }
79
+ # before_create { puts 'before_create called!' }
80
+ # before_update { puts 'before_update called!' }
81
+ # after_save { puts 'after_save called!' }
82
+ # after_create { puts 'after_create called!' }
83
+ # after_update { puts 'after_update called!' }
84
+ # end
85
+ #
86
+ # model = ComposedModel.new
87
+ #
88
+ # model.save
89
+ # # before_save called!
90
+ # # after_save called!
91
+ #
92
+ # model.update
93
+ # # before_save called!
94
+ # # before_update called!
95
+ # # after_update called!
96
+ # # after_save called!
97
+ #
46
98
  def update(attributes = {})
47
99
  assign_attributes(attributes)
48
100
  return false if invalid?
@@ -50,6 +102,8 @@ module ActiveRecordCompose
50
102
  save_in_transaction { run_callbacks(:save) { run_callbacks(:update) { save_models } } }
51
103
  end
52
104
 
105
+ # Behavior is same to `#update`, but raises an exception prematurely on failure.
106
+ #
53
107
  def update!(attributes = {})
54
108
  update(attributes) || raise(error_class_on_save_error.new('Failed to update the model.', self))
55
109
  end
@@ -58,7 +112,9 @@ module ActiveRecordCompose
58
112
 
59
113
  def models = @models ||= ActiveRecordCompose::InnerModelCollection.new
60
114
 
61
- def validate_models = models.select { _1.invalid? }.each { errors.merge!(_1) }
115
+ def wrapped_models = models.__each_by_wrapped
116
+
117
+ def validate_models = wrapped_models.select { _1.invalid? }.each { errors.merge!(_1) }
62
118
 
63
119
  def save_in_transaction
64
120
  run_callbacks(:commit) do
@@ -74,6 +130,6 @@ module ActiveRecordCompose
74
130
  end.present?
75
131
  end
76
132
 
77
- def save_models = models.all? { _1.save! }
133
+ def save_models = wrapped_models.all? { _1.save! }
78
134
  end
79
135
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordCompose
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
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.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - hamajyotan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-06 00:00:00.000000000 Z
11
+ date: 2024-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -49,6 +49,8 @@ homepage: https://github.com/active_record_compose
49
49
  licenses:
50
50
  - MIT
51
51
  metadata:
52
+ changelog_uri: https://github.com/hamajyotan/active_record_compose/blob/main/CHANGELOG.md
53
+ source_code_uri: https://github.com/hamajyotan/active_record_compose
52
54
  rubygems_mfa_required: 'true'
53
55
  post_install_message:
54
56
  rdoc_options: []