activerecord 5.2.3.rc1 → 6.0.0.beta1

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 (240) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +326 -696
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +2 -1
  7. data/lib/active_record/aggregations.rb +4 -2
  8. data/lib/active_record/associations.rb +16 -12
  9. data/lib/active_record/associations/association.rb +35 -19
  10. data/lib/active_record/associations/association_scope.rb +4 -6
  11. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +14 -50
  14. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
  16. data/lib/active_record/associations/collection_association.rb +11 -25
  17. data/lib/active_record/associations/collection_proxy.rb +32 -6
  18. data/lib/active_record/associations/foreign_association.rb +7 -0
  19. data/lib/active_record/associations/has_many_association.rb +1 -1
  20. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  21. data/lib/active_record/associations/has_one_association.rb +28 -30
  22. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  23. data/lib/active_record/associations/join_dependency.rb +15 -20
  24. data/lib/active_record/associations/join_dependency/join_association.rb +6 -0
  25. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  26. data/lib/active_record/associations/preloader.rb +31 -28
  27. data/lib/active_record/associations/preloader/association.rb +1 -2
  28. data/lib/active_record/associations/singular_association.rb +2 -16
  29. data/lib/active_record/attribute_assignment.rb +7 -10
  30. data/lib/active_record/attribute_methods.rb +34 -56
  31. data/lib/active_record/attribute_methods/dirty.rb +64 -26
  32. data/lib/active_record/attribute_methods/primary_key.rb +8 -7
  33. data/lib/active_record/attribute_methods/read.rb +16 -48
  34. data/lib/active_record/attribute_methods/serialization.rb +1 -1
  35. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  36. data/lib/active_record/attribute_methods/write.rb +15 -16
  37. data/lib/active_record/autosave_association.rb +1 -1
  38. data/lib/active_record/base.rb +2 -2
  39. data/lib/active_record/callbacks.rb +3 -17
  40. data/lib/active_record/collection_cache_key.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +10 -14
  42. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  43. data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
  44. data/lib/active_record/connection_adapters/abstract/query_cache.rb +14 -11
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
  46. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
  47. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
  48. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +40 -26
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
  53. data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
  54. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
  55. data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
  56. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  57. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
  58. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
  59. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
  60. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
  61. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
  62. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  63. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  64. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
  65. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
  66. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
  67. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  68. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  69. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
  70. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
  71. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
  72. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
  73. data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
  74. data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
  75. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
  76. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
  77. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +93 -60
  78. data/lib/active_record/connection_handling.rb +132 -26
  79. data/lib/active_record/core.rb +76 -43
  80. data/lib/active_record/counter_cache.rb +4 -29
  81. data/lib/active_record/database_configurations.rb +184 -0
  82. data/lib/active_record/database_configurations/database_config.rb +37 -0
  83. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  84. data/lib/active_record/database_configurations/url_config.rb +74 -0
  85. data/lib/active_record/enum.rb +22 -7
  86. data/lib/active_record/errors.rb +24 -21
  87. data/lib/active_record/explain.rb +1 -1
  88. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  89. data/lib/active_record/fixture_set/render_context.rb +17 -0
  90. data/lib/active_record/fixture_set/table_row.rb +153 -0
  91. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  92. data/lib/active_record/fixtures.rb +140 -472
  93. data/lib/active_record/gem_version.rb +4 -4
  94. data/lib/active_record/inheritance.rb +12 -2
  95. data/lib/active_record/integration.rb +56 -16
  96. data/lib/active_record/internal_metadata.rb +5 -1
  97. data/lib/active_record/locking/optimistic.rb +2 -2
  98. data/lib/active_record/locking/pessimistic.rb +3 -3
  99. data/lib/active_record/log_subscriber.rb +7 -26
  100. data/lib/active_record/migration.rb +38 -37
  101. data/lib/active_record/migration/command_recorder.rb +35 -5
  102. data/lib/active_record/migration/compatibility.rb +34 -16
  103. data/lib/active_record/model_schema.rb +30 -9
  104. data/lib/active_record/nested_attributes.rb +2 -2
  105. data/lib/active_record/no_touching.rb +7 -0
  106. data/lib/active_record/persistence.rb +18 -7
  107. data/lib/active_record/query_cache.rb +11 -4
  108. data/lib/active_record/querying.rb +19 -11
  109. data/lib/active_record/railtie.rb +71 -42
  110. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  111. data/lib/active_record/railties/controller_runtime.rb +30 -35
  112. data/lib/active_record/railties/databases.rake +94 -43
  113. data/lib/active_record/reflection.rb +46 -34
  114. data/lib/active_record/relation.rb +150 -69
  115. data/lib/active_record/relation/batches.rb +13 -10
  116. data/lib/active_record/relation/calculations.rb +34 -23
  117. data/lib/active_record/relation/delegation.rb +4 -13
  118. data/lib/active_record/relation/finder_methods.rb +12 -25
  119. data/lib/active_record/relation/merger.rb +2 -6
  120. data/lib/active_record/relation/predicate_builder.rb +4 -6
  121. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  122. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  123. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  124. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  125. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  126. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  127. data/lib/active_record/relation/query_attribute.rb +15 -12
  128. data/lib/active_record/relation/query_methods.rb +26 -47
  129. data/lib/active_record/relation/where_clause.rb +4 -0
  130. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  131. data/lib/active_record/result.rb +30 -11
  132. data/lib/active_record/sanitization.rb +2 -39
  133. data/lib/active_record/schema.rb +1 -10
  134. data/lib/active_record/schema_dumper.rb +12 -6
  135. data/lib/active_record/schema_migration.rb +4 -0
  136. data/lib/active_record/scoping.rb +9 -8
  137. data/lib/active_record/scoping/default.rb +8 -1
  138. data/lib/active_record/scoping/named.rb +10 -14
  139. data/lib/active_record/statement_cache.rb +30 -3
  140. data/lib/active_record/store.rb +39 -8
  141. data/lib/active_record/table_metadata.rb +1 -4
  142. data/lib/active_record/tasks/database_tasks.rb +89 -23
  143. data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
  144. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
  145. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
  146. data/lib/active_record/test_databases.rb +38 -0
  147. data/lib/active_record/test_fixtures.rb +224 -0
  148. data/lib/active_record/timestamp.rb +4 -6
  149. data/lib/active_record/transactions.rb +2 -21
  150. data/lib/active_record/translation.rb +1 -1
  151. data/lib/active_record/type.rb +3 -4
  152. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  153. data/lib/active_record/type_caster/connection.rb +1 -6
  154. data/lib/active_record/type_caster/map.rb +1 -4
  155. data/lib/active_record/validations/uniqueness.rb +13 -25
  156. data/lib/arel.rb +44 -0
  157. data/lib/arel/alias_predication.rb +9 -0
  158. data/lib/arel/attributes.rb +22 -0
  159. data/lib/arel/attributes/attribute.rb +37 -0
  160. data/lib/arel/collectors/bind.rb +24 -0
  161. data/lib/arel/collectors/composite.rb +31 -0
  162. data/lib/arel/collectors/plain_string.rb +20 -0
  163. data/lib/arel/collectors/sql_string.rb +20 -0
  164. data/lib/arel/collectors/substitute_binds.rb +28 -0
  165. data/lib/arel/crud.rb +42 -0
  166. data/lib/arel/delete_manager.rb +18 -0
  167. data/lib/arel/errors.rb +9 -0
  168. data/lib/arel/expressions.rb +29 -0
  169. data/lib/arel/factory_methods.rb +49 -0
  170. data/lib/arel/insert_manager.rb +49 -0
  171. data/lib/arel/math.rb +45 -0
  172. data/lib/arel/nodes.rb +67 -0
  173. data/lib/arel/nodes/and.rb +32 -0
  174. data/lib/arel/nodes/ascending.rb +23 -0
  175. data/lib/arel/nodes/binary.rb +52 -0
  176. data/lib/arel/nodes/bind_param.rb +36 -0
  177. data/lib/arel/nodes/case.rb +55 -0
  178. data/lib/arel/nodes/casted.rb +50 -0
  179. data/lib/arel/nodes/count.rb +12 -0
  180. data/lib/arel/nodes/delete_statement.rb +45 -0
  181. data/lib/arel/nodes/descending.rb +23 -0
  182. data/lib/arel/nodes/equality.rb +18 -0
  183. data/lib/arel/nodes/extract.rb +24 -0
  184. data/lib/arel/nodes/false.rb +16 -0
  185. data/lib/arel/nodes/full_outer_join.rb +8 -0
  186. data/lib/arel/nodes/function.rb +44 -0
  187. data/lib/arel/nodes/grouping.rb +8 -0
  188. data/lib/arel/nodes/in.rb +8 -0
  189. data/lib/arel/nodes/infix_operation.rb +80 -0
  190. data/lib/arel/nodes/inner_join.rb +8 -0
  191. data/lib/arel/nodes/insert_statement.rb +37 -0
  192. data/lib/arel/nodes/join_source.rb +20 -0
  193. data/lib/arel/nodes/matches.rb +18 -0
  194. data/lib/arel/nodes/named_function.rb +23 -0
  195. data/lib/arel/nodes/node.rb +50 -0
  196. data/lib/arel/nodes/node_expression.rb +13 -0
  197. data/lib/arel/nodes/outer_join.rb +8 -0
  198. data/lib/arel/nodes/over.rb +15 -0
  199. data/lib/arel/nodes/regexp.rb +16 -0
  200. data/lib/arel/nodes/right_outer_join.rb +8 -0
  201. data/lib/arel/nodes/select_core.rb +63 -0
  202. data/lib/arel/nodes/select_statement.rb +41 -0
  203. data/lib/arel/nodes/sql_literal.rb +16 -0
  204. data/lib/arel/nodes/string_join.rb +11 -0
  205. data/lib/arel/nodes/table_alias.rb +27 -0
  206. data/lib/arel/nodes/terminal.rb +16 -0
  207. data/lib/arel/nodes/true.rb +16 -0
  208. data/lib/arel/nodes/unary.rb +44 -0
  209. data/lib/arel/nodes/unary_operation.rb +20 -0
  210. data/lib/arel/nodes/unqualified_column.rb +22 -0
  211. data/lib/arel/nodes/update_statement.rb +41 -0
  212. data/lib/arel/nodes/values.rb +16 -0
  213. data/lib/arel/nodes/values_list.rb +24 -0
  214. data/lib/arel/nodes/window.rb +126 -0
  215. data/lib/arel/nodes/with.rb +11 -0
  216. data/lib/arel/order_predications.rb +13 -0
  217. data/lib/arel/predications.rb +257 -0
  218. data/lib/arel/select_manager.rb +271 -0
  219. data/lib/arel/table.rb +110 -0
  220. data/lib/arel/tree_manager.rb +72 -0
  221. data/lib/arel/update_manager.rb +34 -0
  222. data/lib/arel/visitors.rb +20 -0
  223. data/lib/arel/visitors/depth_first.rb +199 -0
  224. data/lib/arel/visitors/dot.rb +292 -0
  225. data/lib/arel/visitors/ibm_db.rb +21 -0
  226. data/lib/arel/visitors/informix.rb +56 -0
  227. data/lib/arel/visitors/mssql.rb +143 -0
  228. data/lib/arel/visitors/mysql.rb +83 -0
  229. data/lib/arel/visitors/oracle.rb +159 -0
  230. data/lib/arel/visitors/oracle12.rb +67 -0
  231. data/lib/arel/visitors/postgresql.rb +116 -0
  232. data/lib/arel/visitors/sqlite.rb +39 -0
  233. data/lib/arel/visitors/to_sql.rb +913 -0
  234. data/lib/arel/visitors/visitor.rb +42 -0
  235. data/lib/arel/visitors/where_sql.rb +23 -0
  236. data/lib/arel/window_predications.rb +9 -0
  237. data/lib/rails/generators/active_record/migration.rb +14 -1
  238. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  239. data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
  240. metadata +101 -23
