activerecord 5.1.5 → 5.2.8.1

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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +655 -608
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +7 -5
  9. data/lib/active_record/associations/alias_tracker.rb +19 -27
  10. data/lib/active_record/associations/association.rb +41 -37
  11. data/lib/active_record/associations/association_scope.rb +38 -50
  12. data/lib/active_record/associations/belongs_to_association.rb +28 -9
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +14 -5
  16. data/lib/active_record/associations/builder/collection_association.rb +3 -3
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +59 -47
  22. data/lib/active_record/associations/collection_proxy.rb +20 -49
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +12 -1
  25. data/lib/active_record/associations/has_many_through_association.rb +36 -30
  26. data/lib/active_record/associations/has_one_association.rb +12 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +13 -8
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
  31. data/lib/active_record/associations/join_dependency.rb +48 -93
  32. data/lib/active_record/associations/preloader/association.rb +45 -61
  33. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  34. data/lib/active_record/associations/preloader.rb +18 -38
  35. data/lib/active_record/associations/singular_association.rb +14 -16
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +40 -63
  38. data/lib/active_record/attribute_assignment.rb +2 -5
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +32 -216
  42. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +9 -3
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +21 -9
  48. data/lib/active_record/attribute_methods.rb +65 -24
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +35 -19
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +12 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +15 -1
  55. data/lib/active_record/collection_cache_key.rb +12 -8
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +142 -42
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -32
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +110 -173
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -3
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -112
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +66 -74
  117. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +24 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +82 -95
  126. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  127. data/lib/active_record/connection_handling.rb +4 -2
  128. data/lib/active_record/core.rb +51 -61
  129. data/lib/active_record/counter_cache.rb +20 -15
  130. data/lib/active_record/define_callbacks.rb +5 -3
  131. data/lib/active_record/dynamic_matchers.rb +9 -9
  132. data/lib/active_record/enum.rb +18 -13
  133. data/lib/active_record/errors.rb +60 -15
  134. data/lib/active_record/explain.rb +3 -1
  135. data/lib/active_record/explain_registry.rb +2 -0
  136. data/lib/active_record/explain_subscriber.rb +2 -0
  137. data/lib/active_record/fixture_set/file.rb +2 -0
  138. data/lib/active_record/fixtures.rb +67 -60
  139. data/lib/active_record/gem_version.rb +5 -3
  140. data/lib/active_record/inheritance.rb +49 -19
  141. data/lib/active_record/integration.rb +58 -19
  142. data/lib/active_record/internal_metadata.rb +2 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  144. data/lib/active_record/locking/optimistic.rb +30 -42
  145. data/lib/active_record/locking/pessimistic.rb +9 -6
  146. data/lib/active_record/log_subscriber.rb +43 -0
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +47 -9
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/migration.rb +189 -139
  151. data/lib/active_record/model_schema.rb +19 -24
  152. data/lib/active_record/nested_attributes.rb +18 -6
  153. data/lib/active_record/no_touching.rb +3 -1
  154. data/lib/active_record/null_relation.rb +2 -0
  155. data/lib/active_record/persistence.rb +198 -49
  156. data/lib/active_record/query_cache.rb +12 -14
  157. data/lib/active_record/querying.rb +4 -2
  158. data/lib/active_record/railtie.rb +80 -6
  159. data/lib/active_record/railties/console_sandbox.rb +2 -0
  160. data/lib/active_record/railties/controller_runtime.rb +2 -0
  161. data/lib/active_record/railties/databases.rake +46 -36
  162. data/lib/active_record/readonly_attributes.rb +3 -2
  163. data/lib/active_record/reflection.rb +108 -194
  164. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  165. data/lib/active_record/relation/batches.rb +20 -5
  166. data/lib/active_record/relation/calculations.rb +46 -20
  167. data/lib/active_record/relation/delegation.rb +45 -27
  168. data/lib/active_record/relation/finder_methods.rb +77 -78
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +53 -23
  171. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  172. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  173. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  174. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  175. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  176. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  177. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  178. data/lib/active_record/relation/predicate_builder.rb +60 -79
  179. data/lib/active_record/relation/query_attribute.rb +28 -2
  180. data/lib/active_record/relation/query_methods.rb +129 -100
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +4 -2
  183. data/lib/active_record/relation/where_clause.rb +65 -68
  184. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  185. data/lib/active_record/relation.rb +120 -214
  186. data/lib/active_record/result.rb +2 -0
  187. data/lib/active_record/runtime_registry.rb +2 -0
  188. data/lib/active_record/sanitization.rb +129 -121
  189. data/lib/active_record/schema.rb +4 -2
  190. data/lib/active_record/schema_dumper.rb +36 -26
  191. data/lib/active_record/schema_migration.rb +2 -0
  192. data/lib/active_record/scoping/default.rb +8 -9
  193. data/lib/active_record/scoping/named.rb +23 -7
  194. data/lib/active_record/scoping.rb +9 -8
  195. data/lib/active_record/secure_token.rb +2 -0
  196. data/lib/active_record/serialization.rb +2 -0
  197. data/lib/active_record/statement_cache.rb +23 -13
  198. data/lib/active_record/store.rb +3 -1
  199. data/lib/active_record/suppressor.rb +2 -0
  200. data/lib/active_record/table_metadata.rb +12 -3
  201. data/lib/active_record/tasks/database_tasks.rb +26 -15
  202. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  203. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  204. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  205. data/lib/active_record/timestamp.rb +13 -6
  206. data/lib/active_record/touch_later.rb +2 -0
  207. data/lib/active_record/transactions.rb +33 -28
  208. data/lib/active_record/translation.rb +2 -0
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +6 -0
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type.rb +4 -1
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +3 -1
  224. data/lib/active_record/type_caster.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +36 -6
  230. data/lib/active_record/validations.rb +2 -0
  231. data/lib/active_record/version.rb +2 -0
  232. data/lib/active_record.rb +11 -4
  233. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  234. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  238. data/lib/rails/generators/active_record/migration.rb +2 -0
  239. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  240. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record.rb +3 -1
  243. metadata +26 -40
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  252. data/lib/active_record/attribute.rb +0 -240
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -114
  254. data/lib/active_record/attribute_set/builder.rb +0 -124
  255. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  256. data/lib/active_record/attribute_set.rb +0 -113
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record/relation/from_clause"
2
4
  require "active_record/relation/query_attribute"
