class Composition::Compositions::Compose

Public Instance Methods

actual_column_for(aliased_attribute) click to toggle source
# File lib/composition/compositions/compose.rb, line 56
def actual_column_for(aliased_attribute)
  mapping.key(aliased_attribute)
end
getter(ar) click to toggle source

For a composition defined like:

class User < ActiveRecord::Base
  compose :credit_card,
          mapping: {
            credit_card_name: :name,
            credit_card_brand: :brand
          }
end

The getter method will be in charge of implementing @user.credit_card.

It is responsible for instantiating a new CreditCard object with the attributes from the de-normalized columns in User, and then return it.

# File lib/composition/compositions/compose.rb, line 19
def getter(ar)
  attributes = attributes(ar)
  klass.new(attributes.merge(composed_from.name => ar)).tap(&:valid?) unless all_blank?(attributes)
end
mapping() click to toggle source
# File lib/composition/compositions/compose.rb, line 52
def mapping
  @options[:mapping]
end
setter(ar, setter_value) click to toggle source

For a composition defined like:

class User < ActiveRecord::Base
  compose :credit_card,
          mapping: {
            credit_card_name: :name,
            credit_card_brand: :brand
          }
end

The setter method will be in charge of implementing @user.credit_card=.

setter_value can be either a credit_card instance or a hash of attributes and the setter will only set the @credit_card attributes that are included in the hash. This means that if a credit_card attribute is not given in the hash then we'll set it with the value from the @user de-normalized column. The reason behind this is to imitate how ActiveRecord assign_attributes method works.

# File lib/composition/compositions/compose.rb, line 41
def setter(ar, setter_value)
  nil_columns(ar) and return if setter_value.nil?
  attributes = setter_value.to_h.with_indifferent_access

  mapping.each do |actual_column, composed_alias|
    ar.send("#{actual_column}=", attributes[composed_alias]) if attributes.key?(composed_alias)
  end

  setter_value
end

Private Instance Methods

all_blank?(attributes = {}) click to toggle source
# File lib/composition/compositions/compose.rb, line 70
def all_blank?(attributes = {})
  attributes.all? { |_, value| value.blank? }
end
attributes(ar) click to toggle source

Returns the hash of attributes for instantiating the composition defined for a given class.

# File lib/composition/compositions/compose.rb, line 64
def attributes(ar)
  mapping.each_with_object({}) do |(actual_column, composed_alias), memo|
    memo[composed_alias] = ar.send(actual_column)
  end
end
composed_from() click to toggle source

TODO: Add descriptive error if find returns nil. “composed_from is missing”

# File lib/composition/compositions/compose.rb, line 79
def composed_from
  klass._composition_reflections.find { |_, composition| composition.class_name == inverse_of }.last
end
nil_columns(ar) click to toggle source
# File lib/composition/compositions/compose.rb, line 74
def nil_columns(ar)
  mapping.each { |actual_column, _| ar.send("#{actual_column}=", nil) }
end