Class: ThinkingSphinx::Association

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

Overview

Association tracks a specific reflection and join to reference data that isn’t in the base model. Very much an internal class for Thinking Sphinx - perhaps because I feel it’s not as strong (or simple) as most of the rest.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent, reflection) ⇒ Association

Create a new association by passing in the parent association, and the corresponding reflection instance. If there is no parent, pass in nil.

top   = Association.new nil, top_reflection
child = Association.new top, child_reflection


15
16
17
18
# File 'lib/thinking_sphinx/association.rb', line 15

def initialize(parent, reflection)
  @parent, @reflection = parent, reflection
  @children = {}
end

Instance Attribute Details

#joinObject

Returns the value of attribute join.



7
8
9
# File 'lib/thinking_sphinx/association.rb', line 7

def join
  @join
end

#parentObject

Returns the value of attribute parent.



7
8
9
# File 'lib/thinking_sphinx/association.rb', line 7

def parent
  @parent
end

#reflectionObject

Returns the value of attribute reflection.



7
8
9
# File 'lib/thinking_sphinx/association.rb', line 7

def reflection
  @reflection
end

Class Method Details

.children(klass, assoc, parent = nil) ⇒ Object

Get the children associations for a given class, association name and parent association. Much like the instance method of the same name, it will return an empty array if no associations have the name, and only have multiple association instances if the underlying relationship is polymorphic.

Association.children(User, :pages, user_association)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/thinking_sphinx/association.rb', line 40

def self.children(klass, assoc, parent=nil)
  ref = klass.reflect_on_association(assoc)
  
  return [] if ref.nil?
  return [Association.new(parent, ref)] unless ref.options[:polymorphic]
  
  # association is polymorphic - create associations for each
  # non-polymorphic reflection.
  polymorphic_classes(ref).collect { |klass|
    Association.new parent, ::ActiveRecord::Reflection::AssociationReflection.new(
      ref.macro,
      "#{ref.name}_#{klass.name}".to_sym,
      casted_options(klass, ref),
      ref.active_record
    )
  }
end

Instance Method Details

#ancestorsObject

Returns an array of all the associations that lead to this one - starting with the top level all the way to the current association object.



94
95
96
# File 'lib/thinking_sphinx/association.rb', line 94

def ancestors
  (parent ? parent.ancestors : []) << self
end

#children(assoc) ⇒ Object

Get the children associations for a given association name. The only time that there’ll actually be more than one association is when the relationship is polymorphic. To keep things simple though, it will always be an Array that gets returned (an empty one if no matches).

# where pages is an association on the class tied to the reflection.
association.children(:pages)


28
29
30
# File 'lib/thinking_sphinx/association.rb', line 28

def children(assoc)
  @children[assoc] ||= Association.children(@reflection.klass, assoc, self)
end

#has_column?(column) ⇒ Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/thinking_sphinx/association.rb', line 98

def has_column?(column)
  @reflection.klass.column_names.include?(column.to_s)
end

#is_many?Boolean

Returns true if the association - or a parent - is a has_many or has_and_belongs_to_many.

Returns:

  • (Boolean)


82
83
84
85
86
87
88
89
# File 'lib/thinking_sphinx/association.rb', line 82

def is_many?
  case @reflection.macro
  when :has_many, :has_and_belongs_to_many
    true
  else
    @parent ? @parent.is_many? : false
  end
end

#join_to(base_join) ⇒ Object

Link up the join for this model from a base join - and set parent associations’ joins recursively.



61
62
63
64
65
66
67
# File 'lib/thinking_sphinx/association.rb', line 61

def join_to(base_join)
  parent.join_to(base_join) if parent && parent.join.nil?
  
  @join ||= ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.new(
    @reflection, base_join, parent ? parent.join : base_join.joins.first
  )
end

#primary_key_from_reflectionObject



102
103
104
105
106
107
108
109
110
111
# File 'lib/thinking_sphinx/association.rb', line 102

def primary_key_from_reflection
  if @reflection.options[:through]
    @reflection.source_reflection.options[:foreign_key] ||
    @reflection.source_reflection.primary_key_name
  elsif @reflection.macro == :has_and_belongs_to_many
    @reflection.association_foreign_key
  else
    nil
  end
end

#tableObject



113
114
115
116
117
118
119
120
# File 'lib/thinking_sphinx/association.rb', line 113

def table
  if @reflection.options[:through] ||
    @reflection.macro == :has_and_belongs_to_many
    @join.aliased_join_table_name
  else
    @join.aliased_table_name
  end
end

#to_sqlObject

Returns the association’s join SQL statements - and it replaces

::ts_join_alias

with the aliased table name so the generated reflection

join conditions avoid column name collisions.



73
74
75
76
77
# File 'lib/thinking_sphinx/association.rb', line 73

def to_sql
  @join.association_join.gsub(/::ts_join_alias::/,
    "#{@reflection.klass.connection.quote_table_name(@join.parent.aliased_table_name)}"
  )
end