Class: ActiveRecord::Associations::Association

Inherits:
Object
  • Object
show all
Defined in:
lib/ocean-dynamo/active_record_stuff/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

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
29
30
31
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 24

def initialize(owner, reflection)
  reflection.check_validity!

  @owner, @reflection = owner, reflection

  reset
  reset_scope
end

Instance Attribute Details

#ownerObject (readonly)

:nodoc: all



20
21
22
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 20

def owner
  @owner
end

#reflectionObject (readonly)

:nodoc: all



20
21
22
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 20

def reflection
  @reflection
end

#targetObject

:nodoc: all



20
21
22
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 20

def target
  @target
end

Instance Method Details

#aliased_table_nameObject

Returns the name of the table of the associated class:

post.comments.aliased_table_name # => "comments"


37
38
39
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 37

def aliased_table_name
  klass.table_name
end

#association_scopeObject

The scope for this association.

Note that the association_scope is merged into the target_scope only when the scope method is called. This is because at that point the call may be surrounded by scope.scoping { … } or with_scope { … } etc, which affects the scope which actually gets built.



98
99
100
101
102
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 98

def association_scope
  if klass
    @association_scope ||= AssociationScope.new(self).scope
  end
end

#interpolate(sql, record = nil) ⇒ Object



147
148
149
150
151
152
153
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 147

def interpolate(sql, record = nil)
  if sql.respond_to?(:to_proc)
    owner.instance_exec(record, &sql)
  else
    sql
  end
end

#klassObject

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



118
119
120
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 118

def klass
  reflection.klass
end

#load_targetObject

Loads the target if needed and returns it.

This method is abstract in the sense that it relies on find_target, which is expected to be provided by descendants.

If the target is already loaded it is just returned. Thus, you can call load_target unconditionally to get the target.

ActiveRecord::RecordNotFound is rescued within the method, and it is not reraised. The proxy is reset and nil is the return value.



138
139
140
141
142
143
144
145
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 138

def load_target
  @target = find_target if (@stale_state && stale_target?) || find_target?

  loaded! unless loaded?
  target
rescue ActiveRecord::RecordNotFound
  reset
end

#loaded!Object

Asserts the target has been loaded setting the loaded flag to true.



62
63
64
65
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 62

def loaded!
  @loaded      = true
  @stale_state = stale_state
end

#loaded?Boolean

Has the target been already loaded?

Returns:

  • (Boolean)


57
58
59
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 57

def loaded?
  @loaded
end

#marshal_dumpObject

We can’t dump @reflection since it contains the scope proc



156
157
158
159
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 156

def marshal_dump
  ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
  [@reflection.name, ivars]
end

#marshal_load(data) ⇒ Object



161
162
163
164
165
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 161

def marshal_load(data)
  reflection_name, ivars = data
  ivars.each { |name, val| instance_variable_set(name, val) }
  @reflection = @owner.class.reflect_on_association(reflection_name)
end

#reloadObject

Reloads the target and returns self on success.



49
50
51
52
53
54
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 49

def reload
  reset
  reset_scope
  load_target
  self unless target.nil?
end

#resetObject

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



42
43
44
45
46
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 42

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

#reset_scopeObject



104
105
106
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 104

def reset_scope
  @association_scope = nil
end

#scopeObject



83
84
85
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 83

def scope
  target_scope.merge(association_scope)
end

#scopedObject



87
88
89
90
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 87

def scoped
  ActiveSupport::Deprecation.warn "#scoped is deprecated. use #scope instead."
  scope
end

#set_inverse_instance(record) ⇒ Object

Set the inverse association, if possible



109
110
111
112
113
114
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 109

def set_inverse_instance(record)
  if record && invertible_for?(record)
    inverse = record.association(inverse_reflection_for(record).name)
    inverse.target = owner
  end
end

#stale_target?Boolean

The target is stale if the target no longer points to the record(s) that the relevant foreign_key(s) refers to. If stale, the association accessor method on the owner will reload the target. It’s up to subclasses to implement the stale_state method if relevant.

Note that if the target has not been loaded, it is not considered stale.

Returns:

  • (Boolean)


73
74
75
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 73

def stale_target?
  loaded? && @stale_state != stale_state
end

#target_scopeObject

Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the through association’s scope)



124
125
126
# File 'lib/ocean-dynamo/active_record_stuff/association.rb', line 124

def target_scope
  klass.all
end