activerecord 5.2.6 → 6.0.5

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 (294) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +928 -559
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +5 -3
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/advisory_lock_base.rb +18 -0
  7. data/lib/active_record/aggregations.rb +4 -3
  8. data/lib/active_record/association_relation.rb +10 -8
  9. data/lib/active_record/associations/alias_tracker.rb +0 -1
  10. data/lib/active_record/associations/association.rb +55 -19
  11. data/lib/active_record/associations/association_scope.rb +11 -7
  12. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  14. data/lib/active_record/associations/builder/association.rb +14 -18
  15. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  16. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +35 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +19 -23
  22. data/lib/active_record/associations/collection_proxy.rb +14 -17
  23. data/lib/active_record/associations/foreign_association.rb +7 -0
  24. data/lib/active_record/associations/has_many_association.rb +2 -11
  25. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  26. data/lib/active_record/associations/has_one_association.rb +28 -30
  27. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  28. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  29. data/lib/active_record/associations/join_dependency/join_part.rb +4 -4
  30. data/lib/active_record/associations/join_dependency.rb +47 -30
  31. data/lib/active_record/associations/preloader/association.rb +61 -41
  32. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  33. data/lib/active_record/associations/preloader.rb +44 -33
  34. data/lib/active_record/associations/singular_association.rb +2 -16
  35. data/lib/active_record/associations/through_association.rb +1 -1
  36. data/lib/active_record/associations.rb +21 -16
  37. data/lib/active_record/attribute_assignment.rb +7 -11
  38. data/lib/active_record/attribute_decorators.rb +0 -2
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
  40. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  41. data/lib/active_record/attribute_methods/primary_key.rb +15 -24
  42. data/lib/active_record/attribute_methods/query.rb +2 -3
  43. data/lib/active_record/attribute_methods/read.rb +15 -54
  44. data/lib/active_record/attribute_methods/serialization.rb +1 -2
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
  46. data/lib/active_record/attribute_methods/write.rb +17 -25
  47. data/lib/active_record/attribute_methods.rb +28 -100
  48. data/lib/active_record/attributes.rb +13 -1
  49. data/lib/active_record/autosave_association.rb +12 -14
  50. data/lib/active_record/base.rb +2 -3
  51. data/lib/active_record/callbacks.rb +6 -21
  52. data/lib/active_record/coders/yaml_column.rb +0 -1
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +109 -18
  54. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
  55. data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
  56. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
  57. data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
  58. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +105 -72
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -43
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -217
  65. data/lib/active_record/connection_adapters/column.rb +17 -13
  66. data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
  67. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
  68. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
  70. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  71. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
  73. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  74. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  75. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
  76. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +8 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  89. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
  98. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
  101. data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
  102. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  103. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  104. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +137 -147
  107. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  108. data/lib/active_record/connection_handling.rb +139 -26
  109. data/lib/active_record/core.rb +107 -66
  110. data/lib/active_record/counter_cache.rb +8 -30
  111. data/lib/active_record/database_configurations/database_config.rb +37 -0
  112. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  113. data/lib/active_record/database_configurations/url_config.rb +78 -0
  114. data/lib/active_record/database_configurations.rb +233 -0
  115. data/lib/active_record/dynamic_matchers.rb +3 -4
  116. data/lib/active_record/enum.rb +44 -7
  117. data/lib/active_record/errors.rb +15 -7
  118. data/lib/active_record/explain.rb +1 -2
  119. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  120. data/lib/active_record/fixture_set/render_context.rb +17 -0
  121. data/lib/active_record/fixture_set/table_row.rb +152 -0
  122. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  123. data/lib/active_record/fixtures.rb +144 -474
  124. data/lib/active_record/gem_version.rb +3 -3
  125. data/lib/active_record/inheritance.rb +13 -6
  126. data/lib/active_record/insert_all.rb +179 -0
  127. data/lib/active_record/integration.rb +68 -16
  128. data/lib/active_record/internal_metadata.rb +11 -3
  129. data/lib/active_record/locking/optimistic.rb +14 -7
  130. data/lib/active_record/locking/pessimistic.rb +3 -3
  131. data/lib/active_record/log_subscriber.rb +8 -27
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  133. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  134. data/lib/active_record/middleware/database_selector.rb +74 -0
  135. data/lib/active_record/migration/command_recorder.rb +54 -22
  136. data/lib/active_record/migration/compatibility.rb +79 -52
  137. data/lib/active_record/migration/join_table.rb +0 -1
  138. data/lib/active_record/migration.rb +104 -85
  139. data/lib/active_record/model_schema.rb +62 -11
  140. data/lib/active_record/nested_attributes.rb +2 -4
  141. data/lib/active_record/no_touching.rb +9 -2
  142. data/lib/active_record/null_relation.rb +0 -1
  143. data/lib/active_record/persistence.rb +232 -29
  144. data/lib/active_record/query_cache.rb +11 -4
  145. data/lib/active_record/querying.rb +33 -21
  146. data/lib/active_record/railtie.rb +80 -43
  147. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  148. data/lib/active_record/railties/controller_runtime.rb +30 -35
  149. data/lib/active_record/railties/databases.rake +199 -46
  150. data/lib/active_record/reflection.rb +51 -51
  151. data/lib/active_record/relation/batches.rb +13 -11
  152. data/lib/active_record/relation/calculations.rb +55 -49
  153. data/lib/active_record/relation/delegation.rb +35 -50
  154. data/lib/active_record/relation/finder_methods.rb +23 -28
  155. data/lib/active_record/relation/from_clause.rb +4 -0
  156. data/lib/active_record/relation/merger.rb +12 -17
  157. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  158. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  159. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  160. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  161. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  162. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  163. data/lib/active_record/relation/predicate_builder.rb +5 -11
  164. data/lib/active_record/relation/query_attribute.rb +13 -8
  165. data/lib/active_record/relation/query_methods.rb +232 -69
  166. data/lib/active_record/relation/spawn_methods.rb +1 -2
  167. data/lib/active_record/relation/where_clause.rb +14 -11
  168. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  169. data/lib/active_record/relation.rb +326 -81
  170. data/lib/active_record/result.rb +30 -12
  171. data/lib/active_record/sanitization.rb +32 -40
  172. data/lib/active_record/schema.rb +2 -11
  173. data/lib/active_record/schema_dumper.rb +22 -7
  174. data/lib/active_record/schema_migration.rb +6 -2
  175. data/lib/active_record/scoping/default.rb +4 -6
  176. data/lib/active_record/scoping/named.rb +25 -16
  177. data/lib/active_record/scoping.rb +8 -9
  178. data/lib/active_record/statement_cache.rb +30 -3
  179. data/lib/active_record/store.rb +87 -8
  180. data/lib/active_record/suppressor.rb +2 -2
  181. data/lib/active_record/table_metadata.rb +23 -15
  182. data/lib/active_record/tasks/database_tasks.rb +194 -25
  183. data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
  184. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
  185. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
  186. data/lib/active_record/test_databases.rb +23 -0
  187. data/lib/active_record/test_fixtures.rb +243 -0
  188. data/lib/active_record/timestamp.rb +39 -26
  189. data/lib/active_record/touch_later.rb +5 -4
  190. data/lib/active_record/transactions.rb +64 -73
  191. data/lib/active_record/translation.rb +1 -1
  192. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  193. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  194. data/lib/active_record/type/serialized.rb +0 -1
  195. data/lib/active_record/type/time.rb +10 -0
  196. data/lib/active_record/type/type_map.rb +0 -1
  197. data/lib/active_record/type/unsigned_integer.rb +0 -1
  198. data/lib/active_record/type.rb +3 -5
  199. data/lib/active_record/type_caster/connection.rb +15 -14
  200. data/lib/active_record/type_caster/map.rb +1 -4
  201. data/lib/active_record/validations/associated.rb +0 -1
  202. data/lib/active_record/validations/uniqueness.rb +15 -27
  203. data/lib/active_record/validations.rb +3 -3
  204. data/lib/active_record.rb +10 -2
  205. data/lib/arel/alias_predication.rb +9 -0
  206. data/lib/arel/attributes/attribute.rb +37 -0
  207. data/lib/arel/attributes.rb +22 -0
  208. data/lib/arel/collectors/bind.rb +24 -0
  209. data/lib/arel/collectors/composite.rb +31 -0
  210. data/lib/arel/collectors/plain_string.rb +20 -0
  211. data/lib/arel/collectors/sql_string.rb +20 -0
  212. data/lib/arel/collectors/substitute_binds.rb +28 -0
  213. data/lib/arel/crud.rb +42 -0
  214. data/lib/arel/delete_manager.rb +18 -0
  215. data/lib/arel/errors.rb +9 -0
  216. data/lib/arel/expressions.rb +29 -0
  217. data/lib/arel/factory_methods.rb +49 -0
  218. data/lib/arel/insert_manager.rb +49 -0
  219. data/lib/arel/math.rb +45 -0
  220. data/lib/arel/nodes/and.rb +32 -0
  221. data/lib/arel/nodes/ascending.rb +23 -0
  222. data/lib/arel/nodes/binary.rb +52 -0
  223. data/lib/arel/nodes/bind_param.rb +36 -0
  224. data/lib/arel/nodes/case.rb +55 -0
  225. data/lib/arel/nodes/casted.rb +50 -0
  226. data/lib/arel/nodes/comment.rb +29 -0
  227. data/lib/arel/nodes/count.rb +12 -0
  228. data/lib/arel/nodes/delete_statement.rb +45 -0
  229. data/lib/arel/nodes/descending.rb +23 -0
  230. data/lib/arel/nodes/equality.rb +18 -0
  231. data/lib/arel/nodes/extract.rb +24 -0
  232. data/lib/arel/nodes/false.rb +16 -0
  233. data/lib/arel/nodes/full_outer_join.rb +8 -0
  234. data/lib/arel/nodes/function.rb +44 -0
  235. data/lib/arel/nodes/grouping.rb +8 -0
  236. data/lib/arel/nodes/in.rb +8 -0
  237. data/lib/arel/nodes/infix_operation.rb +80 -0
  238. data/lib/arel/nodes/inner_join.rb +8 -0
  239. data/lib/arel/nodes/insert_statement.rb +37 -0
  240. data/lib/arel/nodes/join_source.rb +20 -0
  241. data/lib/arel/nodes/matches.rb +18 -0
  242. data/lib/arel/nodes/named_function.rb +23 -0
  243. data/lib/arel/nodes/node.rb +50 -0
  244. data/lib/arel/nodes/node_expression.rb +13 -0
  245. data/lib/arel/nodes/outer_join.rb +8 -0
  246. data/lib/arel/nodes/over.rb +15 -0
  247. data/lib/arel/nodes/regexp.rb +16 -0
  248. data/lib/arel/nodes/right_outer_join.rb +8 -0
  249. data/lib/arel/nodes/select_core.rb +67 -0
  250. data/lib/arel/nodes/select_statement.rb +41 -0
  251. data/lib/arel/nodes/sql_literal.rb +16 -0
  252. data/lib/arel/nodes/string_join.rb +11 -0
  253. data/lib/arel/nodes/table_alias.rb +27 -0
  254. data/lib/arel/nodes/terminal.rb +16 -0
  255. data/lib/arel/nodes/true.rb +16 -0
  256. data/lib/arel/nodes/unary.rb +45 -0
  257. data/lib/arel/nodes/unary_operation.rb +20 -0
  258. data/lib/arel/nodes/unqualified_column.rb +22 -0
  259. data/lib/arel/nodes/update_statement.rb +41 -0
  260. data/lib/arel/nodes/values_list.rb +9 -0
  261. data/lib/arel/nodes/window.rb +126 -0
  262. data/lib/arel/nodes/with.rb +11 -0
  263. data/lib/arel/nodes.rb +68 -0
  264. data/lib/arel/order_predications.rb +13 -0
  265. data/lib/arel/predications.rb +256 -0
  266. data/lib/arel/select_manager.rb +271 -0
  267. data/lib/arel/table.rb +110 -0
  268. data/lib/arel/tree_manager.rb +72 -0
  269. data/lib/arel/update_manager.rb +34 -0
  270. data/lib/arel/visitors/depth_first.rb +203 -0
  271. data/lib/arel/visitors/dot.rb +296 -0
  272. data/lib/arel/visitors/ibm_db.rb +34 -0
  273. data/lib/arel/visitors/informix.rb +62 -0
  274. data/lib/arel/visitors/mssql.rb +156 -0
  275. data/lib/arel/visitors/mysql.rb +83 -0
  276. data/lib/arel/visitors/oracle.rb +158 -0
  277. data/lib/arel/visitors/oracle12.rb +65 -0
  278. data/lib/arel/visitors/postgresql.rb +109 -0
  279. data/lib/arel/visitors/sqlite.rb +38 -0
  280. data/lib/arel/visitors/to_sql.rb +888 -0
  281. data/lib/arel/visitors/visitor.rb +45 -0
  282. data/lib/arel/visitors/where_sql.rb +22 -0
  283. data/lib/arel/visitors.rb +20 -0
  284. data/lib/arel/window_predications.rb +9 -0
  285. data/lib/arel.rb +62 -0
  286. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  287. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  288. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  289. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  290. data/lib/rails/generators/active_record/migration.rb +14 -2
  291. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  292. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  293. metadata +116 -29
  294. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -70,7 +70,15 @@ module ActiveRecord
