class Tint::Decorator

Attributes

_attributes[RW]
_override_methods[RW]
parent_association[RW]
parent_decorator[RW]
object_attributes[RW]

Public Class Methods

already_eager_loaded_associations?(object) click to toggle source
# File lib/tint/decorator.rb, line 144
def already_eager_loaded_associations?(object)
  if object.respond_to?(:association_cache)
    object.association_cache.any?
  else
    true
  end
end
attributes(*options) click to toggle source
# File lib/tint/decorator.rb, line 38
def attributes(*options)
  @_attributes ||= Set.new

  return if options.blank?

  mapped_attrs = options.extract_options!

  link_mappings_to_object(mapped_attrs)

  delegated_attrs = options

  link_delegations_to_object(delegated_attrs)
end
decorate(object, options = {}) click to toggle source
Calls superclass method
# File lib/tint/decorator.rb, line 98
def decorate(object, options = {})
  object_class = object.class

  _object_attributes =
      if object.present? && object.respond_to?(:attributes)
        object.attributes
      else
        {}
      end

  @object_attributes =
      if _object_attributes && _object_attributes.kind_of?(Hash)
        _object_attributes
      else
        {}
      end

  unless already_eager_loaded_associations?(object)
    object =
        if responds_to_methods?(object_class, :includes, :find) && eager_loads.present?
          object_class.includes(eager_loads).find(object.id)
        else
          object
        end
  end

  super
end
decorate_collection(collection, options = {}) click to toggle source
Calls superclass method
# File lib/tint/decorator.rb, line 83
def decorate_collection(collection, options = {})

  collection_with_eager_loads =
    if collection.respond_to?(:includes) &&
      eager_loads.present?  &&
       !parent_eager_loads_include_own?(options[:context])

      collection.includes(eager_loads)
    else
      collection
    end

  super(collection_with_eager_loads, options)
end
decorates_association(*args) click to toggle source
# File lib/tint/decorator.rb, line 56
def decorates_association(*args)
  options = args.extract_options!
  association_chain = args

  association_tail = association_chain.last

  options[:with] ||= (association_tail.to_s.camelize.singularize + 'Decorator').constantize

  association_alias = options.delete(:as) || association_tail

  options.assert_valid_keys(:with, :scope, :context)

  define_association_method(association_alias, association_chain, options)

  eager_load_association(association_chain, options)
end
decorates_associations(*arguments) click to toggle source
# File lib/tint/decorator.rb, line 73
def decorates_associations(*arguments)

  options = arguments.extract_options!
  association_list = arguments

  association_list.each do |association_name|
    decorates_association(association_name, options.dup)
  end
end
eager_load(*schema) click to toggle source
# File lib/tint/decorator.rb, line 52
def eager_load(*schema)
  self.eager_loads = self.eager_loads.deeper_merge(expand_schema(schema))
end
eager_loads() click to toggle source
# File lib/tint/decorator.rb, line 30
def eager_loads
  @_eager_loads ||= {}
end
eager_loads=(value) click to toggle source
# File lib/tint/decorator.rb, line 34
def eager_loads=(value)
  @_eager_loads = value
end
ids_for(*options) click to toggle source
# File lib/tint/decorator.rb, line 160
def ids_for(*options)
  mapped_attrs = options.extract_options!

  attribute_options = options.map do |association_name|
    association_method = method_name_from_association(association_name)
    eager_load(association_name)
    association_method
  end

  attribute_options.push(
      mapped_attrs.inject({}) do |memo, key_and_value|
        association_name, value = key_and_value
        memo[value] = method_name_from_association(association_name)

        eager_load(association_name)
        memo
      end
  )

  attributes(*attribute_options)
end
new(object, options = {}) click to toggle source
Calls superclass method
# File lib/tint/decorator.rb, line 13
def initialize(object, options = {})
  super(object, options.except(:parent_decorator, :parent_association))
  @object_attributes = {}
  @context = @context.merge(options.slice(:parent_decorator, :parent_association))
end
parent_eager_loads_include_own?(context = {}) click to toggle source
# File lib/tint/decorator.rb, line 127
def parent_eager_loads_include_own?(context = {})

  if context && context[:parent_decorator]
    if (parent_eager_loads = context[:parent_decorator].class.eager_loads)

      association_eager_load =
        context[:parent_association].inject(parent_eager_loads) do |memo, chain_link|
          memo[chain_link] if memo
        end

      !!association_eager_load
    end
  else
    false
  end
end
responds_to_methods?(object, *methods) click to toggle source
# File lib/tint/decorator.rb, line 152
def responds_to_methods?(object, *methods)
  methods.each do |method_name|
    return false unless object.respond_to?(method_name)
  end

  true
end

Private Class Methods

association_schema(association_chain, eager_loads = {}) click to toggle source
# File lib/tint/decorator.rb, line 258
def association_schema(association_chain, eager_loads = {})
  association_chain.reverse.reduce({}) do |memo, chain_link|

    if chain_link == association_chain.last
      { chain_link => eager_loads }
    else
      { chain_link => memo }
    end
  end
end
define_association_method(association_alias, association_chain, options) click to toggle source
# File lib/tint/decorator.rb, line 232
def define_association_method(association_alias, association_chain, options)
  define_method(association_alias) do
    context_with_association = context.merge({
         parent_decorator: self,
         parent_association: association_chain
     })

    decorated_associations[association_alias] ||= Tint::DecoratedAssociation.new(
        self,
        association_chain,
        options.merge(context: context_with_association)
    )

    decorated_associations[association_alias].call
  end

  attributes(association_alias)
end
eager_load_association(association_chain, options) click to toggle source
# File lib/tint/decorator.rb, line 251
def eager_load_association(association_chain, options)
  association_eager_loads = options[:with].eager_loads
  schema = association_schema(association_chain, association_eager_loads)

  eager_load(schema)
end
expand_schema(schema) click to toggle source
# File lib/tint/decorator.rb, line 217
def expand_schema(schema)
  if schema.kind_of?(Hash)
    schema.inject({}) do |memo, (schema_key, schema_value)|
      memo[schema_key] = expand_schema(schema_value)
      memo
    end
  elsif schema.kind_of?(Array)
    schema.inject({}) do |memo, schema_item|
      memo.merge(expand_schema(schema_item))
    end
  else
    { schema => {} }
  end
end
method_name_from_association(association) click to toggle source
# File lib/tint/decorator.rb, line 184
def method_name_from_association(association)
  association.to_s.singularize + '_ids'
end

Public Instance Methods

column_names() click to toggle source
# File lib/tint/decorator.rb, line 19
def column_names
  object.class.column_names
end
persisted?() click to toggle source
# File lib/tint/decorator.rb, line 23
def persisted?
  object.persisted?
end