@@ -251,25 +251,28 @@ module ActiveRecord
251
251
  end
252
252
  end
253
253
 
254
- attr = Relation::QueryAttribute.new(primary_key, primary_key_offset, klass.type_for_attribute(primary_key))
255
- batch_relation = relation.where(arel_attribute(primary_key).gt(Arel::Nodes::BindParam.new(attr)))
254
+ batch_relation = relation.where(
255
+ bind_attribute(primary_key, primary_key_offset) { |attr, bind| attr.gt(bind) }
256
+ )
256
257
  end
257
258
  end
258
259
 
259
260
  private
260
261
 
261
262
  def apply_limits(relation, start, finish)
262
- if start
263
- attr = Relation::QueryAttribute.new(primary_key, start, klass.type_for_attribute(primary_key))
264
- relation = relation.where(arel_attribute(primary_key).gteq(Arel::Nodes::BindParam.new(attr)))
265
- end
266
- if finish
267
- attr = Relation::QueryAttribute.new(primary_key, finish, klass.type_for_attribute(primary_key))
268
- relation = relation.where(arel_attribute(primary_key).lteq(Arel::Nodes::BindParam.new(attr)))
269
- end
263
+ relation = apply_start_limit(relation, start) if start
264
+ relation = apply_finish_limit(relation, finish) if finish
270
265
  relation