3
5
  require "active_record/relation/where_clause"
@@ -74,31 +76,6 @@ module ActiveRecord
74
76
  CODE
75
77
  end
76
78
 
77
- def bound_attributes
78
- if limit_value
79
- limit_bind = Attribute.with_cast_value(
80
- "LIMIT".freeze,
81
- connection.sanitize_limit(limit_value),
82
- Type.default_value,
83
- )
84
- end
85
- if offset_value
86
- offset_bind = Attribute.with_cast_value(
87
- "OFFSET".freeze,
88
- offset_value.to_i,
89
- Type.default_value,
90
- )
91
- end
92
- connection.combine_bind_parameters(
93
- from_clause: from_clause.binds,
94
- join_clause: arel.bind_values,
95
- where_clause: where_clause.binds,
96
- having_clause: having_clause.binds,
97
- limit: limit_bind,
98
- offset: offset_bind,
99
- )
100
- end
101
-
102
79
  alias extensions extending_values
103
80
 
104
81
  # Specify relationships to be included in the result set. For
@@ -202,12 +179,13 @@ module ActiveRecord
202
179
 
203
180
  # Works in two unique ways.
204
181
  #
205
- # First: takes a block so it can be used just like +Array#select+.
182
+ # First: takes a block so it can be used just like <tt>Array#select</tt>.
206
183
  #
207
184
  # Model.all.select { |m| m.field == value }
208
185
  #
209
186
  # This will build an array of objects from the database for the scope,
