Module: ActiveRecordCompose::Attributes

Extended by:
ActiveSupport::Concern
Includes:
ActiveModel::Attributes
Included in:
Inspectable, Model
Defined in:
lib/active_record_compose/attributes.rb,
lib/active_record_compose/attributes/querying.rb,
lib/active_record_compose/attributes/delegation.rb,
lib/active_record_compose/attributes/attribute_predicate.rb

Overview

Provides attribute-related functionality for use within ActiveRecordCompose::Model.

This module allows you to define attributes on your composed model, including support for query methods (e.g., #attribute?) and delegation of attributes to underlying ActiveRecord instances via macros.

For example, .delegate_attribute defines attribute accessors that delegate to a specific model, similar to:

delegate :name, :name=, to: :account

Additionally, delegated attributes are included in the composed model's #attributes hash.

Examples:

class AccountRegistration < ActiveRecordCompose::Model
  def initialize(, attributes = {})
    @account = 
    super(attributes)
    models.push()
  end

  attribute :original_attribute, :string, default: "qux"
  delegate_attribute :name, to: :account

  private

  attr_reader :account
end

 = Account.new
.name = "foo"

registration = AccountRegistration.new()
registration.name         # => "foo" (delegated)
registration.name?        # => true  (delegated attribute method + `?`)

registration.name = "bar" # => updates account.name
.name              # => "bar"
.name?             # => true

registration.attributes
# => { "original_attribute" => "qux", "name" => "bar" }

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.attribute_namesArray<String>

Returns a array of attribute name. Attributes declared with delegate_attribute are also merged.

Returns:

  • (Array<String>)

    array of attribute name.

See Also:



99
# File 'lib/active_record_compose/attributes.rb', line 99

def attribute_names = super + delegated_attributes.to_a.map { _1.attribute_name }

.delegate_attribute(*attributes, to:, allow_nil: false) ⇒ void

Provides a method of attribute access to the encapsulated model.

It provides a way to access the attributes of the model it encompasses, allowing transparent access as if it had those attributes itself.

Examples:

Basic usage

delegate_attribute :name, :email, to: :profile

Allowing nil

delegate_attribute :bio, to: :profile, allow_nil: true

Parameters:

  • attributes (Array<Symbol, String>)

    attributes A variable-length list of attribute names to delegate.

  • to (Symbol, String)

    The target object to which attributes are delegated (keyword argument).

  • allow_nil (Boolean) (defaults to: false)

    allow_nil Whether to allow nil values. Defaults to false.

See Also:

  • for similar behavior in ActiveSupport


83
84
85
86
87
88
89
90
91
92
# File 'lib/active_record_compose/attributes.rb', line 83

def delegate_attribute(*attributes, to:, allow_nil: false)
  if to.start_with?("@")
    raise ArgumentError, "Instance variables cannot be specified in delegate to. (#{to})"
  end

  delegations = attributes.map { Delegation.new(attribute: _1, to:, allow_nil:) }
  delegations.each { _1.define_delegated_attribute(self) }

  self.delegated_attributes = (delegated_attributes.to_a + delegations).reverse.uniq { _1.attribute }.reverse
end

Instance Method Details

#attribute_namesArray<String>

Returns a array of attribute name. Attributes declared with delegate_attribute are also merged.

class Foo < ActiveRecordCompose::Base
  def initialize(attributes = {})
    @account = Account.new
    super
  end

  attribute :confirmation, :boolean, default: false   # plain attribute
  delegate_attribute :name, to: :account              # delegated attribute

  private

  attr_reader :account
end

Foo.attribute_names                                   # Returns the merged state of plain and delegated attributes
# => ["confirmation" ,"name"]

foo = Foo.new
foo.attribute_names                                   # Similar behavior for instance method version
# => ["confirmation", "name"]

Returns:

  • (Array<String>)

    array of attribute name.

See Also:



130
# File 'lib/active_record_compose/attributes.rb', line 130

def attribute_names = super + delegated_attributes.to_a.map { _1.attribute_name }

#attributesHash<String, Object>

Returns a hash with the attribute name as key and the attribute value as value. Attributes declared with delegate_attribute are also merged.

class Foo < ActiveRecordCompose::Base
  def initialize(attributes = {})
    @account = Account.new
    super
  end

  attribute :confirmation, :boolean, default: false   # plain attribute
  delegate_attribute :name, to: :account              # delegated attribute

  private

  attr_reader :account
end

foo = Foo.new
foo.name = "Alice"
foo.confirmation = true

foo.attributes                                        # Returns the merged state of plain and delegated attributes
# => { "confirmation" => true, "name" => "Alice" }

Returns:

  • (Hash<String, Object>)

    hash with the attribute name as key and the attribute value as value.



157
158
159
# File 'lib/active_record_compose/attributes.rb', line 157

def attributes
  super.merge(*delegated_attributes.to_a.map { _1.attribute_hash(self) })
end