271
266
  end
272
267
 
268
+ def apply_start_limit(relation, start)
269
+ relation.where(bind_attribute(primary_key, start) { |attr, bind| attr.gteq(bind) })
270
+ end
271
+
272
+ def apply_finish_limit(relation, finish)
273
+ relation.where(bind_attribute(primary_key, finish) { |attr, bind| attr.lteq(bind) })
274
+ end
275
+
273
276
  def batch_order
274
277
  arel_attribute(primary_key).asc
275
278
  end
@@ -41,15 +41,13 @@ module ActiveRecord
41
41
  def count(column_name = nil)
42
42
  if block_given?
43
43
  unless column_name.nil?
44
- ActiveSupport::Deprecation.warn \
45
- "When `count' is called with a block, it ignores other arguments. " \
46
- "This behavior is now deprecated and will result in an ArgumentError in Rails 6.0."
44
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
47
45
  end
48
46
 
49
- return super()
47
+ super()
48
+ else
49
+ calculate(:count, column_name)
50
50
  end
51
-
52
- calculate(:count, column_name)
53
51
  end
54
52
 
55
53
  # Calculates the average value on a given column. Returns +nil+ if there's
@@ -86,15 +84,13 @@ module ActiveRecord
86
84
  def sum(column_name = nil)
87
85
  if block_given?