70
70
  predicates == other.predicates
71
71
  end
72
72
 
73
- def invert
73
+ def invert(as = :nand)
74
+ if predicates.size == 1
75
+ inverted_predicates = [ invert_predicate(predicates.first) ]
76
+ elsif as == :nor
77
+ inverted_predicates = predicates.map { |node| invert_predicate(node) }
78
+ else
79
+ inverted_predicates = [ Arel::Nodes::Not.new(ast) ]
80
+ end
81
+
74
82
  WhereClause.new(inverted_predicates)
75
83
  end
76
84
 
@@ -79,7 +87,6 @@ module ActiveRecord
79
87
  end
80
88
 
81
89
  protected
82
-
83
90
  attr_reader :predicates
84
91
 
85
92
  def referenced_columns
@@ -115,16 +122,16 @@ module ActiveRecord
115
122
  node.respond_to?(:operator) && node.operator == :==
116
123
  end
117
124
 
118
- def inverted_predicates
119
- predicates.map { |node| invert_predicate(node) }
120
- end
121
-
122
125
  def invert_predicate(node)
123
126
  case node
124
127
  when NilClass
125
128
  raise ArgumentError, "Invalid argument for .where.not(), got nil."
126
129
  when Arel::Nodes::In
127
130
  Arel::Nodes::NotIn.new(node.left, node.right)