210
- # converting them into an array and iterating through them using +Array#select+.
187
+ # converting them into an array and iterating through them using
188
+ # <tt>Array#select</tt>.
211
189
  #
212
190
  # Second: Modifies the SELECT statement for the query so that only certain
213
191
  # fields are retrieved:
@@ -248,15 +226,12 @@ module ActiveRecord
248
226
  return super()
249
227
  end
250
228
 
251
- raise ArgumentError, "Call this with at least one field" if fields.empty?
229
+ raise ArgumentError, "Call `select' with at least one field" if fields.empty?
252
230
  spawn._select!(*fields)
253
231
  end
254
232
 
255
233
  def _select!(*fields) # :nodoc:
256
234
  fields.flatten!
257
- fields.map! do |field|
258
- klass.attribute_alias?(field) ? klass.attribute_alias(field).to_sym : field
259
- end
260
235
  self.select_values += fields
261
236
  self
262
237
  end
@@ -317,6 +292,7 @@ module ActiveRecord
317
292
  spawn.order!(*args)
318
293
  end
319
294
 
295
+ # Same as #order but operates on relation in-place instead of copying.
320
296
  def order!(*args) # :nodoc:
321
297
  preprocess_order_args(args)
322
298
 
@@ -338,6 +314,7 @@ module ActiveRecord
338
314
  spawn.reorder!(*args)
339
315
  end
340
316
 
317
+ # Same as #reorder but operates on relation in-place instead of copying.
341
318
  def reorder!(*args) # :nodoc:
342
319
  preprocess_order_args(args)
343
320
 
@@ -347,8 +324,8 @@ module ActiveRecord
347
324
  end
348
325
 
349
326
  VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock,
350
- :limit, :offset, :joins, :includes, :from,
351
- :readonly, :having])
327
+ :limit, :offset, :joins, :left_outer_joins,
328
+ :includes, :from, :readonly, :having])
352
329
 
353
330
  # Removes an unwanted relation that is already defined on a chain of relations.
354
331
  # This is useful when passing around chains of relations and would like to
@@ -395,10 +372,11 @@ module ActiveRecord
395
372
  args.each do |scope|
396
373
  case scope
397
374
  when Symbol
375
+ scope = :left_outer_joins if scope == :left_joins
398
376
  if !VALID_UNSCOPING_VALUES.include?(scope)
399
377
  raise ArgumentError, "Called unscope() with invalid unscoping argument ':#{scope}'. Valid arguments are :#{VALID_UNSCOPING_VALUES.to_a.join(", :")}."
400
378
  end
401
- set_value(scope, nil)
379
+ set_value(scope, DEFAULT_VALUES[scope])
402
380
  when Hash
403
381
  scope.each do |key, target_value|
404
382
  if key != :where
@@ -463,16 +441,14 @@ module ActiveRecord
463
441
  # => SELECT "users".* FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
464
442
  #
465
443
  def left_outer_joins(*args)
466
- check_if_method_has_arguments!(:left_outer_joins, args)
467
-
468
- args.compact!
469
- args.flatten!
470
-
444
+ check_if_method_has_arguments!(__callee__, args)
471
445
  spawn.left_outer_joins!(*args)
472
446
  end
473
447
  alias :left_joins :left_outer_joins
474
448
 
475
449
  def left_outer_joins!(*args) # :nodoc:
450
+ args.compact!
451
+ args.flatten!
476
452
  self.left_outer_joins_values += args
477
453
  self
478
454
  end
@@ -657,6 +633,7 @@ module ActiveRecord
657
633
 
658
634
  self.where_clause = self.where_clause.or(other.where_clause)
659
635
  self.having_clause = having_clause.or(other.having_clause)
636
+ self.references_values += other.references_values
660
637
 
661
638
  self
662
639
  end
@@ -797,7 +774,7 @@ module ActiveRecord
797
774
  value = sanitize_forbidden_attributes(value)
798
775
  self.create_with_value = create_with_value.merge(value)