88
86
  unless column_name.nil?
89
- ActiveSupport::Deprecation.warn \
90
- "When `sum' is called with a block, it ignores other arguments. " \
91
- "This behavior is now deprecated and will result in an ArgumentError in Rails 6.0."
87
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
92
88
  end
93
89
 
94
- return super()
90
+ super()
91
+ else
92
+ calculate(:sum, column_name)
95
93
  end
96
-
97
- calculate(:sum, column_name)
98
94
  end
99
95
 
100
96
  # This calculates aggregate values in the given column. Methods for #count, #sum, #average,
@@ -190,14 +186,34 @@ module ActiveRecord
190
186
  relation = apply_join_dependency
191
187
  relation.pluck(*column_names)
192
188
  else
193
- klass.enforce_raw_sql_whitelist(column_names)
189
+ disallow_raw_sql!(column_names)
194
190
  relation = spawn
195
- relation.select_values = column_names
191
+ relation.select_values = column_names.map { |cn|
192
+ @klass.has_attribute?(cn) || @klass.attribute_alias?(cn) ? arel_attribute(cn) : cn
193
+ }
196
194
  result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) }
197
195
  result.cast_values(klass.attribute_types)
198
196
  end
199
197
  end
200
198
 
199
+ # Pick the value(s) from the named column(s) in the current relation.
200
+ # This is short-hand for <tt>relation.limit(1).pluck(*column_names).first</tt>, and is primarily useful
201
+ # when you have a relation that's already narrowed down to a single row.
202
+ #
203
+ # Just like #pluck, #pick will only load the actual value, not the entire record object, so it's also
204
+ # more efficient. The value is, again like with pluck, typecast by the column type.
205
+ #
206
+ # Person.where(id: 1).pick(:name)
207
+ # # SELECT people.name FROM people WHERE id = 1 LIMIT 1
208
+ # # => 'David'
209
+ #
210
+ # Person.where(id: 1).pick(:name, :email_address)
211
+ # # SELECT people.name, people.email_address FROM people WHERE id = 1 LIMIT 1
212
+ # # => [ 'David', 'david@loudthinking.com' ]
213
+ def pick(*column_names)
214
+ limit(1).pluck(*column_names).first
215
+ end
216
+
201
217
  # Pluck all the ID's for the relation using the table's primary key
