activerecord 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (181) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +2102 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +35 -44
  5. data/examples/performance.rb +110 -100
  6. data/lib/active_record/aggregations.rb +59 -75
  7. data/lib/active_record/associations/alias_tracker.rb +76 -0
  8. data/lib/active_record/associations/association.rb +248 -0
  9. data/lib/active_record/associations/association_scope.rb +135 -0
  10. data/lib/active_record/associations/belongs_to_association.rb +60 -59
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -59
  12. data/lib/active_record/associations/builder/association.rb +108 -0
  13. data/lib/active_record/associations/builder/belongs_to.rb +98 -0
  14. data/lib/active_record/associations/builder/collection_association.rb +89 -0
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
  16. data/lib/active_record/associations/builder/has_many.rb +15 -0
  17. data/lib/active_record/associations/builder/has_one.rb +25 -0
  18. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  19. data/lib/active_record/associations/collection_association.rb +608 -0
  20. data/lib/active_record/associations/collection_proxy.rb +986 -0
  21. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +40 -112
  22. data/lib/active_record/associations/has_many_association.rb +83 -76
  23. data/lib/active_record/associations/has_many_through_association.rb +147 -66
  24. data/lib/active_record/associations/has_one_association.rb +67 -108
  25. data/lib/active_record/associations/has_one_through_association.rb +21 -25
  26. data/lib/active_record/associations/join_dependency/join_association.rb +174 -0
  27. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  28. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  29. data/lib/active_record/associations/join_dependency.rb +235 -0
  30. data/lib/active_record/associations/join_helper.rb +45 -0
  31. data/lib/active_record/associations/preloader/association.rb +121 -0
  32. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  33. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  35. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  36. data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
  37. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  38. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  39. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  40. data/lib/active_record/associations/preloader/through_association.rb +63 -0
  41. data/lib/active_record/associations/preloader.rb +178 -0
  42. data/lib/active_record/associations/singular_association.rb +64 -0
  43. data/lib/active_record/associations/through_association.rb +87 -0
  44. data/lib/active_record/associations.rb +512 -1224
  45. data/lib/active_record/attribute_assignment.rb +201 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +49 -12
  47. data/lib/active_record/attribute_methods/dirty.rb +51 -28
  48. data/lib/active_record/attribute_methods/primary_key.rb +94 -22
  49. data/lib/active_record/attribute_methods/query.rb +5 -4
  50. data/lib/active_record/attribute_methods/read.rb +63 -72
  51. data/lib/active_record/attribute_methods/serialization.rb +162 -0
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -41
  53. data/lib/active_record/attribute_methods/write.rb +39 -13
  54. data/lib/active_record/attribute_methods.rb +362 -29
  55. data/lib/active_record/autosave_association.rb +132 -75
  56. data/lib/active_record/base.rb +83 -1627
  57. data/lib/active_record/callbacks.rb +69 -47
  58. data/lib/active_record/coders/yaml_column.rb +38 -0
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +411 -138
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +21 -11
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -173
  62. data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -22
  63. data/lib/active_record/connection_adapters/abstract/quoting.rb +82 -25
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +176 -414
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +562 -232
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +281 -53
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
  70. data/lib/active_record/connection_adapters/column.rb +318 -0
  71. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
  73. data/lib/active_record/connection_adapters/mysql_adapter.rb +365 -450
  74. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  75. data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
  76. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  80. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
  81. data/lib/active_record/connection_adapters/postgresql_adapter.rb +672 -752
  82. data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
  83. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +588 -17
  84. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  85. data/lib/active_record/connection_handling.rb +98 -0
  86. data/lib/active_record/core.rb +463 -0
  87. data/lib/active_record/counter_cache.rb +108 -101
  88. data/lib/active_record/dynamic_matchers.rb +131 -0
  89. data/lib/active_record/errors.rb +54 -13
  90. data/lib/active_record/explain.rb +38 -0
  91. data/lib/active_record/explain_registry.rb +30 -0
  92. data/lib/active_record/explain_subscriber.rb +29 -0
  93. data/lib/active_record/fixture_set/file.rb +55 -0
  94. data/lib/active_record/fixtures.rb +703 -785
  95. data/lib/active_record/inheritance.rb +200 -0
  96. data/lib/active_record/integration.rb +60 -0
  97. data/lib/active_record/locale/en.yml +8 -1
  98. data/lib/active_record/locking/optimistic.rb +69 -60
  99. data/lib/active_record/locking/pessimistic.rb +34 -12
  100. data/lib/active_record/log_subscriber.rb +40 -6
  101. data/lib/active_record/migration/command_recorder.rb +164 -0
  102. data/lib/active_record/migration/join_table.rb +15 -0
  103. data/lib/active_record/migration.rb +614 -216
  104. data/lib/active_record/model_schema.rb +345 -0
  105. data/lib/active_record/nested_attributes.rb +248 -119
  106. data/lib/active_record/null_relation.rb +65 -0
  107. data/lib/active_record/persistence.rb +275 -57
  108. data/lib/active_record/query_cache.rb +29 -9
  109. data/lib/active_record/querying.rb +62 -0
  110. data/lib/active_record/railtie.rb +135 -21
  111. data/lib/active_record/railties/console_sandbox.rb +5 -0
  112. data/lib/active_record/railties/controller_runtime.rb +17 -5
  113. data/lib/active_record/railties/databases.rake +249 -359
  114. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  115. data/lib/active_record/readonly_attributes.rb +30 -0
  116. data/lib/active_record/reflection.rb +283 -103
  117. data/lib/active_record/relation/batches.rb +38 -34
  118. data/lib/active_record/relation/calculations.rb +252 -139
  119. data/lib/active_record/relation/delegation.rb +125 -0
  120. data/lib/active_record/relation/finder_methods.rb +182 -188
  121. data/lib/active_record/relation/merger.rb +161 -0
  122. data/lib/active_record/relation/predicate_builder.rb +86 -21
  123. data/lib/active_record/relation/query_methods.rb +917 -134
  124. data/lib/active_record/relation/spawn_methods.rb +53 -92
  125. data/lib/active_record/relation.rb +405 -143
  126. data/lib/active_record/result.rb +67 -0
  127. data/lib/active_record/runtime_registry.rb +17 -0
  128. data/lib/active_record/sanitization.rb +168 -0
  129. data/lib/active_record/schema.rb +20 -14
  130. data/lib/active_record/schema_dumper.rb +55 -46
  131. data/lib/active_record/schema_migration.rb +39 -0
  132. data/lib/active_record/scoping/default.rb +146 -0
  133. data/lib/active_record/scoping/named.rb +175 -0
  134. data/lib/active_record/scoping.rb +82 -0
  135. data/lib/active_record/serialization.rb +8 -46
  136. data/lib/active_record/serializers/xml_serializer.rb +21 -68
  137. data/lib/active_record/statement_cache.rb +26 -0
  138. data/lib/active_record/store.rb +156 -0
  139. data/lib/active_record/tasks/database_tasks.rb +203 -0
  140. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  141. data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
  142. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  143. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  144. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  145. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  146. data/lib/active_record/test_case.rb +57 -28
  147. data/lib/active_record/timestamp.rb +49 -18
  148. data/lib/active_record/transactions.rb +106 -63
  149. data/lib/active_record/translation.rb +22 -0
  150. data/lib/active_record/validations/associated.rb +25 -24
  151. data/lib/active_record/validations/presence.rb +65 -0
  152. data/lib/active_record/validations/uniqueness.rb +123 -83
  153. data/lib/active_record/validations.rb +29 -29
  154. data/lib/active_record/version.rb +7 -5
  155. data/lib/active_record.rb +83 -34
  156. data/lib/rails/generators/active_record/migration/migration_generator.rb +46 -9
  157. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
  158. data/lib/rails/generators/active_record/migration/templates/migration.rb +30 -8
  159. data/lib/rails/generators/active_record/model/model_generator.rb +15 -5
  160. data/lib/rails/generators/active_record/model/templates/model.rb +7 -2
  161. data/lib/rails/generators/active_record/model/templates/module.rb +3 -1
  162. data/lib/rails/generators/active_record.rb +4 -8
  163. metadata +163 -121
  164. data/CHANGELOG +0 -6023
  165. data/examples/associations.png +0 -0
  166. data/lib/active_record/association_preload.rb +0 -403
  167. data/lib/active_record/associations/association_collection.rb +0 -562
  168. data/lib/active_record/associations/association_proxy.rb +0 -295
  169. data/lib/active_record/associations/through_association_scope.rb +0 -154
  170. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -113
  171. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -401
  172. data/lib/active_record/dynamic_finder_match.rb +0 -53
  173. data/lib/active_record/dynamic_scope_match.rb +0 -32
  174. data/lib/active_record/named_scope.rb +0 -138
  175. data/lib/active_record/observer.rb +0 -140
  176. data/lib/active_record/session_store.rb +0 -340
  177. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -16
  178. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  179. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -2
  180. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -24
  181. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -1,295 +0,0 @@