799
776
  else
800
- self.create_with_value = {}
777
+ self.create_with_value = FROZEN_EMPTY_HASH
801
778
  end
802
779
 
803
780
  self
@@ -913,21 +890,28 @@ module ActiveRecord
913
890
  self
914
891
  end
915
892
 
893
+ def skip_query_cache!(value = true) # :nodoc:
894
+ self.skip_query_cache_value = value
895
+ self
896
+ end
897
+
916
898
  # Returns the Arel object associated with the relation.
917
- def arel # :nodoc:
918
- @arel ||= build_arel
899
+ def arel(aliases = nil) # :nodoc:
900
+ @arel ||= build_arel(aliases)
919
901
  end
920
902
 
921
903
  # Returns a relation value with a given name
922
904
  def get_value(name) # :nodoc:
923
- @values[name] || default_value_for(name)
905
+ @values.fetch(name, DEFAULT_VALUES[name])
924
906
  end
925
907
 
926
- # Sets the relation value with the given name
927
- def set_value(name, value) # :nodoc:
928
- assert_mutability!
929
- @values[name] = value
930
- end
908
+ protected
909
+
910
+ # Sets the relation value with the given name
911
+ def set_value(name, value) # :nodoc:
912
+ assert_mutability!
913
+ @values[name] = value
914
+ end
931
915
 
932
916
  private
933
917
 
@@ -936,16 +920,30 @@ module ActiveRecord
936
920
  raise ImmutableRelation if defined?(@arel) && @arel
937
921
  end
938
922
 
939
- def build_arel
923
+ def build_arel(aliases)
940
924
  arel = Arel::SelectManager.new(table)
941
925
 
942
- build_joins(arel, joins_values.flatten) unless joins_values.empty?
943
- build_left_outer_joins(arel, left_outer_joins_values.flatten) unless left_outer_joins_values.empty?
926
+ aliases = build_joins(arel, joins_values.flatten, aliases) unless joins_values.empty?
927
+ build_left_outer_joins(arel, left_outer_joins_values.flatten, aliases) unless left_outer_joins_values.empty?
944
928
 
945
929
  arel.where(where_clause.ast) unless where_clause.empty?
946
930
  arel.having(having_clause.ast) unless having_clause.empty?
947
- arel.take(Arel::Nodes::BindParam.new) if limit_value
948
- arel.skip(Arel::Nodes::BindParam.new) if offset_value
931
+ if limit_value
932
+ limit_attribute = ActiveModel::Attribute.with_cast_value(
933
+ "LIMIT".freeze,
934
+ connection.sanitize_limit(limit_value),
935
+ Type.default_value,
936
+ )
937
+ arel.take(Arel::Nodes::BindParam.new(limit_attribute))
938
+ end
939
+ if offset_value
940
+ offset_attribute = ActiveModel::Attribute.with_cast_value(
941
+ "OFFSET".freeze,
942
+ offset_value.to_i,
943
+ Type.default_value,
944
+ )
945
+ arel.skip(Arel::Nodes::BindParam.new(offset_attribute))
946
+ end
949
947
  arel.group(*arel_columns(group_values.uniq.reject(&:blank?))) unless group_values.empty?
950
948
 
951
949
  build_order(arel)
@@ -964,6 +962,9 @@ module ActiveRecord
964
962
  name = from_clause.name
965
963
  case opts
966
964
  when Relation
965
+ if opts.eager_loading?
966
+ opts = opts.send(:apply_join_dependency)
967
+ end
967
968
  name ||= "subquery"
968
969
  opts.arel.as(name.to_s)
969
970
  else
@@ -971,20 +972,22 @@ module ActiveRecord
971
972
  end
972
973
  end
973
974
 
974
- def build_left_outer_joins(manager, outer_joins)
975
+ def build_left_outer_joins(manager, outer_joins, aliases)
975
976
  buckets = outer_joins.group_by do |join|
976
977
  case join
