55require_relative "attributes/querying"
66
77module ActiveRecordCompose
8- # @private
9- #
108 # Provides attribute-related functionality for use within ActiveRecordCompose::Model.
119 #
1210 # This module allows you to define attributes on your composed model, including support
@@ -56,47 +54,32 @@ module Attributes
5654 include ActiveModel ::Attributes
5755
5856 included do
57+ # @type self: Class
58+
5959 include Querying
6060
61- # @type self: Class
6261 class_attribute :delegated_attributes , instance_writer : false
6362 end
6463
6564 # steep:ignore:start
6665
6766 class_methods do
68- # Defines the reader and writer for the specified attribute.
69- #
70- # @example
71- # class AccountRegistration < ActiveRecordCompose::Model
72- # def initialize(account, attributes = {})
73- # @account = account
74- # super(attributes)
75- # models.push(account)
76- # end
77- #
78- # attribute :original_attribute, :string, default: "qux"
79- # delegate_attribute :name, to: :account
80- #
81- # private
82- #
83- # attr_reader :account
84- # end
85- #
86- # account = Account.new
87- # account.name = "foo"
88- #
89- # registration = AccountRegistration.new(account)
90- # registration.name # => "foo" (delegated)
91- # registration.name? # => true (delegated attribute method + `?`)
92- #
93- # registration.name = "bar" # => updates account.name
94- # account.name # => "bar"
95- # account.name? # => true
67+ # Provides a method of attribute access to the encapsulated model.
9668 #
97- # registration. attributes
98- # # => { "original_attribute" => "qux", "name" => "bar" }
69+ # It provides a way to access the attributes of the model it encompasses,
70+ # allowing transparent access as if it had those attributes itself.
9971 #
72+ # @param [Array<Symbol, String>] attributes
73+ # attributes A variable-length list of attribute names to delegate.
74+ # @param [Symbol, String] to
75+ # The target object to which attributes are delegated (keyword argument).
76+ # @param [Boolean] allow_nil
77+ # allow_nil Whether to allow nil values. Defaults to false.
78+ # @example Basic usage
79+ # delegate_attribute :name, :email, to: :profile
80+ # @example Allowing nil
81+ # delegate_attribute :bio, to: :profile, allow_nil: true
82+ # @see Module#delegate for similar behavior in ActiveSupport
10083 def delegate_attribute ( *attributes , to :, allow_nil : false )
10184 if to . start_with? ( "@" )
10285 raise ArgumentError , "Instance variables cannot be specified in delegate to. (#{ to } )"
@@ -109,47 +92,68 @@ def delegate_attribute(*attributes, to:, allow_nil: false)
10992 end
11093
11194 # Returns a array of attribute name.
112- # Attributes declared with ` delegate_attribute` are also merged.
95+ # Attributes declared with {. delegate_attribute} are also merged.
11396 #
97+ # @see #attribute_names
11498 # @return [Array<String>] array of attribute name.
11599 def attribute_names = super + delegated_attributes . to_a . map { _1 . attribute_name }
116100 end
117101
118102 # steep:ignore:end
119103
120104 # Returns a array of attribute name.
121- # Attributes declared with ` delegate_attribute` are also merged.
105+ # Attributes declared with {. delegate_attribute} are also merged.
122106 #
107+ # class Foo < ActiveRecordCompose::Base
108+ # def initialize(attributes = {})
109+ # @account = Account.new
110+ # super
111+ # end
112+ #
113+ # attribute :confirmation, :boolean, default: false # plain attribute
114+ # delegate_attribute :name, to: :account # delegated attribute
115+ #
116+ # private
117+ #
118+ # attr_reader :account
119+ # end
120+ #
121+ # Foo.attribute_names # Returns the merged state of plain and delegated attributes
122+ # # => ["confirmation" ,"name"]
123+ #
124+ # foo = Foo.new
125+ # foo.attribute_names # Similar behavior for instance method version
126+ # # => ["confirmation", "name"]
127+ #
128+ # @see #attributes
123129 # @return [Array<String>] array of attribute name.
124130 def attribute_names = super + delegated_attributes . to_a . map { _1 . attribute_name }
125131
126132 # Returns a hash with the attribute name as key and the attribute value as value.
127- # Attributes declared with ` delegate_attribute` are also merged.
133+ # Attributes declared with {. delegate_attribute} are also merged.
128134 #
129- # @return [Hash] hash with the attribute name as key and the attribute value as value.
130- # @example
131- # class AccountRegistration < ActiveRecordCompose::Model
132- # def initialize(account, attributes = {})
133- # @account = account
134- # super(attributes)
135- # models.push(account)
136- # end
135+ # class Foo < ActiveRecordCompose::Base
136+ # def initialize(attributes = {})
137+ # @account = Account.new
138+ # super
139+ # end
137140 #
138- # attribute :original_attribute , :string , default: "qux"
139- # delegate_attribute :name, to: :account
141+ # attribute :confirmation , :boolean , default: false # plain attribute
142+ # delegate_attribute :name, to: :account # delegated attribute
140143 #
141- # private
144+ # private
142145 #
143- # attr_reader :account
144- # end
145- #
146- # account = Account.new
147- # account.name = "foo"
146+ # attr_reader :account
147+ # end
148148 #
149- # registration = AccountRegistration.new(account)
149+ # foo = Foo.new
150+ # foo.name = "Alice"
151+ # foo.confirmation = true
150152 #
151- # registration.attributes # => { "original_attribute" => "qux", "name" => "bar" }
153+ # foo.attributes # Returns the merged state of plain and delegated attributes
154+ # # => { "confirmation" => true, "name" => "Alice" }
152155 #
156+ # @return [Hash<String, Object>] hash with the attribute name as key and the attribute value as value.
153157 def attributes
154158 super . merge ( *delegated_attributes . to_a . map { _1 . attribute_hash ( self ) } )
155159 end
0 commit comments