131
+ when Arel::Nodes::IsNotDistinctFrom
132
+ Arel::Nodes::IsDistinctFrom.new(node.left, node.right)
133
+ when Arel::Nodes::IsDistinctFrom
134
+ Arel::Nodes::IsNotDistinctFrom.new(node.left, node.right)
128
135
  when Arel::Nodes::Equality
129
136
  Arel::Nodes::NotEqual.new(node.left, node.right)
130
137
  when String
@@ -136,11 +143,7 @@ module ActiveRecord
136
143
 
137
144
  def except_predicates(columns)
138
145
  predicates.reject do |node|
139
- case node
140
- when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
141
- subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
142
- columns.include?(subrelation.name.to_s)
143
- end
146
+ Arel.fetch_attribute(node) { |attr| columns.include?(attr.name.to_s) }
144
147
  end
145
148
  end
146
149
 
@@ -26,8 +26,7 @@ module ActiveRecord
26
26
  WhereClause.new(parts)
27
27
  end
28
28
 
29
- protected
30
-
29
+ private
31
30
  attr_reader :klass, :predicate_builder
32
31
  end
33
32
  end
@@ -5,10 +5,11 @@ module ActiveRecord
5
5
  class Relation
6
6
  MULTI_VALUE_METHODS = [:includes, :eager_load, :preload, :select, :group,
7
7
  :order, :joins, :left_outer_joins, :references,
8
- :extending, :unscope]
8
+ :extending, :unscope, :optimizer_hints, :annotate]
9
9
 
