summaryrefslogtreecommitdiff
path: root/vendor/plugins/thinking-sphinx/lib/thinking_sphinx/association.rb
diff options
context:
space:
mode:
authorUser <hukl@cccms.ccc.de>2011-02-10 14:23:36 +0100
committerUser <hukl@cccms.ccc.de>2011-02-10 14:23:36 +0100
commit384b187e9e067ddf2bb4d5fad0c2deaf96f69c89 (patch)
treecf743f377d3e2e28a31ae0359d95f37beba82cc3 /vendor/plugins/thinking-sphinx/lib/thinking_sphinx/association.rb
parent3d0de09cf94cee6233b36a7f5ce20d5059854acc (diff)
parentcec2b1e2881db0000b2a09029154bea0fc62ade3 (diff)
Merge branch 'master' of ssh://svn.medienhaus.udk-berlin.de/usr/local/git/cccms
Diffstat (limited to 'vendor/plugins/thinking-sphinx/lib/thinking_sphinx/association.rb')
-rw-r--r--vendor/plugins/thinking-sphinx/lib/thinking_sphinx/association.rb161
1 files changed, 0 insertions, 161 deletions
diff --git a/vendor/plugins/thinking-sphinx/lib/thinking_sphinx/association.rb b/vendor/plugins/thinking-sphinx/lib/thinking_sphinx/association.rb
deleted file mode 100644
index b057035..0000000
--- a/vendor/plugins/thinking-sphinx/lib/thinking_sphinx/association.rb
+++ /dev/null
@@ -1,161 +0,0 @@
1module ThinkingSphinx
2 # Association tracks a specific reflection and join to reference data that
3 # isn't in the base model. Very much an internal class for Thinking Sphinx -
4 # perhaps because I feel it's not as strong (or simple) as most of the rest.
5 #
6 class Association
7 attr_accessor :parent, :reflection, :join
8
9 # Create a new association by passing in the parent association, and the
10 # corresponding reflection instance. If there is no parent, pass in nil.
11 #
12 # top = Association.new nil, top_reflection
13 # child = Association.new top, child_reflection
14 #
15 def initialize(parent, reflection)
16 @parent, @reflection = parent, reflection
17 @children = {}
18 end
19
20 # Get the children associations for a given association name. The only time
21 # that there'll actually be more than one association is when the
22 # relationship is polymorphic. To keep things simple though, it will always
23 # be an Array that gets returned (an empty one if no matches).
24 #
25 # # where pages is an association on the class tied to the reflection.
26 # association.children(:pages)
27 #
28 def children(assoc)
29 @children[assoc] ||= Association.children(@reflection.klass, assoc, self)
30 end
31
32 # Get the children associations for a given class, association name and
33 # parent association. Much like the instance method of the same name, it
34 # will return an empty array if no associations have the name, and only
35 # have multiple association instances if the underlying relationship is
36 # polymorphic.
37 #
38 # Association.children(User, :pages, user_association)
39 #
40 def self.children(klass, assoc, parent=nil)
41 ref = klass.reflect_on_association(assoc)
42
43 return [] if ref.nil?
44 return [Association.new(parent, ref)] unless ref.options[:polymorphic]
45
46 # association is polymorphic - create associations for each
47 # non-polymorphic reflection.
48 polymorphic_classes(ref).collect { |klass|
49 Association.new parent, ::ActiveRecord::Reflection::AssociationReflection.new(
50 ref.macro,
51 "#{ref.name}_#{klass.name}".to_sym,
52 casted_options(klass, ref),
53 ref.active_record
54 )
55 }
56 end
57
58 # Link up the join for this model from a base join - and set parent
59 # associations' joins recursively.
60 #
61 def join_to(base_join)
62 parent.join_to(base_join) if parent && parent.join.nil?
63
64 @join ||= ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation.new(
65 @reflection, base_join, parent ? parent.join : base_join.joins.first
66 )
67 end
68
69 # Returns the association's join SQL statements - and it replaces
70 # ::ts_join_alias:: with the aliased table name so the generated reflection
71 # join conditions avoid column name collisions.
72 #
73 def to_sql
74 @join.association_join.gsub(/::ts_join_alias::/,
75 "#{@reflection.klass.connection.quote_table_name(@join.parent.aliased_table_name)}"
76 )
77 end
78
79 # Returns true if the association - or a parent - is a has_many or
80 # has_and_belongs_to_many.
81 #
82 def is_many?
83 case @reflection.macro
84 when :has_many, :has_and_belongs_to_many
85 true
86 else
87 @parent ? @parent.is_many? : false
88 end
89 end
90
91 # Returns an array of all the associations that lead to this one - starting
92 # with the top level all the way to the current association object.
93 #
94 def ancestors
95 (parent ? parent.ancestors : []) << self
96 end
97
98 def has_column?(column)
99 @reflection.klass.column_names.include?(column.to_s)
100 end
101
102 def primary_key_from_reflection
103 if @reflection.options[:through]
104 @reflection.source_reflection.options[:foreign_key] ||
105 @reflection.source_reflection.primary_key_name
106 else
107 nil
108 end
109 end
110
111 def table
112 if @reflection.options[:through]
113 @join.aliased_join_table_name
114 else
115 @join.aliased_table_name
116 end
117 end
118
119 private
120
121 # Returns all the objects that could be currently instantiated from a
122 # polymorphic association. This is pretty damn fast if there's an index on
123 # the foreign type column - but if there isn't, it can take a while if you
124 # have a lot of data.
125 #
126 def self.polymorphic_classes(ref)
127 ref.active_record.connection.select_all(
128 "SELECT DISTINCT #{ref.options[:foreign_type]} " +
129 "FROM #{ref.active_record.table_name} " +
130 "WHERE #{ref.options[:foreign_type]} IS NOT NULL"
131 ).collect { |row|
132 row[ref.options[:foreign_type]].constantize
133 }
134 end
135
136 # Returns a new set of options for an association that mimics an existing
137 # polymorphic relationship for a specific class. It adds a condition to
138 # filter by the appropriate object.
139 #
140 def self.casted_options(klass, ref)
141 options = ref.options.clone
142 options[:polymorphic] = nil
143 options[:class_name] = klass.name
144 options[:foreign_key] ||= "#{ref.name}_id"
145
146 quoted_foreign_type = klass.connection.quote_column_name ref.options[:foreign_type]
147 case options[:conditions]
148 when nil
149 options[:conditions] = "::ts_join_alias::.#{quoted_foreign_type} = '#{klass.name}'"
150 when Array
151 options[:conditions] << "::ts_join_alias::.#{quoted_foreign_type} = '#{klass.name}'"
152 when Hash
153 options[:conditions].merge!(ref.options[:foreign_type] => klass.name)
154 else
155 options[:conditions] << " AND ::ts_join_alias::.#{quoted_foreign_type} = '#{klass.name}'"
156 end
157
158 options
159 end
160 end
161end \ No newline at end of file