977
978
  when Hash, Symbol, Array
978
979
  :association_join
980
+ when ActiveRecord::Associations::JoinDependency
981
+ :stashed_join
979
982
  else
980
983
  raise ArgumentError, "only Hash, Symbol and Array are allowed"
981
984
  end
982
985
  end
983
986
 
984
- build_join_query(manager, buckets, Arel::Nodes::OuterJoin)
987
+ build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases)
985
988
  end
986
989
 
987
- def build_joins(manager, joins)
990
+ def build_joins(manager, joins, aliases)
988
991
  buckets = joins.group_by do |join|
989
992
  case join
990
993
  when String
@@ -1000,38 +1003,33 @@ module ActiveRecord
1000
1003
  end
1001
1004
  end
1002
1005
 
1003
- build_join_query(manager, buckets, Arel::Nodes::InnerJoin)
1006
+ build_join_query(manager, buckets, Arel::Nodes::InnerJoin, aliases)
1004
1007
  end
1005
1008
 
1006
- def build_join_query(manager, buckets, join_type)
1009
+ def build_join_query(manager, buckets, join_type, aliases)
1007
1010
  buckets.default = []
1008
1011
 
1009
- association_joins = buckets[:association_join]
1010
- stashed_association_joins = buckets[:stashed_join]
1011
- join_nodes = buckets[:join_node].uniq
1012
- string_joins = buckets[:string_join].map(&:strip).uniq
1012
+ association_joins = buckets[:association_join]
1013
+ stashed_joins = buckets[:stashed_join]
1014
+ join_nodes = buckets[:join_node].uniq
1015
+ string_joins = buckets[:string_join].map(&:strip).uniq
1013
1016
 
1014
- join_list = join_nodes + convert_join_strings_to_ast(manager, string_joins)
1017
+ join_list = join_nodes + convert_join_strings_to_ast(string_joins)
1018
+ alias_tracker = alias_tracker(join_list, aliases)
1015
1019
 
1016
1020
  join_dependency = ActiveRecord::Associations::JoinDependency.new(
1017
- @klass,
1018
- association_joins,
1019
- join_list
1021
+ klass, table, association_joins
1020
1022
  )
1021
1023
 
1022
- join_infos = join_dependency.join_constraints stashed_association_joins, join_type
1023
-
1024
- join_infos.each do |info|
1025
- info.joins.each { |join| manager.from(join) }
1026
- manager.bind_values.concat info.binds
1027
- end
1024
+ joins = join_dependency.join_constraints(stashed_joins, join_type, alias_tracker)
1025
+ joins.each { |join| manager.from(join) }
1028
1026
 
1029
1027
  manager.join_sources.concat(join_list)
1030
1028
 
1031
- manager
1029
+ alias_tracker.aliases
1032
1030
  end
1033
1031
 
1034
- def convert_join_strings_to_ast(table, joins)
1032
+ def convert_join_strings_to_ast(joins)
1035
1033
  joins
1036
1034
  .flatten
1037
1035
  .reject(&:blank?)
@@ -1044,22 +1042,42 @@ module ActiveRecord
1044
1042
  elsif klass.ignored_columns.any?
1045
1043
  arel.project(*klass.column_names.map { |field| arel_attribute(field) })
1046
1044
  else
1047
- arel.project(@klass.arel_table[Arel.star])
1045
+ arel.project(table[Arel.star])
1048
1046
  end
1049
1047
  end
1050
1048
 
1051
1049
  def arel_columns(columns)
1052
- columns.map do |field|
1053
- if (Symbol === field || String === field) && (klass.has_attribute?(field) || klass.attribute_alias?(field)) && !from_clause.value
1054
- arel_attribute(field)
1055
- elsif Symbol === field
1056
- connection.quote_table_name(field.to_s)
1050
+ columns.flat_map do |field|
1051
+ case field
1052
+ when Symbol
1053
+ arel_column(field.to_s) do |attr_name|
1054
+ connection.quote_table_name(attr_name)
1055
+ end
1056
+ when String
1057
+ arel_column(field, &:itself)
1058
+ when Proc
1059
+ field.call
1057
1060
  else