202
218
  #
203
219
  # Person.ids # SELECT people.id FROM people
@@ -207,6 +223,7 @@ module ActiveRecord
207
223
  end
208
224
 
209
225
  private
226
+
210
227
  def has_include?(column_name)
211
228
  eager_loading? || (includes_values.present? && column_name && column_name != :all)
212
229
  end
@@ -221,12 +238,10 @@ module ActiveRecord
221
238
  if operation == "count"
222
239
  column_name ||= select_for_count
223
240
  if column_name == :all
224
- if !distinct
225
- distinct = distinct_select?(select_for_count) if group_values.empty?
226
- elsif group_values.any? || select_values.empty? && order_values.empty?
241
+ if distinct && (group_values.any? || select_values.empty? && order_values.empty?)
227
242
  column_name = primary_key
228
243
  end
229
- elsif distinct_select?(column_name)
244
+ elsif column_name.is_a?(::String) && /\bDISTINCT[\s(]/i.match?(column_name)
230
245
  distinct = nil
231
246
  end
232
247
  end
@@ -238,10 +253,6 @@ module ActiveRecord
238
253
  end
239
254
  end
240
255
 
241
- def distinct_select?(column_name)
242
- column_name.is_a?(::String) && /\bDISTINCT[\s(]/i.match?(column_name)
243
- end
244
-
245
256
  def aggregate_column(column_name)
246
257
  return column_name if Arel::Expressions === column_name
247
258
 
@@ -386,7 +397,7 @@ module ActiveRecord
386
397
  case operation
387
398
  when "count" then value.to_i
388
399
  when "sum" then type.deserialize(value || 0)
389
- when "average" then value && value.respond_to?(:to_d) ? value.to_d : value
400
+ when "average" then value&.respond_to?(:to_d) ? value.to_d : value
390
401
  else type.deserialize(value)
391
402
  end
392
403
  end
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  include ClassSpecificRelation
19
19
  }
20
20
  include_relation_methods(delegate)
21
- mangled_name = klass.name.gsub("::".freeze, "_".freeze)
21
+ mangled_name = klass.name.gsub("::", "_")
22
22
  const_set mangled_name, delegate
23
23
  private_constant mangled_name
24
24
 
@@ -33,7 +33,7 @@ module ActiveRecord
33
33
 
34
34
  protected
35
35
  def include_relation_methods(delegate)
36
- superclass.include_relation_methods(delegate) unless base_class == self
36
+ superclass.include_relation_methods(delegate) unless base_class?
37
37
  delegate.include generated_relation_methods
38
38
  end
39
39
 
@@ -54,7 +54,7 @@ module ActiveRecord
54
54
  end
55
55
  RUBY
56
56
  else
57
- generated_relation_methods.send(:define_method, method) do |*args, &block|
57
+ generated_relation_methods.define_method(method) do |*args, &block|
58
58
  scoping { klass.public_send(method, *args, &block) }
59
59
  end
60
60
  end
@@ -68,7 +68,7 @@ module ActiveRecord
68
68
  # may vary depending on the klass of a relation, so we create a subclass of Relation
69
69
  # for each different klass, and the delegations are compiled into that subclass only.
70
70
 
71
- delegate :to_xml, :encode_with, :length, :each, :uniq, :join,
71
+ delegate :to_xml, :encode_with, :length, :each, :join,
72
72
  :[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
73
73
  :to_sentence, :to_formatted_s, :as_json,
74
74
  :shuffle, :split, :slice, :index, :rindex, to: :records
@@ -112,15 +112,6 @@ module ActiveRecord
112
112
  if @klass.respond_to?(method)
113
113
  self.class.delegate_to_scoped_klass(method)
114
114
  scoping { @klass.public_send(method, *args, &block) }
115
- elsif @delegate_to_klass && @klass.respond_to?(method, true)
116
- ActiveSupport::Deprecation.warn \
117
- "Delegating missing #{method} method to #{@klass}. " \
118
- "Accessibility of private/protected class methods in :scope is deprecated and will be removed in Rails 6.0."
119
- @klass.send(method, *args, &block)
120
- elsif arel.respond_to?(method)
121
- ActiveSupport::Deprecation.warn \
122
- "Delegating #{method} to arel is deprecated and will be removed in Rails 6.0."
123
- arel.public_send(method, *args, &block)
124
115
  else
125
116
  super
126
117
  end
@@ -79,17 +79,12 @@ module ActiveRecord
79
79
  # Post.find_by "published_at < ?", 2.weeks.ago
80
80
  def find_by(arg, *args)
81
81
  where(arg, *args).take
82
- rescue ::RangeError
83
- nil
84
82
  end
85
83
 
86
84
  # Like #find_by, except that if no record is found, raises
87
85
  # an ActiveRecord::RecordNotFound error.
88
86
  def find_by!(arg, *args)
89
87
  where(arg, *args).take!
90
- rescue ::RangeError
91
- raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value",
92
- @klass.name, @klass.primary_key)
93
88
  end
94
89
 
95
90
  # Gives a record (or N records if a parameter is supplied) without any implied
@@ -312,6 +307,8 @@ module ActiveRecord
312
307
 
313
308
  return false if !conditions || limit_value == 0
314
309
 
310
+ conditions = sanitize_forbidden_attributes(conditions)
311
+
315
312
  if eager_loading?
316
313
  relation = apply_join_dependency(eager_loading: false)
317
314
  return relation.exists?(conditions)
@@ -319,9 +316,7 @@ module ActiveRecord
319
316
 
320
317
  relation = construct_relation_for_exists(conditions)
321
318
 
322
- skip_query_cache_if_necessary { connection.select_one(relation.arel, "#{name} Exists") } ? true : false
323
- rescue ::RangeError
324
- false
319
+ skip_query_cache_if_necessary { connection.select_value(relation.arel, "#{name} Exists") } ? true : false
325
320
  end
326
321
 
327
322
  # This method is called whenever no records are found with either a single
@@ -338,14 +333,14 @@ module ActiveRecord
338
333
  name = @klass.name
339
334
 
340
335
  if ids.nil?
341
- error = "Couldn't find #{name}".dup
336
+ error = +"Couldn't find #{name}"
342
337
  error << " with#{conditions}" if conditions
343
338
  raise RecordNotFound.new(error, name, key)
344
339
  elsif Array(ids).size == 1
345
340
  error = "Couldn't find #{name} with '#{key}'=#{ids}#{conditions}"
346
341
  raise RecordNotFound.new(error, name, key, ids)
347
342
  else
348
- error = "Couldn't find all #{name.pluralize} with '#{key}': ".dup
343
+ error = +"Couldn't find all #{name.pluralize} with '#{key}': "
349
344
  error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})."
