Class: ActiveNode::Associations::Association

Inherits:
Object
  • Object
show all
Defined in:
lib/active_node/associations/association.rb

Overview

Active Record Associations

This is the root class of all associations (‘+ Foo’ signifies an included module Foo):

Association
  SingularAssociation
    HasOneAssociation
      HasOneThroughAssociation + ThroughAssociation
    BelongsToAssociation
      BelongsToPolymorphicAssociation
  CollectionAssociation
    HasAndBelongsToManyAssociation
    HasManyAssociation
      HasManyThroughAssociation + ThroughAssociation

Direct Known Subclasses

CollectionAssociation, SingularAssociation

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(owner, reflection) ⇒ Association

Returns a new instance of Association.



24
25
26
27
28
# File 'lib/active_node/associations/association.rb', line 24

def initialize(owner, reflection)
  @owner, @reflection = owner, reflection

  reset
end

Instance Attribute Details

#ownerObject (readonly)

:nodoc:



20
21
22
# File 'lib/active_node/associations/association.rb', line 20

def owner
  @owner
end

#reflectionObject (readonly)

:nodoc:



20
21
22
# File 'lib/active_node/associations/association.rb', line 20

def reflection
  @reflection
end

#rel_targetObject (readonly)

:nodoc:



20
21
22
# File 'lib/active_node/associations/association.rb', line 20

def rel_target
  @rel_target
end

#targetObject (readonly)

:nodoc:



20
21
22
# File 'lib/active_node/associations/association.rb', line 20

def target
  @target
end

Instance Method Details

#ids_readerObject

Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items



80
81
82
83
# File 'lib/active_node/associations/association.rb', line 80

def ids_reader
  reader
  @target.map(&:id)
end

#ids_writer(ids) ⇒ Object

Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items



70
71
72
73
# File 'lib/active_node/associations/association.rb', line 70

def ids_writer(ids)
  @rel_target = nil
  super_writer klass.find(ids.reject(&:blank?))
end

#klassObject

Returns the class of the target. belongs_to polymorphic overrides this to look at the polymorphic_type field on the owner.



39
40
41
# File 'lib/active_node/associations/association.rb', line 39

def klass
  reflection.klass
end

#load_ids(records) ⇒ Object



57
58
59
# File 'lib/active_node/associations/association.rb', line 57

def load_ids(records)
  records.map {|r| ActiveNode::Base === r ? r : reflection.klass.find(r)}
end

#reader(*args) ⇒ Object



75
76
77
# File 'lib/active_node/associations/association.rb', line 75

def reader(*args)
  @target ||= rels_reader(*args).map &:other
end

#rel(*associations) ⇒ Object



43
44
45
46
# File 'lib/active_node/associations/association.rb', line 43

def rel(*associations)
  @loaded = true
  owner.includes!(reflection.name => associations)
end

#rels_loader(rels) ⇒ Object



96
97
98
99
100
# File 'lib/active_node/associations/association.rb', line 96

def rels_loader(rels)
  @target = nil
  @rel_target = rels
  @loaded = true
end

#rels_reader(*args) ⇒ Object



86
87
88
89
# File 'lib/active_node/associations/association.rb', line 86

def rels_reader(*args)
  rel(*args) unless @loaded
  @rel_target ||= []
end

#rels_writer(rels) ⇒ Object



91
92
93
94
# File 'lib/active_node/associations/association.rb', line 91

def rels_writer(rels)
  @dirty = true
  rels_loader(rels)
end

#resetObject

Resets the loaded flag to false and sets the target to nil.



31
32
33
34
35
# File 'lib/active_node/associations/association.rb', line 31

def reset
  @loaded = false
  @target = nil
  @stale_state = nil
end

#save(fresh = false) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/active_node/associations/association.rb', line 102

def save(fresh=false)
  #return unless @dirty
  #delete all relations missing in new target
  original_rels = fresh ? [] : owner.class.includes(reflection.name).build(owner.id).first.association(reflection.name).rels_reader
  original_rels.each do |r|
    unless ids_reader.include? r.other.id
      Neo.db.delete_relationship(r.id)
      original_rels.delete(r)
    end
  end

  #add relations missing in old target
  #if no rel_target proceed as before + set rel_target from db
  #if rel_target exists update persisted records and insert new records
  if @rel_target
    @rel_target.each { |r| r.save(self) }
  else
    @target.map do |n|
      original_rels.detect { |r| r.other.id == n.id }.tap { |o_r| o_r.try :other=, n } ||
          ActiveNode::Relationship.create!(n, self)
    end
  end
end

#validate_type(records) ⇒ Object



61
62
63
64
65
# File 'lib/active_node/associations/association.rb', line 61

def validate_type(records)
  unless records.all? { |r| r.is_a?(reflection.klass) }
    raise ArgumentError, "#{reflection.name} can only accept object(s) of class #{reflection.klass}"
  end
end

#writer(records) ⇒ Object Also known as: super_writer

Implements the writer method, e.g. foo.items= for Foo.has_many :items



49
50
51
52
53
54
55
# File 'lib/active_node/associations/association.rb', line 49

def writer(records)
  records = load_ids(records)
  validate_type(records)
  @dirty = true
  @rel_target = nil
  @target = records
end