10
10
  SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering,
11
11
  :reverse_order, :distinct, :create_with, :skip_query_cache]
12
+
12
13
  CLAUSE_METHODS = [:where, :having, :from]
13
14
  INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :group, :having]
14
15
 
@@ -18,6 +19,7 @@ module ActiveRecord
18
19
  include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation
19
20
 
20
21
  attr_reader :table, :klass, :loaded, :predicate_builder
22
+ attr_accessor :skip_preloading_value
21
23
  alias :model :klass
22
24
  alias :loaded? :loaded
23
25
  alias :locked? :lock_value
@@ -41,6 +43,17 @@ module ActiveRecord
41
43
  klass.arel_attribute(name, table)
42
44
  end
43
45
 
46
+ def bind_attribute(name, value) # :nodoc:
47
+ if reflection = klass._reflect_on_association(name)
48
+ name = reflection.foreign_key
49
+ value = value.read_attribute(reflection.klass.primary_key) unless value.nil?
50
+ end
51
+
52
+ attr = arel_attribute(name)
53
+ bind = predicate_builder.build_bind_attribute(attr.name, value)
54
+ yield attr, bind
55
+ end
56
+
44
57
  # Initializes new record from relation while maintaining the current
45
58
  # scope.
46
59
  #
@@ -54,7 +67,8 @@ module ActiveRecord
54
67
  # user = users.new { |user| user.name = 'Oscar' }
55
68
  # user.name # => Oscar
56
69
  def new(attributes = nil, &block)
57
- scoping { klass.new(values_for_create(attributes), &block) }
70
+ block = _deprecated_scope_block("new", &block)
71
+ scoping { klass.new(attributes, &block) }
58
72
  end
59
73
 
60
74
  alias build new
@@ -82,7 +96,8 @@ module ActiveRecord
82
96
  if attributes.is_a?(Array)
83
97
  attributes.collect { |attr| create(attr, &block) }
84
98
  else
85
- scoping { klass.create(values_for_create(attributes), &block) }
99
+ block = _deprecated_scope_block("create", &block)
100
+ scoping { klass.create(attributes, &block) }
86
101
  end
87
102
  end
88
103
 
@@ -96,7 +111,8 @@ module ActiveRecord
96
111
  if attributes.is_a?(Array)
97
112
  attributes.collect { |attr| create!(attr, &block) }
98
113
  else
99
- scoping { klass.create!(values_for_create(attributes), &block) }
114
+ block = _deprecated_scope_block("create!", &block)
115
+ scoping { klass.create!(attributes, &block) }
100
116
  end
101
117
  end
102
118
 
@@ -143,23 +159,12 @@ module ActiveRecord
143
159
  # failed due to validation errors it won't be persisted, you get what
144
160
  # #create returns in such situation.
145
161
  #
146
- # Please note *this method is not atomic*, it runs first a SELECT, and if
162
+ # Please note <b>this method is not atomic</b>, it runs first a SELECT, and if
147
163
  # there are no results an INSERT is attempted. If there are other threads
148
164
  # or processes there is a race condition between both calls and it could
149
165
  # be the case that you end up with two similar records.
150
166
  #
151
- # Whether that is a problem or not depends on the logic of the
152
- # application, but in the particular case in which rows have a UNIQUE
153
- # constraint an exception may be raised, just retry:
154
- #
155
- # begin
156
- # CreditAccount.transaction(requires_new: true) do
157
- # CreditAccount.find_or_create_by(user_id: user.id)
158
- # end
159
- # rescue ActiveRecord::RecordNotUnique
160
- # retry
161
- # end
162
- #
167
+ # If this might be a problem for your application, please see #create_or_find_by.
163
168
  def find_or_create_by(attributes, &block)
164
169
  find_by(attributes) || create(attributes, &block)
165
170
  end
@@ -171,6 +176,51 @@ module ActiveRecord
171
176
  find_by(attributes) || create!(attributes, &block)
172
177
  end
173
178
 