1
- require 'active_support/core_ext/array/wrap'
2
-
3
- module ActiveRecord
4
- module Associations
5
- # = Active Record Associations
6
- #
7
- # This is the root class of all association proxies:
8
- #
9
- # AssociationProxy
10
- # BelongsToAssociation
11
- # HasOneAssociation
12
- # BelongsToPolymorphicAssociation
13
- # AssociationCollection
14
- # HasAndBelongsToManyAssociation
15
- # HasManyAssociation
16
- # HasManyThroughAssociation
17
- # HasOneThroughAssociation
18
- #
19
- # Association proxies in Active Record are middlemen between the object that
20
- # holds the association, known as the <tt>@owner</tt>, and the actual associated
21
- # object, known as the <tt>@target</tt>. The kind of association any proxy is
22
- # about is available in <tt>@reflection</tt>. That's an instance of the class
23
- # ActiveRecord::Reflection::AssociationReflection.
24
- #
25
- # For example, given
26
- #
27
- # class Blog < ActiveRecord::Base
28
- # has_many :posts
29
- # end
30
- #
31
- # blog = Blog.find(:first)
32
- #
33
- # the association proxy in <tt>blog.posts</tt> has the object in +blog+ as
34
- # <tt>@owner</tt>, the collection of its posts as <tt>@target</tt>, and
35
- # the <tt>@reflection</tt> object represents a <tt>:has_many</tt> macro.
36
- #
37
- # This class has most of the basic instance methods removed, and delegates
38
- # unknown methods to <tt>@target</tt> via <tt>method_missing</tt>. As a
39
- # corner case, it even removes the +class+ method and that's why you get
40
- #
41
- # blog.posts.class # => Array
42
- #
43
- # though the object behind <tt>blog.posts</tt> is not an Array, but an
44
- # ActiveRecord::Associations::HasManyAssociation.
45
- #
46
- # The <tt>@target</tt> object is not \loaded until needed. For example,
47
- #
48
- # blog.posts.count
49
- #
50
- # is computed directly through SQL and does not trigger by itself the
51
- # instantiation of the actual post records.
52
- class AssociationProxy #:nodoc:
53
- alias_method :proxy_respond_to?, :respond_to?
54
- alias_method :proxy_extend, :extend
55
- delegate :to_param, :to => :proxy_target
56
- instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|proxy_/ }
57
-
58
- def initialize(owner, reflection)
59
- @owner, @reflection = owner, reflection
60
- @updated = false
61
- reflection.check_validity!
62
- Array.wrap(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
63
- reset
64
- end
65
-
66
- # Returns the owner of the proxy.
67
- def proxy_owner
68
- @owner
69
- end
70
-
71
- # Returns the reflection object that represents the association handled
72
- # by the proxy.
73
- def proxy_reflection
74
- @reflection
75
- end
76
-
77
- # Returns the \target of the proxy, same as +target+.
78
- def proxy_target
79
- @target
80
- end
81
-
82
- # Does the proxy or its \target respond to +symbol+?
83
- def respond_to?(*args)
84
- proxy_respond_to?(*args) || (load_target && @target.respond_to?(*args))
85
- end
86
-
87
- # Forwards <tt>===</tt> explicitly to the \target because the instance method
88
- # removal above doesn't catch it. Loads the \target if needed.
89
- def ===(other)
90
- load_target
91
- other === @target
92
- end
93
-
94
- # Returns the name of the table of the related class:
95
- #
96
- # post.comments.aliased_table_name # => "comments"
97
- #
98
- def aliased_table_name
99
- @reflection.klass.table_name
100
- end
101
-
102
- # Returns the SQL string that corresponds to the <tt>:conditions</tt>
103
- # option of the macro, if given, or +nil+ otherwise.
104
- def conditions
105
- @conditions ||= interpolate_sql(@reflection.sanitized_conditions) if @reflection.sanitized_conditions
106
- end
107
- alias :sql_conditions :conditions
108
-
109
- # Resets the \loaded flag to +false+ and sets the \target to +nil+.
110
- def reset
111
- @loaded = false
112
- @target = nil
113
- end
114
-
115
- # Reloads the \target and returns +self+ on success.
116
- def reload
117
- reset
118
- load_target
119
- self unless @target.nil?
120
- end
121
-
122
- # Has the \target been already \loaded?
123
- def loaded?
124
- @loaded
125
- end
126
-
127
- # Asserts the \target has been loaded setting the \loaded flag to +true+.
128
- def loaded
129
- @loaded = true
130
- end
131
-
132
- # Returns the target of this proxy, same as +proxy_target+.
133
- def target
134
- @target
135
- end
136
-
137
- # Sets the target of this proxy to <tt>\target</tt>, and the \loaded flag to +true+.
138
- def target=(target)
139
- @target = target
140
- loaded
141
- end
142
-
143
- # Forwards the call to the target. Loads the \target if needed.
144
- def inspect
145
- load_target
146
- @target.inspect
147
- end
148
-
149
- def send(method, *args)
150
- if proxy_respond_to?(method)
151
- super
152
- else
153
- load_target
154
- @target.send(method, *args)
155
- end
156
- end
157
-
158
- protected
159
- # Does the association have a <tt>:dependent</tt> option?
160
- def dependent?
161
- @reflection.options[:dependent]
162
- end
163
-
164
- def interpolate_sql(sql, record = nil)
165
- @owner.send(:interpolate_sql, sql, record)
166
- end
167
-
168
- # Forwards the call to the reflection class.
169
- def sanitize_sql(sql, table_name = @reflection.klass.table_name)
170
- @reflection.klass.send(:sanitize_sql, sql, table_name)
171
- end
172
-
173
- # Assigns the ID of the owner to the corresponding foreign key in +record+.
174
- # If the association is polymorphic the type of the owner is also set.
175
- def set_belongs_to_association_for(record)
176
- if @reflection.options[:as]
177
- record["#{@reflection.options[:as]}_id"] = @owner.id unless @owner.new_record?
178
- record["#{@reflection.options[:as]}_type"] = @owner.class.base_class.name.to_s
179
- else
180
- unless @owner.new_record?
181
- primary_key = @reflection.options[:primary_key] || :id
182
- record[@reflection.primary_key_name] = @owner.send(primary_key)
183
- end
184
- end
185
- end
186
-
187
- # Merges into +options+ the ones coming from the reflection.
188
- def merge_options_from_reflection!(options)
189
- options.reverse_merge!(
190
- :group => @reflection.options[:group],
191
- :having => @reflection.options[:having],
192
- :limit => @reflection.options[:limit],
193
- :offset => @reflection.options[:offset],
194
- :joins => @reflection.options[:joins],
195
- :include => @reflection.options[:include],
196
- :select => @reflection.options[:select],
197
- :readonly => @reflection.options[:readonly]
198
- )
199
- end
200
-
201
- # Forwards +with_scope+ to the reflection.
202
- def with_scope(*args, &block)
203
- @reflection.klass.send :with_scope, *args, &block
204
- end
205
-
206
- private
207
- # Forwards any missing method call to the \target.
208
- def method_missing(method, *args)
209
- if load_target
210
- unless @target.respond_to?(method)
211
- message = "undefined method `#{method.to_s}' for \"#{@target}\":#{@target.class.to_s}"
212
- raise NoMethodError, message
213
- end
214
-
215
- if block_given?
216
- @target.send(method, *args) { |*block_args| yield(*block_args) }
217
- else
218
- @target.send(method, *args)
219
- end
220
- end
221
- end
222
-
223
- # Loads the \target if needed and returns it.
224
- #
225
- # This method is abstract in the sense that it relies on +find_target+,
226
- # which is expected to be provided by descendants.
227
- #
228
- # If the \target is already \loaded it is just returned. Thus, you can call
229
- # +load_target+ unconditionally to get the \target.
230
- #
231
- # ActiveRecord::RecordNotFound is rescued within the method, and it is
232
- # not reraised. The proxy is \reset and +nil+ is the return value.
233
- def load_target
234
- return nil unless defined?(@loaded)
235
-
236
- if !loaded? and (!@owner.new_record? || foreign_key_present)
237
- @target = find_target
238
- end
239
-
240
- @loaded = true
241
- @target
242
- rescue ActiveRecord::RecordNotFound
243
- reset
244
- end
245
-
246
- # Can be overwritten by associations that might have the foreign key
247
- # available for an association without having the object itself (and
248
- # still being a new record). Currently, only +belongs_to+ presents
249
- # this scenario (both vanilla and polymorphic).
250
- def foreign_key_present
251
- false
252
- end
253
-
254
- # Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
255
- # the kind of the class of the associated objects. Meant to be used as
256
- # a sanity check when you are about to assign an associated record.
257
- def raise_on_type_mismatch(record)
258
- unless record.is_a?(@reflection.klass) || record.is_a?(@reflection.class_name.constantize)
259
- message = "#{@reflection.class_name}(##{@reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
260
- raise ActiveRecord::AssociationTypeMismatch, message
261
- end
262
- end
263
-
264
- if RUBY_VERSION < '1.9.2'
265
- # Array#flatten has problems with recursive arrays before Ruby 1.9.2.
266
- # Going one level deeper solves the majority of the problems.
267
- def flatten_deeper(array)
268
- array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
269
- end
270
- else
271
- def flatten_deeper(array)
272
- array.flatten
273
- end
274
- end
275
-
276
- # Returns the ID of the owner, quoted if needed.
277
- def owner_quoted_id
278
- @owner.quoted_id
279
- end
280
-
281
- def set_inverse_instance(record, instance)
282
- return if record.nil? || !we_can_set_the_inverse_on_this?(record)
283
- inverse_relationship = @reflection.inverse_of
284
- unless inverse_relationship.nil?
285
- record.send(:"set_#{inverse_relationship.name}_target", instance)
286
- end
287
- end
288
-
289
- # Override in subclasses
290
- def we_can_set_the_inverse_on_this?(record)
291
- false
292
- end
293
- end
294
- end
295
- end
@@ -1,154 +0,0 @@
1
- module ActiveRecord
2
- # = Active Record Through Association Scope
3
- module Associations
4
- module ThroughAssociationScope
5
-
6
- protected
7
-
8
- def construct_scope
9
- { :create => construct_owner_attributes(@reflection),
10
- :find => { :conditions => construct_conditions,
11
- :joins => construct_joins,
12
- :include => @reflection.options[:include] || @reflection.source_reflection.options[:include],
13
- :select => construct_select,
14
- :order => @reflection.options[:order],
15
- :limit => @reflection.options[:limit],
16
- :readonly => @reflection.options[:readonly],
17
- } }
18
- end
19
-
20
- # Build SQL conditions from attributes, qualified by table name.
21
- def construct_conditions
22
- table_name = @reflection.through_reflection.quoted_table_name
23
- conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value|
24
- "#{table_name}.#{attr} = #{value}"
25
- end
26
- conditions << sql_conditions if sql_conditions
27
- "(" + conditions.join(') AND (') + ")"
28
- end
29
-
30
- # Associate attributes pointing to owner, quoted.
31
- def construct_quoted_owner_attributes(reflection)
32
- if as = reflection.options[:as]
33
- { "#{as}_id" => owner_quoted_id,
34
- "#{as}_type" => reflection.klass.quote_value(
35
- @owner.class.base_class.name.to_s,
36
- reflection.klass.columns_hash["#{as}_type"]) }
37
- elsif reflection.macro == :belongs_to
38
- { reflection.klass.primary_key => @owner.class.quote_value(@owner[reflection.primary_key_name]) }
39
- else
40
- { reflection.primary_key_name => owner_quoted_id }
41
- end
42
- end
43
-
44
- def construct_from
45
- @reflection.table_name
46
- end
47
-
48
- def construct_select(custom_select = nil)
49
- distinct = "DISTINCT " if @reflection.options[:uniq]
50
- selected = custom_select || @reflection.options[:select] || "#{distinct}#{@reflection.quoted_table_name}.*"
51
- end
52
-
53
- def construct_joins(custom_joins = nil)
54
- polymorphic_join = nil
55
- if @reflection.source_reflection.macro == :belongs_to
56
- reflection_primary_key = @reflection.klass.primary_key
57
- source_primary_key = @reflection.source_reflection.primary_key_name
58
- if @reflection.options[:source_type]
59
- polymorphic_join = "AND %s.%s = %s" % [
60
- @reflection.through_reflection.quoted_table_name, "#{@reflection.source_reflection.options[:foreign_type]}",
61
- @owner.class.quote_value(@reflection.options[:source_type])
62
- ]
63
- end
64
- else
65
- reflection_primary_key = @reflection.source_reflection.primary_key_name
66
- source_primary_key = @reflection.through_reflection.klass.primary_key
67
- if @reflection.source_reflection.options[:as]
68
- polymorphic_join = "AND %s.%s = %s" % [
69
- @reflection.quoted_table_name, "#{@reflection.source_reflection.options[:as]}_type",
70
- @owner.class.quote_value(@reflection.through_reflection.klass.name)
71
- ]
72
- end
73
- end
74
-
75
- "INNER JOIN %s ON %s.%s = %s.%s %s #{@reflection.options[:joins]} #{custom_joins}" % [
76
- @reflection.through_reflection.quoted_table_name,
77
- @reflection.quoted_table_name, reflection_primary_key,
78
- @reflection.through_reflection.quoted_table_name, source_primary_key,
79
- polymorphic_join
80
- ]
81
- end
82
-
83
- # Construct attributes for associate pointing to owner.
84
- def construct_owner_attributes(reflection)
85
- if as = reflection.options[:as]
86
- { "#{as}_id" => @owner.id,
87
- "#{as}_type" => @owner.class.base_class.name.to_s }
88
- else
89
- { reflection.primary_key_name => @owner.id }
90
- end
91
- end
92
-
93
- # Construct attributes for :through pointing to owner and associate.
94
- def construct_join_attributes(associate)
95
- # TODO: revisit this to allow it for deletion, supposing dependent option is supported
96
- raise ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(@owner, @reflection) if [:has_one, :has_many].include?(@reflection.source_reflection.macro)
97
-
98
- join_attributes = construct_owner_attributes(@reflection.through_reflection).merge(@reflection.source_reflection.primary_key_name => associate.id)
99
-
100
- if @reflection.options[:source_type]
101
- join_attributes.merge!(@reflection.source_reflection.options[:foreign_type] => associate.class.base_class.name.to_s)
102
- end
103
-
104
- if @reflection.through_reflection.options[:conditions].is_a?(Hash)
105
- join_attributes.merge!(@reflection.through_reflection.options[:conditions])
106
- end
107
-
108
- join_attributes
109
- end
110
-
111
- def conditions
112
- @conditions = build_conditions unless defined?(@conditions)
113
- @conditions
114
- end
115
-
116
- def build_conditions
117
- association_conditions = @reflection.options[:conditions]
118
- through_conditions = build_through_conditions
119
- source_conditions = @reflection.source_reflection.options[:conditions]
120
- uses_sti = !@reflection.through_reflection.klass.descends_from_active_record?
121
-
122
- if association_conditions || through_conditions || source_conditions || uses_sti
123
- all = []
124
-
125
- [association_conditions, source_conditions].each do |conditions|
126
- all << interpolate_sql(sanitize_sql(conditions)) if conditions
127
- end
128
-
129
- all << through_conditions if through_conditions
130
- all << build_sti_condition if uses_sti
131
-
132
- all.map { |sql| "(#{sql})" } * ' AND '
133
- end
134
- end
135
-
136
- def build_through_conditions
137
- conditions = @reflection.through_reflection.options[:conditions]
138
- if conditions.is_a?(Hash)
139
- interpolate_sql(@reflection.through_reflection.klass.send(:sanitize_sql, conditions)).gsub(
140
- @reflection.quoted_table_name,
141
- @reflection.through_reflection.quoted_table_name)
142
- elsif conditions
143
- interpolate_sql(sanitize_sql(conditions))
144
- end
145
- end
146
-
147
- def build_sti_condition
148
- @reflection.through_reflection.klass.send(:type_condition).to_sql
149
- end
150
-
151
- alias_method :sql_conditions, :conditions
152
- end
153
- end
154
- end
@@ -1,113 +0,0 @@
1
- module ActiveRecord
2
- class Base
3
- class ConnectionSpecification #:nodoc:
4
- attr_reader :config, :adapter_method
5
- def initialize (config, adapter_method)
6
- @config, @adapter_method = config, adapter_method
7
- end
8
- end
9
-
10
- ##
11
- # :singleton-method:
12
- # The connection handler
13
- class_attribute :connection_handler, :instance_writer => false
14
- self.connection_handler = ConnectionAdapters::ConnectionHandler.new
15
-
16
- # Returns the connection currently associated with the class. This can
17
- # also be used to "borrow" the connection to do database work that isn't
18
- # easily done without going straight to SQL.
19
- def connection
20
- self.class.connection
21
- end
22
-
23
- # Establishes the connection to the database. Accepts a hash as input where
24
- # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
25
- # example for regular databases (MySQL, Postgresql, etc):
26
- #
27
- # ActiveRecord::Base.establish_connection(
28
- # :adapter => "mysql",
29
- # :host => "localhost",
30
- # :username => "myuser",
31
- # :password => "mypass",
32
- # :database => "somedatabase"
33
- # )
34
- #
35
- # Example for SQLite database:
36
- #
37
- # ActiveRecord::Base.establish_connection(
38
- # :adapter => "sqlite",
39
- # :database => "path/to/dbfile"
40
- # )
41
- #
42
- # Also accepts keys as strings (for parsing from YAML for example):
43
- #
44
- # ActiveRecord::Base.establish_connection(
45
- # "adapter" => "sqlite",
46
- # "database" => "path/to/dbfile"
47
- # )
48
- #
49
- # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
50
- # may be returned on an error.
51
- def self.establish_connection(spec = nil)
52
- case spec
53
- when nil
54
- raise AdapterNotSpecified unless defined?(Rails.env)
55
- establish_connection(Rails.env)
56
- when ConnectionSpecification
57
- self.connection_handler.establish_connection(name, spec)
58
- when Symbol, String
59
- if configuration = configurations[spec.to_s]
60
- establish_connection(configuration)
61
- else
62
- raise AdapterNotSpecified, "#{spec} database is not configured"
63
- end
64
- else
65
- spec = spec.symbolize_keys
66
- unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end
67
-
68
- begin
69
- require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
70
- rescue LoadError
71
- raise "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{$!})"
72
- end
73
-
74
- adapter_method = "#{spec[:adapter]}_connection"
75
- if !respond_to?(adapter_method)
76
- raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter"
77
- end
78
-
79
- remove_connection
80
- establish_connection(ConnectionSpecification.new(spec, adapter_method))
81
- end
82
- end
83
-
84
- class << self
85
- # Returns the connection currently associated with the class. This can
86
- # also be used to "borrow" the connection to do database work unrelated
87
- # to any of the specific Active Records.
88
- def connection
89
- retrieve_connection
90
- end
91
-
92
- def connection_pool
93
- connection_handler.retrieve_connection_pool(self)
94
- end
95
-
96
- def retrieve_connection
97
- connection_handler.retrieve_connection(self)
98
- end
99
-
100
- # Returns true if Active Record is connected.
101
- def connected?
102
- connection_handler.connected?(self)
103
- end
104
-
105
- def remove_connection(klass = self)
106
- connection_handler.remove_connection(klass)
107
- end
108
-
109
- delegate :clear_active_connections!, :clear_reloadable_connections!,
110
- :clear_all_connections!,:verify_active_connections!, :to => :connection_handler
111
- end
112
- end
113
- end