class SelfishAssociations::Association

Public Class Methods

new(name, model, scope = nil, options = {}) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 12
def initialize(name, model, scope = nil, options = {})
  options = options.symbolize_keys
  @name = name.to_s
  @model = model
  @foreign_class_name = (options[:class_name] || name.to_s.classify).to_s
  @foreign_key = options[:foreign_key] == false ? false : (options[:foreign_key] || @model.name.foreign_key).to_sym
  @scopes = []

  add_scope(scope) if scope.present?
  add_scope(foreign_key_scope) if @foreign_key.present?
  validate
end

Public Instance Methods

create_for(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 47
def create_for(instance)
  foreign_class.create(instance_create_attributes(instance))
end
foreign_class() click to toggle source
# File lib/selfish_associations/associations/association.rb, line 29
def foreign_class
  @foreign_class ||= self.class.const_get(@foreign_class_name)
end
initialize_for(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 43
def initialize_for(instance)
  foreign_class.new(instance_create_attributes(instance))
end
inspect() click to toggle source
# File lib/selfish_associations/associations/association.rb, line 25
def inspect
  "#<#{self.class}:#{self.object_id} @name=#{@name} @model=#{@model} @foreign_class=#{foreign_class} @foreign_key=#{@foreign_key}>"
end
join() click to toggle source
# File lib/selfish_associations/associations/association.rb, line 33
def join
  conditions = arelize_conditions(relation_reader.conditions_for_find)
  arel_join = @model.arel_table.join(foreign_class.arel_table).on(conditions).join_sources
  @model.joins(joins_for_find).joins(arel_join).merge(foreign_class.all)
end
matches_for(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 39
def matches_for(instance)
  foreign_class.where(instance_find_conditions(instance))
end

Private Instance Methods

add_scope(scope) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 53
def add_scope(scope)
  @scopes << scope
end
apply_scopes(reader) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 57
def apply_scopes(reader)
  @scopes.each{|scope| reader.read(scope) }
  return reader
end
arelize_conditions(conditions) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 62
def arelize_conditions(conditions)
  conditions.map do |foreign_field, node|
    foreign_class.arel_table[foreign_field].eq(node)
  end.reduce(&:and)
end
foreign_key_scope() click to toggle source
# File lib/selfish_associations/associations/association.rb, line 120
def foreign_key_scope
  # TODO: pass foreign_key in rather than using the closure
  foreign_key = @foreign_key
  return ->(obj){ where foreign_key => obj.id }
end
instance_create_attributes(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 76
def instance_create_attributes(instance)
  read_instance_create_attributes(instance)
end
instance_find_conditions(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 68
def instance_find_conditions(instance)
  read_instance_find_conditions(instance)
  # TODO: dynamically determine if we should use lookup_instance_find_conditions instead
  # cannot use if the scope constains non-associations
  # should not use if all associations are preloaded on instance
  # cannot use if instance contains unpersisted changes
end
instance_reader(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 84
def instance_reader(instance)
  apply_scopes(ScopeReaders::Instance.new(instance))
end
instantiate_conditions(instance, conditions) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 104
def instantiate_conditions(instance, conditions)
  arel_conditions, static_conditions = conditions.partition{|field, value| value.is_a?(::Arel::Attribute)}.map(&:to_h)
  selector = arel_conditions.map{|field, arel| arel.as(field.to_s)}
  instance = @model.joins(joins_for_find).select(selector).find_by(id: instance.id)
  arel_conditions.keys.each{|k| static_conditions[k] = instance[k]}
  return static_conditions
end
joins_for_create() click to toggle source
# File lib/selfish_associations/associations/association.rb, line 116
def joins_for_create
  relation_reader.joins_for_create
end
joins_for_find() click to toggle source
# File lib/selfish_associations/associations/association.rb, line 112
def joins_for_find
  relation_reader.joins_for_find
end
lookup_instance_create_attributes(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 100
def lookup_instance_create_attributes(instance)
  instantiate_conditions(instance, relation_reader.attributes_for_create)
end
lookup_instance_find_conditions(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 96
def lookup_instance_find_conditions(instance)
  instantiate_conditions(instance, relation_reader.conditions_for_find)
end
read_instance_create_attributes(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 92
def read_instance_create_attributes(instance)
  instance_reader(instance).attributes_for_create
end
read_instance_find_conditions(instance) click to toggle source
# File lib/selfish_associations/associations/association.rb, line 88
def read_instance_find_conditions(instance)
  instance_reader(instance).attributes_for_find
end
relation_reader() click to toggle source
# File lib/selfish_associations/associations/association.rb, line 80
def relation_reader
  @relation_reader ||= apply_scopes(SelfishAssociations::ScopeReaders::Relation.new(@model))
end
validate() click to toggle source
# File lib/selfish_associations/associations/association.rb, line 126
def validate
  @scopes.each do |scope|
    scope.is_a?(Proc) or raise SelfishAssociations::SelfishException, "Scope must be a Proc"
    scope.arity == 0 || scope.arity == 1 or raise SelfishAssociations::SelfishException, "Scope must have arity of 0 or 1"
  end
  @model.is_a?(Class) && @model < ActiveRecord::Base or raise SelfishAssociations::SelfishException, "Tried to define a SelfishAssociation for an invalid object (#{@model})"
end