179
+ # Attempts to create a record with the given attributes in a table that has a unique constraint
180
+ # on one or several of its columns. If a row already exists with one or several of these
181
+ # unique constraints, the exception such an insertion would normally raise is caught,
182
+ # and the existing record with those attributes is found using #find_by!.
183
+ #
184
+ # This is similar to #find_or_create_by, but avoids the problem of stale reads between the SELECT
185
+ # and the INSERT, as that method needs to first query the table, then attempt to insert a row
186
+ # if none is found.
187
+ #
188
+ # There are several drawbacks to #create_or_find_by, though:
189
+ #
190
+ # * The underlying table must have the relevant columns defined with unique constraints.
191
+ # * A unique constraint violation may be triggered by only one, or at least less than all,
192
+ # of the given attributes. This means that the subsequent #find_by! may fail to find a
193
+ # matching record, which will then raise an <tt>ActiveRecord::RecordNotFound</tt> exception,
194
+ # rather than a record with the given attributes.
195
+ # * While we avoid the race condition between SELECT -> INSERT from #find_or_create_by,
196
+ # we actually have another race condition between INSERT -> SELECT, which can be triggered
197
+ # if a DELETE between those two statements is run by another client. But for most applications,
198
+ # that's a significantly less likely condition to hit.
199
+ # * It relies on exception handling to handle control flow, which may be marginally slower.
200
+ # * The primary key may auto-increment on each create, even if it fails. This can accelerate
201
+ # the problem of running out of integers, if the underlying table is still stuck on a primary
202
+ # key of type int (note: All Rails apps since 5.1+ have defaulted to bigint, which is not liable
203
+ # to this problem).
204
+ #
205
+ # This method will return a record if all given attributes are covered by unique constraints
206
+ # (unless the INSERT -> DELETE -> SELECT race condition is triggered), but if creation was attempted
207
+ # and failed due to validation errors it won't be persisted, you get what #create returns in
208
+ # such situation.
209
+ def create_or_find_by(attributes, &block)
210
+ transaction(requires_new: true) { create(attributes, &block) }
211
+ rescue ActiveRecord::RecordNotUnique
212
+ find_by!(attributes)
213
+ end
214
+
215
+ # Like #create_or_find_by, but calls
216
+ # {create!}[rdoc-ref:Persistence::ClassMethods#create!] so an exception
217
+ # is raised if the created record is invalid.
218
+ def create_or_find_by!(attributes, &block)
219
+ transaction(requires_new: true) { create!(attributes, &block) }
220
+ rescue ActiveRecord::RecordNotUnique
221
+ find_by!(attributes)
222
+ end
223
+
174
224
  # Like #find_or_create_by, but calls {new}[rdoc-ref:Core#new]
175
225
  # instead of {create}[rdoc-ref:Persistence::ClassMethods#create].
176
226
  def find_or_initialize_by(attributes, &block)
@@ -185,7 +235,7 @@ module ActiveRecord
185
235
  # are needed by the next ones when eager loading is going on.
186
236
  #
187
237
  # Please see further details in the
188
- # {Active Record Query Interface guide}[http://guides.rubyonrails.org/active_record_querying.html#running-explain].
238
+ # {Active Record Query Interface guide}[https://guides.rubyonrails.org/active_record_querying.html#running-explain].
189
239
  def explain
190
240
  exec_explain(collecting_queries_for_explain { exec_queries })
191
241
  end
@@ -241,30 +291,107 @@ module ActiveRecord
241
291
  limit_value ? records.many? : size > 1
242
292
  end
243
293
 
244
- # Returns a cache key that can be used to identify the records fetched by
245
- # this query. The cache key is built with a fingerprint of the sql query,
246
- # the number of records matched by the query and a timestamp of the last
247
- # updated record. When a new record comes to match the query, or any of
248
- # the existing records is updated or deleted, the cache key changes.
294
+ # Returns a stable cache key that can be used to identify this query.
295
+ # The cache key is built with a fingerprint of the SQL query.
249
296
  #
250
- # Product.where("name like ?", "%Cosmic Encounter%").cache_key
251
- # # => "products/query-1850ab3d302391b85b8693e941286659-1-20150714212553907087000"
297
+ # Product.where("name like ?", "%Cosmic Encounter%").cache_key
298
+ # # => "products/query-1850ab3d302391b85b8693e941286659"
252
299
  #
253
- # If the collection is loaded, the method will iterate through the records
254
- # to generate the timestamp, otherwise it will trigger one SQL query like:
300
+ # If ActiveRecord::Base.collection_cache_versioning is turned off, as it was
301
+ # in Rails 6.0 and earlier, the cache key will also include a version.
255
302
  #
256
- # SELECT COUNT(*), MAX("products"."updated_at") FROM "products" WHERE (name like '%Cosmic Encounter%')
303
+ # ActiveRecord::Base.collection_cache_versioning = false
304
+ # Product.where("name like ?", "%Cosmic Encounter%").cache_key
305
+ # # => "products/query-1850ab3d302391b85b8693e941286659-1-20150714212553907087000"
257
306
  #
258
307
  # You can also pass a custom timestamp column to fetch the timestamp of the
259
308
  # last updated record.
260
309
  #
261
310
  # Product.where("name like ?", "%Game%").cache_key(:last_reviewed_at)
262
- #
263
- # You can customize the strategy to generate the key on a per model basis
264
- # overriding ActiveRecord::Base#collection_cache_key.
265
311
  def cache_key(timestamp_column = :updated_at)
266
312
  @cache_keys ||= {}