1058
1061
  field
1059
1062
  end
1060
1063
  end
1061
1064
  end
1062
1065
 
1066
+ def arel_column(field)
1067
+ field = klass.attribute_alias(field) if klass.attribute_alias?(field)
1068
+ from = from_clause.name || from_clause.value
1069
+
1070
+ if klass.columns_hash.key?(field) && (!from || table_name_matches?(from))
1071
+ arel_attribute(field)
1072
+ else
1073
+ yield field
1074
+ end
1075
+ end
1076
+
1077
+ def table_name_matches?(from)
1078
+ /(?:\A|(?<!FROM)\s)(?:\b#{table.name}\b|#{connection.quote_table_name(table.name)})(?!\.)/i.match?(from.to_s)
1079
+ end
1080
+
1063
1081
  def reverse_sql_order(order_query)
1064
1082
  if order_query.empty?
1065
1083
  return [arel_attribute(primary_key).desc] if primary_key
@@ -1079,7 +1097,7 @@ module ActiveRecord
1079
1097
  end
1080
1098
  o.split(",").map! do |s|
1081
1099
  s.strip!
1082
- s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || s.concat(" DESC")
1100
+ s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || (s << " DESC")
1083
1101
  end
1084
1102
  else
1085
1103
  o
@@ -1088,6 +1106,10 @@ module ActiveRecord
1088
1106
  end
1089
1107
 
1090
1108
  def does_not_support_reverse?(order)
1109
+ # Account for String subclasses like Arel::Nodes::SqlLiteral that
1110
+ # override methods like #count.
1111
+ order = String.new(order) unless order.instance_of?(String)
1112
+
1091
1113
  # Uses SQL function with multiple arguments.
1092
1114
  (order.include?(",") && order.split(",").find { |section| section.count("(") != section.count(")") }) ||
1093
1115
  # Uses "nulls first" like construction.
@@ -1102,41 +1124,49 @@ module ActiveRecord
1102
1124
  end
1103
1125
 
1104
1126
  VALID_DIRECTIONS = [:asc, :desc, :ASC, :DESC,
1105
- "asc", "desc", "ASC", "DESC"] # :nodoc:
1127
+ "asc", "desc", "ASC", "DESC"].to_set # :nodoc:
1106
1128
 
1107
1129
  def validate_order_args(args)
1108
1130
  args.each do |arg|
1109
1131
  next unless arg.is_a?(Hash)
1110
1132
  arg.each do |_key, value|
1111
- raise ArgumentError, "Direction \"#{value}\" is invalid. Valid " \
1112
- "directions are: #{VALID_DIRECTIONS.inspect}" unless VALID_DIRECTIONS.include?(value)
1133
+ unless VALID_DIRECTIONS.include?(value)
1134
+ raise ArgumentError,
1135
+ "Direction \"#{value}\" is invalid. Valid directions are: #{VALID_DIRECTIONS.to_a.inspect}"
1136
+ end
1113
1137
  end
1114
1138
  end
1115
1139
  end
1116
1140
 
1117
1141
  def preprocess_order_args(order_args)
1118
1142
  order_args.map! do |arg|
1119
- klass.send(:sanitize_sql_for_order, arg)
1143
+ klass.sanitize_sql_for_order(arg)
1120
1144
  end
1121
1145
  order_args.flatten!
1146
+
1147
+ @klass.enforce_raw_sql_whitelist(
1148
+ order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a },
1149
+ whitelist: AttributeMethods::ClassMethods::COLUMN_NAME_ORDER_WHITELIST
1150
+ )
1151
+
1122
1152
  validate_order_args(order_args)
1123
1153
 
1124
1154
  references = order_args.grep(String)