350
345
  error << " Couldn't find #{name.pluralize(not_found_ids.size)} with #{key.to_s.pluralize(not_found_ids.size)} #{not_found_ids.join(', ')}." if not_found_ids
351
346
  raise RecordNotFound.new(error, name, key, ids)
@@ -359,11 +354,7 @@ module ActiveRecord
359
354
  end
360
355
 
361
356
  def construct_relation_for_exists(conditions)
362
- if distinct_value && offset_value
363
- relation = limit(1)
364
- else
365
- relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
366
- end
357
+ relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
367
358
 
368
359
  case conditions
369
360
  when Array, Hash
@@ -375,15 +366,14 @@ module ActiveRecord
375
366
  relation
376
367
  end
377
368
 
378
- def construct_join_dependency
379
- including = eager_load_values + includes_values
369
+ def construct_join_dependency(associations)
380
370
  ActiveRecord::Associations::JoinDependency.new(
381
- klass, table, including
371
+ klass, table, associations
382
372
  )
383
373
  end
384
374
 
385
375
  def apply_join_dependency(eager_loading: group_values.empty?)
386
- join_dependency = construct_join_dependency
376
+ join_dependency = construct_join_dependency(eager_load_values + includes_values)
387
377
  relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
388
378
 
389
379
  if eager_loading && !using_limitable_reflections?(join_dependency.reflections)