267
- @cache_keys[timestamp_column] ||= @klass.collection_cache_key(self, timestamp_column)
313
+ @cache_keys[timestamp_column] ||= klass.collection_cache_key(self, timestamp_column)
314
+ end
315
+
316
+ def compute_cache_key(timestamp_column = :updated_at) # :nodoc:
317
+ query_signature = ActiveSupport::Digest.hexdigest(to_sql)
318
+ key = "#{klass.model_name.cache_key}/query-#{query_signature}"
319
+
320
+ if cache_version(timestamp_column)
321
+ key
322
+ else
323
+ "#{key}-#{compute_cache_version(timestamp_column)}"
324
+ end
325
+ end
326
+ private :compute_cache_key
327
+
328
+ # Returns a cache version that can be used together with the cache key to form
329
+ # a recyclable caching scheme. The cache version is built with the number of records
330
+ # matching the query, and the timestamp of the last updated record. When a new record
331
+ # comes to match the query, or any of the existing records is updated or deleted,
332
+ # the cache version changes.
333
+ #
334
+ # If the collection is loaded, the method will iterate through the records
335
+ # to generate the timestamp, otherwise it will trigger one SQL query like:
336
+ #
337
+ # SELECT COUNT(*), MAX("products"."updated_at") FROM "products" WHERE (name like '%Cosmic Encounter%')
338
+ def cache_version(timestamp_column = :updated_at)
339
+ if collection_cache_versioning
340
+ @cache_versions ||= {}
341
+ @cache_versions[timestamp_column] ||= compute_cache_version(timestamp_column)
342
+ end
343
+ end
344
+
345
+ def compute_cache_version(timestamp_column) # :nodoc:
346
+ if loaded? || distinct_value
347
+ size = records.size
348
+ if size > 0
349
+ timestamp = max_by(&timestamp_column)._read_attribute(timestamp_column)
350
+ end
351
+ else
352
+ collection = eager_loading? ? apply_join_dependency : self
353
+
354
+ column = connection.visitor.compile(arel_attribute(timestamp_column))
355
+ select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
356
+
357
+ if collection.has_limit_or_offset?
358
+ query = collection.select("#{column} AS collection_cache_key_timestamp")
359
+ subquery_alias = "subquery_for_cache_key"
360
+ subquery_column = "#{subquery_alias}.collection_cache_key_timestamp"
361
+ arel = query.build_subquery(subquery_alias, select_values % subquery_column)
362
+ else
363
+ query = collection.unscope(:order)
364
+ query.select_values = [select_values % column]
365
+ arel = query.arel
366
+ end
367
+
368
+ result = connection.select_one(arel, nil)
369
+
370
+ if result
371
+ column_type = klass.type_for_attribute(timestamp_column)
372
+ timestamp = column_type.deserialize(result["timestamp"])
373
+ size = result["size"]
374
+ else
375
+ timestamp = nil
376
+ size = 0
377
+ end
378
+ end
379
+
380
+ if timestamp
381
+ "#{size}-#{timestamp.utc.to_s(cache_timestamp_format)}"
382
+ else
383
+ "#{size}"
384
+ end
385
+ end
386
+ private :compute_cache_version
387
+
388
+ # Returns a cache key along with the version.
389
+ def cache_key_with_version
390
+ if version = cache_version
391
+ "#{cache_key}-#{version}"
392
+ else
393
+ cache_key
394
+ end
268
395
  end
269
396
 
270
397
  # Scope all queries to the current scope.
@@ -277,15 +404,12 @@ module ActiveRecord
277
404
  # Please check unscoped if you want to remove all previous scopes (including
278
405
  # the default_scope) during the execution of a block.
279
406
  def scoping
280
- previous, klass.current_scope = klass.current_scope(true), self unless @delegate_to_klass
281
- yield
282
- ensure
283
- klass.current_scope = previous unless @delegate_to_klass
407
+ already_in_scope? ? yield : _scoping(self) { yield }
284
408
  end
285
409
 
286
- def _exec_scope(*args, &block) # :nodoc:
410
+ def _exec_scope(name, *args, &block) # :nodoc:
287
411
  @delegate_to_klass = true
288
- instance_exec(*args, &block) || self
412
+ _scoping(_deprecated_spawn(name)) { instance_exec(*args, &block) || self }
289
413
  ensure
290
414
  @delegate_to_klass = false
291
415
  end
@@ -295,6 +419,8 @@ module ActiveRecord
295
419
  # trigger Active Record callbacks or validations. However, values passed to #update_all will still go through
296
420
  # Active Record's normal type casting and serialization.
297
421
  #
422
+ # Note: As Active Record callbacks are not triggered, this method will not automatically update +updated_at+/+updated_on+ columns.
423
+ #
298
424
  # ==== Parameters
299
425
  #
300
426
  # * +updates+ - A string, array, or hash representing the SET part of an SQL statement.
@@ -321,17 +447,23 @@ module ActiveRecord
321
447
  end
322
448
 
323
449
  stmt = Arel::UpdateManager.new
324
-
325
- stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates))
326
- stmt.table(table)
327
-
328
- if has_join_values? || offset_value
329
- @klass.connection.join_to_update(stmt, arel, arel_attribute(primary_key))
450
+ stmt.table(arel.join_sources.empty? ? table : arel.source)
451
+ stmt.key = arel_attribute(primary_key)
452
+ stmt.take(arel.limit)
453
+ stmt.offset(arel.offset)
454
+ stmt.order(*arel.orders)
455
+ stmt.wheres = arel.constraints
456
+
457
+ if updates.is_a?(Hash)
458
+ if klass.locking_enabled? &&
459
+ !updates.key?(klass.locking_column) &&
460
+ !updates.key?(klass.locking_column.to_sym)
461
+ attr = arel_attribute(klass.locking_column)
462
+ updates[attr.name] = _increment_attribute(attr)
463
+ end
464
+ stmt.set _substitute_values(updates)
330
465
  else