1125
- references.map! { |arg| arg =~ /^([a-zA-Z]\w*)\.(\w+)/ && $1 }.compact!
1155
+ references.map! { |arg| arg =~ /^\W?(\w+)\W?\./ && $1 }.compact!
1126
1156
  references!(references) if references.any?
1127
1157
 
1128
1158
  # if a symbol is given we prepend the quoted table name
1129
1159
  order_args.map! do |arg|
1130
1160
  case arg
1131
1161
  when Symbol
1132
- arel_attribute(arg).asc
1162
+ order_column(arg.to_s).asc
1133
1163
  when Hash
1134
1164
  arg.map { |field, dir|
1135
1165
  case field
1136
1166
  when Arel::Nodes::SqlLiteral
1137
1167
  field.send(dir.downcase)
1138
1168
  else
1139
- arel_attribute(field).send(dir.downcase)
1169
+ order_column(field.to_s).send(dir.downcase)
1140
1170
  end
1141
1171
  }
1142
1172
  else
@@ -1145,6 +1175,16 @@ module ActiveRecord
1145
1175
  end.flatten!
1146
1176
  end
1147
1177
 
1178
+ def order_column(field)
1179
+ arel_column(field) do |attr_name|
1180
+ if attr_name == "count" && !group_values.empty?
1181
+ arel_attribute(attr_name)
1182
+ else
1183
+ Arel.sql(connection.quote_table_name(attr_name))
1184
+ end
1185
+ end
1186
+ end
1187
+
1148
1188
  # Checks to make sure that the arguments are not blank. Note that if some
1149
1189
  # blank-like object were initially passed into the query method, then this
1150
1190
  # method will not raise an error.
@@ -1167,7 +1207,7 @@ module ActiveRecord
1167
1207
  end
1168
1208
  end
1169
1209
 
1170
- STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having]
1210
+ STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references]
1171
1211
  def structurally_incompatible_values_for_or(other)
1172
1212
  STRUCTURAL_OR_METHODS.reject do |method|
1173
1213
  get_value(method) == other.get_value(method)
@@ -1181,7 +1221,6 @@ module ActiveRecord
1181
1221
 
1182
1222
  DEFAULT_VALUES = {
1183
1223
  create_with: FROZEN_EMPTY_HASH,
1184
- readonly: false,
1185
1224
  where: Relation::WhereClause.empty,
1186
1225
  having: Relation::WhereClause.empty,
1187
1226
  from: Relation::FromClause.empty
@@ -1190,15 +1229,5 @@ module ActiveRecord
1190
1229
  Relation::MULTI_VALUE_METHODS.each do |value|
1191
1230
  DEFAULT_VALUES[value] ||= FROZEN_EMPTY_ARRAY
1192
1231
  end
1193
-
1194
- Relation::SINGLE_VALUE_METHODS.each do |value|
1195
- DEFAULT_VALUES[value] = nil if DEFAULT_VALUES[value].nil?
1196
- end
1197
-
1198
- def default_value_for(name)
1199
- DEFAULT_VALUES.fetch(name) do
1200
- raise ArgumentError, "unknown relation value #{name.inspect}"
1201
- end
1202
- end
1203
1232
  end
1204
1233
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class Relation
3
5
  module RecordFetchWarning
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/except"
2
4
  require "active_support/core_ext/hash/slice"
3
5
  require "active_record/relation/merger"
@@ -6,7 +8,7 @@ module ActiveRecord
6
8
  module SpawnMethods
7
9
  # This is overridden by Associations::CollectionProxy
8
10
  def spawn #:nodoc:
9
- clone
11
+ @delegate_to_klass ? klass.all : clone
10
12
  end
11
13
 
12
14
  # Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
@@ -67,7 +69,7 @@ module ActiveRecord
67
69
  private
68
70
 
69
71
  def relation_with(values)
70
- result = Relation.create(klass, table, predicate_builder, values)
72
+ result = Relation.create(klass, values: values)
71
73
  result.extend(*extending_values) if extending_values.any?
72
74
  result
73
75
  end