@@ -403,7 +393,7 @@ module ActiveRecord
403
393
 
404
394
  def limited_ids_for(relation)
405
395
  values = @klass.connection.columns_for_distinct(
406
- connection.column_name_from_arel_node(arel_attribute(primary_key)),
396
+ connection.visitor.compile(arel_attribute(primary_key)),
407
397
  relation.order_values
408
398
  )
409
399
 
@@ -437,9 +427,6 @@ module ActiveRecord
437
427
  else
438
428
  find_some(ids)
439
429
  end
440
- rescue ::RangeError
441
- error_message = "Couldn't find #{model_name} with an out of range ID"
442
- raise RecordNotFound.new(error_message, model_name, primary_key, ids)
443
430
  end
444
431
 
445
432
  def find_one(id)
@@ -555,8 +542,8 @@ module ActiveRecord
555
542
  end
556
543
 
557
544
  def ordered_relation
558
- if order_values.empty? && primary_key
559
- order(arel_attribute(primary_key).asc)
545
+ if order_values.empty? && (implicit_order_column || primary_key)
546
+ order(arel_attribute(implicit_order_column || primary_key).asc)
560
547
  else
561
548
  self
562
549
  end
@@ -120,9 +120,7 @@ module ActiveRecord
120
120
  joins_dependency = other.joins_values.map do |join|
121
121
  case join
122
122
  when Hash, Symbol, Array
123
- ActiveRecord::Associations::JoinDependency.new(
124
- other.klass, other.table, join
125
- )
123
+ other.send(:construct_join_dependency, join)
126
124
  else
127
125
  join
128
126
  end
@@ -141,9 +139,7 @@ module ActiveRecord
141
139
  joins_dependency = other.left_outer_joins_values.map do |join|
142
140
  case join
143
141
  when Hash, Symbol, Array
144
- ActiveRecord::Associations::JoinDependency.new(
145
- other.klass, other.table, join
146
- )
142
+ other.send(:construct_join_dependency, join)
147
143
  else
148
144
  join
149
145
  end
@@ -27,7 +27,7 @@ module ActiveRecord
27
27
  key
28
28
  else
29
29
  key = key.to_s