331
- stmt.key = arel_attribute(primary_key)
332
- stmt.take(arel.limit)
333
- stmt.order(*arel.orders)
334
- stmt.wheres = arel.constraints
466
+ stmt.set Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
335
467
  end
336
468
 
337
469
  @klass.connection.update stmt, "#{@klass} Update All"
@@ -345,6 +477,53 @@ module ActiveRecord
345
477
  end
346
478
  end
347
479
 
480
+ def update_counters(counters) # :nodoc:
481
+ touch = counters.delete(:touch)
482
+
483
+ updates = {}
484
+ counters.each do |counter_name, value|
485
+ attr = arel_attribute(counter_name)
486
+ updates[attr.name] = _increment_attribute(attr, value)
487
+ end
488
+
489
+ if touch
490
+ names = touch if touch != true
491
+ names = Array.wrap(names)
492
+ options = names.extract_options!
493
+ touch_updates = klass.touch_attributes_with_time(*names, **options)
494
+ updates.merge!(touch_updates) unless touch_updates.empty?
495
+ end
496
+
497
+ update_all updates
498
+ end
499
+
500
+ # Touches all records in the current relation, setting the +updated_at+/+updated_on+ attributes to the current time or the time specified.
501
+ # It does not instantiate the involved models, and it does not trigger Active Record callbacks or validations.
502
+ # This method can be passed attribute names and an optional time argument.
503
+ # If attribute names are passed, they are updated along with +updated_at+/+updated_on+ attributes.
504
+ # If no time argument is passed, the current time is used as default.
505
+ #
506
+ # === Examples
507
+ #
508
+ # # Touch all records
509
+ # Person.all.touch_all
510
+ # # => "UPDATE \"people\" SET \"updated_at\" = '2018-01-04 22:55:23.132670'"
511
+ #
512
+ # # Touch multiple records with a custom attribute
513
+ # Person.all.touch_all(:created_at)
514
+ # # => "UPDATE \"people\" SET \"updated_at\" = '2018-01-04 22:55:23.132670', \"created_at\" = '2018-01-04 22:55:23.132670'"
515
+ #
516
+ # # Touch multiple records with a specified time
517
+ # Person.all.touch_all(time: Time.new(2020, 5, 16, 0, 0, 0))
518
+ # # => "UPDATE \"people\" SET \"updated_at\" = '2020-05-16 00:00:00'"
519
+ #
520
+ # # Touch records with scope
521
+ # Person.where(name: 'David').touch_all
522
+ # # => "UPDATE \"people\" SET \"updated_at\" = '2018-01-04 22:55:23.132670' WHERE \"people\".\"name\" = 'David'"
523
+ def touch_all(*names, time: nil)
524
+ update_all klass.touch_attributes_with_time(*names, time: time)
525
+ end
526
+
348
527
  # Destroys the records by instantiating each
349
528
  # record and calling its {#destroy}[rdoc-ref:Persistence#destroy] method.
350
529
  # Each object's callbacks are executed (including <tt>:dependent</tt> association options).
@@ -385,8 +564,8 @@ module ActiveRecord
385
564
  # # => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
386
565
  def delete_all
387
566
  invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
388
- value = get_value(method)
389
- SINGLE_VALUE_METHODS.include?(method) ? value : value.any?
567
+ value = @values[method]
568
+ method == :distinct ? value : value&.any?
390
569
  end
391
570
  if invalid_methods.any?
392
571
  raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
@@ -398,13 +577,12 @@ module ActiveRecord
398
577
  end
399
578
 
400
579
  stmt = Arel::DeleteManager.new
401
- stmt.from(table)
402
-
403
- if has_join_values? || has_limit_or_offset?
404
- @klass.connection.join_to_delete(stmt, arel, arel_attribute(primary_key))
405
- else
406
- stmt.wheres = arel.constraints
407
- end
580
+ stmt.from(arel.join_sources.empty? ? table : arel.source)
581
+ stmt.key = arel_attribute(primary_key)
582
+ stmt.take(arel.limit)
583
+ stmt.offset(arel.offset)
584
+ stmt.order(*arel.orders)
585
+ stmt.wheres = arel.constraints
408
586
 
409
587
  affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
410
588
 
@@ -412,6 +590,32 @@ module ActiveRecord
412
590
  affected
413
591
  end
414
592
 
593
+ # Finds and destroys all records matching the specified conditions.
594
+ # This is short-hand for <tt>relation.where(condition).destroy_all</tt>.
595
+ # Returns the collection of objects that were destroyed.
596
+ #
597
+ # If no record is found, returns empty array.
598
+ #
599
+ # Person.destroy_by(id: 13)
600
+ # Person.destroy_by(name: 'Spartacus', rating: 4)
601
+ # Person.destroy_by("published_at < ?", 2.weeks.ago)
602
+ def destroy_by(*args)
603
+ where(*args).destroy_all
604
+ end
605
+
606
+ # Finds and deletes all records matching the specified conditions.
607
+ # This is short-hand for <tt>relation.where(condition).delete_all</tt>.
608
+ # Returns the number of rows affected.
609
+ #
610
+ # If no record is found, returns <tt>0</tt> as zero rows were affected.
611
+ #
612
+ # Person.delete_by(id: 13)
613
+ # Person.delete_by(name: 'Spartacus', rating: 4)
614
+ # Person.delete_by("published_at < ?", 2.weeks.ago)
615
+ def delete_by(*args)
616
+ where(*args).delete_all
617
+ end
618
+
415
619
  # Causes the records to be loaded from the database if they have not
416
620
  # been loaded already. You can use this if for some reason you need
417
621
  # to explicitly load some records before actually using them. The
@@ -432,9 +636,11 @@ module ActiveRecord
432
636
 
433
637
  def reset
434
638
  @delegate_to_klass = false
639
+ @_deprecated_scope_source = nil
435
640
  @to_sql = @arel = @loaded = @should_eager_load = nil
436
641
  @records = [].freeze
437
642
  @offsets = {}
643
+ @take = nil
438
644
  self
439
645
  end
440
646
 
@@ -465,7 +671,10 @@ module ActiveRecord
465
671
  end
466
672
 
467
673
  def scope_for_create
468
- where_values_hash.merge!(create_with_value.stringify_keys)
674
+ hash = where_values_hash
675
+ hash.delete(klass.inheritance_column) if klass.finder_needs_type_condition?
676
+ create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
677
+ hash
469
678
  end
470
679
 
471
680
  # Returns true if relation needs eager loading.
@@ -530,17 +739,72 @@ module ActiveRecord
530
739
  ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins)
531
740
  end
532
741
 
742
+ def preload_associations(records) # :nodoc:
743
+ preload = preload_values
744
+ preload += includes_values unless eager_loading?
745
+ preloader = nil
746
+ preload.each do |associations|
747
+ preloader ||= build_preloader
748
+ preloader.preload records, associations
749
+ end
750
+ end
751
+
752
+ attr_reader :_deprecated_scope_source # :nodoc:
753
+
533
754
  protected
755
+ attr_writer :_deprecated_scope_source # :nodoc:
534
756
 
535
757
  def load_records(records)
536
758
  @records = records.freeze
537
759
  @loaded = true
538
760
  end
539
761
 
762
+ def null_relation? # :nodoc:
763
+ is_a?(NullRelation)
764
+ end
765
+
540
766
  private
767
+ def already_in_scope?
768
+ @delegate_to_klass && begin
769
+ scope = klass.current_scope(true)
770
+ scope && !scope._deprecated_scope_source
771
+ end
772
+ end
773
+
774
+ def _deprecated_spawn(name)
775
+ spawn.tap { |scope| scope._deprecated_scope_source = name }
776
+ end
777
+
778
+ def _deprecated_scope_block(name, &block)
779
+ -> record do
780
+ klass.current_scope = _deprecated_spawn(name)
781
+ yield record if block_given?
782
+ end
783
+ end
541
784
 
542
- def has_join_values?
543
- joins_values.any? || left_outer_joins_values.any?
785
+ def _scoping(scope)
786
+ previous, klass.current_scope = klass.current_scope(true), scope
787
+ yield
788
+ ensure
789
+ klass.current_scope = previous
790
+ end
791
+
792
+ def _substitute_values(values)
793
+ values.map do |name, value|
794
+ attr = arel_attribute(name)
795
+ unless Arel.arel_node?(value)
796
+ type = klass.type_for_attribute(attr.name)
797
+ value = predicate_builder.build_bind_attribute(attr.name, type.cast(value))
798
+ end
799
+ [attr, value]
800
+ end
801
+ end
802
+
803
+ def _increment_attribute(attribute, value = 1)
804
+ bind = predicate_builder.build_bind_attribute(attribute.name, value.abs)
805
+ expr = table.coalesce(Arel::Nodes::UnqualifiedColumn.new(attribute), 0)
806
+ expr = value < 0 ? expr - bind : expr + bind
807
+ expr.expr
544
808
  end
545
809
 
546
810
  def exec_queries(&block)
@@ -548,7 +812,7 @@ module ActiveRecord
548
812
  @records =
549
813
  if eager_loading?
550
814
  apply_join_dependency do |relation, join_dependency|
551
- if ActiveRecord::NullRelation === relation
815
+ if relation.null_relation?
552
816
  []
553
817
  else
554
818
  relation = join_dependency.apply_column_aliases(relation)
@@ -560,13 +824,7 @@ module ActiveRecord
560
824
  klass.find_by_sql(arel, &block).freeze
561
825
  end
562
826
 
563
- preload = preload_values
564
- preload += includes_values unless eager_loading?
565
- preloader = nil
566
- preload.each do |associations|
567
- preloader ||= build_preloader
568
- preloader.preload @records, associations
569
- end
827
+ preload_associations(@records) unless skip_preloading_value
570
828
 
571
829
  @records.each(&:readonly!) if readonly_value
572
830
 
@@ -612,18 +870,5 @@ module ActiveRecord
612
870
  # ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
613
871
  string.scan(/([a-zA-Z_][.\w]+).?\./).flatten.map(&:downcase).uniq - ["raw_sql_"]
614
872
  end
615
-
616
- def values_for_create(attributes = nil)
617
- result = attributes ? where_values_hash.merge!(attributes) : where_values_hash
618
-
619
- # NOTE: if there are same keys in both create_with and result, create_with should be used.
620
- # This is to make sure nested attributes don't get passed to the klass.new,
621
- # while keeping the precedence of the duplicate keys in create_with.
622
- create_with_value.stringify_keys.each do |k, v|
623
- result[k] = v if result.key?(k)
624
- end
625
-
626
- result
627
- end
628
873
  end
629
874
  end