30
- key.split(".".freeze).first if key.include?(".".freeze)
30
+ key.split(".").first if key.include?(".")
31
31
  end
32
32
  end.compact
33
33
  end
@@ -62,9 +62,6 @@ module ActiveRecord
62
62
  end
63
63
 
64
64
  protected
65
-
66
- attr_reader :table
67
-
68
65
  def expand_from_hash(attributes)
69
66
  return ["1=0"] if attributes.empty?
70
67
 
@@ -115,6 +112,7 @@ module ActiveRecord
115
112
  end
116
113
 
117
114
  private
115
+ attr_reader :table
118
116
 
119
117
  def associated_predicate_builder(association_name)
120
118
  self.class.new(table.associated_table(association_name))
@@ -122,11 +120,11 @@ module ActiveRecord
122
120
 
123
121
  def convert_dot_notation_to_hash(attributes)
124
122
  dot_notation = attributes.select do |k, v|
125
- k.include?(".".freeze) && !v.is_a?(Hash)
123
+ k.include?(".") && !v.is_a?(Hash)
126
124
  end
127
125
 
128
126
  dot_notation.each_key do |key|
129
- table_name, column_name = key.split(".".freeze)
127
+ table_name, column_name = key.split(".")
130
128
  value = attributes.delete(key)
131
129
  attributes[table_name] ||= {}
132
130
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/array/extract"
4
+
3
5
  module ActiveRecord
4
6
  class PredicateBuilder
5
7
  class ArrayHandler # :nodoc:
@@ -11,8 +13,8 @@ module ActiveRecord
11
13
  return attribute.in([]) if value.empty?
12
14
 
13
15
  values = value.map { |x| x.is_a?(Base) ? x.id : x }
14
- nils, values = values.partition(&:nil?)
15
- ranges, values = values.partition { |v| v.is_a?(Range) }
16
+ nils = values.extract!(&:nil?)
17
+ ranges = values.extract! { |v| v.is_a?(Range) }
16
18
 
17
19
  values_predicate =
18
20
  case values.length
@@ -34,8 +36,7 @@ module ActiveRecord
34
36
  array_predicates.inject(&:or)
35
37
  end
36
38
 
37
- protected
38
-
39
+ private
39
40
  attr_reader :predicate_builder
40
41
 
41
42
  module NullPredicate # :nodoc:
@@ -12,12 +12,9 @@ module ActiveRecord
12
12
  [associated_table.association_join_foreign_key.to_s => ids]
13
13
  end
14
14
 
15
- # TODO Change this to private once we've dropped Ruby 2.2 support.
16
- # Workaround for Ruby 2.2 "private attribute?" warning.
17
- protected
15
+ private
18
16
  attr_reader :associated_table, :value
19
17
 
20
- private
21
18
  def ids
22
19
  case value
23
20
  when Relation
@@ -11,8 +11,7 @@ module ActiveRecord
11
11
  predicate_builder.build(attribute, value.id)
12
12
  end
13
13
 
14
- protected
15
-
14
+ private
16
15
  attr_reader :predicate_builder
17
16
  end
18
17
  end
@@ -12,8 +12,7 @@ module ActiveRecord
12
12
  attribute.eq(bind)
13
13
  end
14
14
 
15
- protected
16
-
15
+ private
17
16
  attr_reader :predicate_builder
18
17
  end
19
18
  end
@@ -17,12 +17,9 @@ module ActiveRecord
17
17
  end
18
18
  end
19
19
 
20
- # TODO Change this to private once we've dropped Ruby 2.2 support.
21
- # Workaround for Ruby 2.2 "private attribute?" warning.
22
- protected
20
+ private
23
21
  attr_reader :associated_table, :values
24
22
 
25
- private
26
23
  def type_to_ids_mapping
27
24
  default_hash = Hash.new { |hsh, key| hsh[key] = [] }
28
25
  values.each_with_object(default_hash) do |value, hash|