activerecord 5.1.5 → 5.2.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 +450 -699
  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 +4 -2
  9. data/lib/active_record/associations/alias_tracker.rb +19 -27
  10. data/lib/active_record/associations/association.rb +33 -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 +1 -1
  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 +52 -41
  22. data/lib/active_record/associations/collection_proxy.rb +12 -15
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +3 -1
  25. data/lib/active_record/associations/has_many_through_association.rb +8 -19
  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 +22 -67
  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 +17 -37
  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 +25 -214
  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 +16 -14
  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 +2 -0
  55. data/lib/active_record/collection_cache_key.rb +11 -7
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +157 -29
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
  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 +149 -78
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
  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 +2 -0
  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 +6 -0
  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 +3 -1
  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 +14 -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 +248 -112
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
  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 +20 -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 +79 -92
  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 +39 -60
  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 +17 -13
  133. data/lib/active_record/errors.rb +42 -3
  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 +4 -2
  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 +40 -2
  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 +196 -48
  156. data/lib/active_record/query_cache.rb +12 -14
  157. data/lib/active_record/querying.rb +3 -1
  158. data/lib/active_record/railtie.rb +61 -3
  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 +110 -192
  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 +31 -9
  167. data/lib/active_record/relation/delegation.rb +15 -27
  168. data/lib/active_record/relation/finder_methods.rb +71 -76
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +47 -20
  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 +55 -79
  179. data/lib/active_record/relation/query_attribute.rb +26 -2
  180. data/lib/active_record/relation/query_methods.rb +95 -91
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +3 -1
  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 +106 -219
  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 +6 -7
  193. data/lib/active_record/scoping/named.rb +21 -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 +22 -12
  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 +25 -14
  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 +32 -27
  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 +23 -36
  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
  module ActiveRecord
2
4
  module NullRelation # :nodoc:
3
5
  def pluck(*column_names)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record \Persistence
3
5
  module Persistence
@@ -69,6 +71,142 @@ module ActiveRecord
69
71
  klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
70
72
  end
71
73
 
74
+ # Updates an object (or multiple objects) and saves it to the database, if validations pass.
75
+ # The resulting object is returned whether the object was saved successfully to the database or not.
76
+ #
77
+ # ==== Parameters
78
+ #
79
+ # * +id+ - This should be the id or an array of ids to be updated.
80
+ # * +attributes+ - This should be a hash of attributes or an array of hashes.
81
+ #
82
+ # ==== Examples
83
+ #
84
+ # # Updates one record
85
+ # Person.update(15, user_name: "Samuel", group: "expert")
86
+ #
87
+ # # Updates multiple records
88
+ # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
89
+ # Person.update(people.keys, people.values)
90
+ #
91
+ # # Updates multiple records from the result of a relation
92
+ # people = Person.where(group: "expert")
93
+ # people.update(group: "masters")
94
+ #
95
+ # Note: Updating a large number of records will run an UPDATE
96
+ # query for each record, which may cause a performance issue.
97
+ # When running callbacks is not needed for each record update,
98
+ # it is preferred to use {update_all}[rdoc-ref:Relation#update_all]
99
+ # for updating all records in a single query.
100
+ def update(id = :all, attributes)
101
+ if id.is_a?(Array)
102
+ id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
103
+ object.update(attributes[idx])
104
+ }
105
+ elsif id == :all
106
+ all.each { |record| record.update(attributes) }
107
+ else
108
+ if ActiveRecord::Base === id
109
+ raise ArgumentError,
110
+ "You are passing an instance of ActiveRecord::Base to `update`. " \
111
+ "Please pass the id of the object by calling `.id`."
112
+ end
113
+ object = find(id)
114
+ object.update(attributes)
115
+ object
116
+ end
117
+ end
118
+
119
+ # Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
120
+ # therefore all callbacks and filters are fired off before the object is deleted. This method is
121
+ # less efficient than #delete but allows cleanup methods and other actions to be run.
122
+ #
123
+ # This essentially finds the object (or multiple objects) with the given id, creates a new object
124
+ # from the attributes, and then calls destroy on it.
125
+ #
126
+ # ==== Parameters
127
+ #
128
+ # * +id+ - This should be the id or an array of ids to be destroyed.
129
+ #
130
+ # ==== Examples
131
+ #
132
+ # # Destroy a single object
133
+ # Todo.destroy(1)
134
+ #
135
+ # # Destroy multiple objects
136
+ # todos = [1,2,3]
137
+ # Todo.destroy(todos)
138
+ def destroy(id)
139
+ if id.is_a?(Array)
140
+ find(id).each(&:destroy)
141
+ else
142
+ find(id).destroy
143
+ end
144
+ end
145
+
146
+ # Deletes the row with a primary key matching the +id+ argument, using a
147
+ # SQL +DELETE+ statement, and returns the number of rows deleted. Active
148
+ # Record objects are not instantiated, so the object's callbacks are not
149
+ # executed, including any <tt>:dependent</tt> association options.
150
+ #
151
+ # You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
152
+ #
153
+ # Note: Although it is often much faster than the alternative, #destroy,
154
+ # skipping callbacks might bypass business logic in your application
155
+ # that ensures referential integrity or performs other essential jobs.
156
+ #
157
+ # ==== Examples
158
+ #
159
+ # # Delete a single row
160
+ # Todo.delete(1)
161
+ #
162
+ # # Delete multiple rows
163
+ # Todo.delete([2,3,4])
164
+ def delete(id_or_array)
165
+ where(primary_key => id_or_array).delete_all
166
+ end
167
+
168
+ def _insert_record(values) # :nodoc:
169
+ primary_key_value = nil
170
+
171
+ if primary_key && Hash === values
172
+ primary_key_value = values[primary_key]
173
+
174
+ if !primary_key_value && prefetch_primary_key?
175
+ primary_key_value = next_sequence_value
176
+ values[primary_key] = primary_key_value
177
+ end
178
+ end
179
+
180
+ if values.empty?
181
+ im = arel_table.compile_insert(connection.empty_insert_statement_value)
182
+ im.into arel_table
183
+ else
184
+ im = arel_table.compile_insert(_substitute_values(values))
185
+ end
186
+
187
+ connection.insert(im, "#{self} Create", primary_key || false, primary_key_value)
188
+ end
189
+
190
+ def _update_record(values, constraints) # :nodoc:
191
+ constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
192
+
193
+ um = arel_table.where(
194
+ constraints.reduce(&:and)
195
+ ).compile_update(_substitute_values(values), primary_key)
196
+
197
+ connection.update(um, "#{self} Update")
198
+ end
199
+
200
+ def _delete_record(constraints) # :nodoc:
201
+ constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
202
+
203
+ dm = Arel::DeleteManager.new
204
+ dm.from(arel_table)
205
+ dm.wheres = constraints
206
+
207
+ connection.delete(dm, "#{self} Destroy")
208
+ end
209
+
72
210
  private
73
211
  # Called by +instantiate+ to decide which class to use for a new
74
212
  # record instance.
@@ -78,6 +216,14 @@ module ActiveRecord
78
216
  def discriminate_class_for_record(record)
79
217
  self
80
218
  end
219
+
220
+ def _substitute_values(values)
221
+ values.map do |name, value|
222
+ attr = arel_attribute(name)
223
+ bind = predicate_builder.build_bind_attribute(name, value)
224
+ [attr, bind]
225
+ end
226
+ end
81
227
  end
82
228
 
83
229
  # Returns true if this object hasn't been saved yet -- that is, a record
@@ -175,7 +321,7 @@ module ActiveRecord
175
321
  # callbacks or any <tt>:dependent</tt> association
176
322
  # options, use <tt>#destroy</tt>.
177
323
  def delete
178
- self.class.delete(id) if persisted?
324
+ _delete_row if persisted?
179
325
  @destroyed = true
180
326
  freeze
181
327
  end
@@ -224,9 +370,10 @@ module ActiveRecord
224
370
  # Any change to the attributes on either instance will affect both instances.
225
371
  # If you want to change the sti column as well, use #becomes! instead.
226
372
  def becomes(klass)
227
- became = klass.new
373
+ became = klass.allocate
374
+ became.send(:initialize)
228
375
  became.instance_variable_set("@attributes", @attributes)
229
- became.instance_variable_set("@mutation_tracker", @mutation_tracker) if defined?(@mutation_tracker)
376
+ became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
230
377
  became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
231
378
  became.instance_variable_set("@new_record", new_record?)
232
379
  became.instance_variable_set("@destroyed", destroyed?)
@@ -326,13 +473,16 @@ module ActiveRecord
326
473
  verify_readonly_attribute(key.to_s)
327
474
  end
328
475
 
329
- updated_count = self.class.unscoped.where(self.class.primary_key => id).update_all(attributes)
476
+ affected_rows = self.class._update_record(
477
+ attributes,
478
+ self.class.primary_key => id_in_database
479
+ )
330
480
 
331
481
  attributes.each do |k, v|
332
- raw_write_attribute(k, v)
482
+ write_attribute_without_type_cast(k, v)
333
483
  end
334
484
 
335
- updated_count == 1
485
+ affected_rows == 1
336
486
  end
337
487
 
338
488
  # Initializes +attribute+ to zero if +nil+ and adds the value passed as +by+ (default is 1).
@@ -347,7 +497,7 @@ module ActiveRecord
347
497
  # Wrapper around #increment that writes the update to the database.
348
498
  # Only +attribute+ is updated; the record itself is not saved.
349
499
  # This means that any other modified attributes will still be dirty.
350
- # Validations and callbacks are skipped. Supports the `touch` option from
500
+ # Validations and callbacks are skipped. Supports the +touch+ option from
351
501
  # +update_counters+, see that for more.
352
502
  # Returns +self+.
353
503
  def increment!(attribute, by = 1, touch: nil)
@@ -368,7 +518,7 @@ module ActiveRecord
368
518
  # Wrapper around #decrement that writes the update to the database.
369
519
  # Only +attribute+ is updated; the record itself is not saved.
370
520
  # This means that any other modified attributes will still be dirty.
371
- # Validations and callbacks are skipped. Supports the `touch` option from
521
+ # Validations and callbacks are skipped. Supports the +touch+ option from
372
522
  # +update_counters+, see that for more.
373
523
  # Returns +self+.
374
524
  def decrement!(attribute, by = 1, touch: nil)
@@ -505,36 +655,12 @@ module ActiveRecord
505
655
  MSG
506
656
  end
507
657
 
508
- time ||= current_time_from_proper_timezone
509
- attributes = timestamp_attributes_for_update_in_model
510
- attributes.concat(names)
511
-
512
- unless attributes.empty?
513
- changes = {}
514
-
515
- attributes.each do |column|
516
- column = column.to_s
517
- changes[column] = write_attribute(column, time)
518
- end
519
-
520
- primary_key = self.class.primary_key
521
- scope = self.class.unscoped.where(primary_key => _read_attribute(primary_key))
522
-
523
- if locking_enabled?
524
- locking_column = self.class.locking_column
525
- scope = scope.where(locking_column => _read_attribute(locking_column))
526
- changes[locking_column] = increment_lock
527
- end
528
-
529
- clear_attribute_changes(changes.keys)
530
- result = scope.update_all(changes) == 1
531
-
532
- if !result && locking_enabled?
533
- raise ActiveRecord::StaleObjectError.new(self, "touch")
534
- end
658
+ attribute_names = timestamp_attributes_for_update_in_model
659
+ attribute_names |= names.map(&:to_s)
535
660
 
536
- @_trigger_update_callback = result
537
- result
661
+ unless attribute_names.empty?
662
+ affected_rows = _touch_row(attribute_names, time)
663
+ @_trigger_update_callback = affected_rows == 1
538
664
  else
539
665
  true
540
666
  end
@@ -547,15 +673,34 @@ module ActiveRecord
547
673
  end
548
674
 
549
675
  def destroy_row
550
- relation_for_destroy.delete_all
676
+ _delete_row
551
677
  end
552
678
 
553
- def relation_for_destroy
554
- self.class.unscoped.where(self.class.primary_key => id)
679
+ def _delete_row
680
+ self.class._delete_record(self.class.primary_key => id_in_database)
681
+ end
682
+
683
+ def _touch_row(attribute_names, time)
684
+ time ||= current_time_from_proper_timezone
685
+
686
+ attribute_names.each do |attr_name|
687
+ write_attribute(attr_name, time)
688
+ clear_attribute_change(attr_name)
689
+ end
690
+
691
+ _update_row(attribute_names, "touch")
692
+ end
693
+
694
+ def _update_row(attribute_names, attempted_action = "update")
695
+ self.class._update_record(
696
+ attributes_with_values(attribute_names),
697
+ self.class.primary_key => id_in_database
698
+ )
555
699
  end
556
700
 
557
701
  def create_or_update(*args, &block)
558
702
  _raise_readonly_record_error if readonly?
703
+ return false if destroyed?
559
704
  result = new_record? ? _create_record(&block) : _update_record(*args, &block)
560
705
  result != false
561
706
  end
@@ -563,26 +708,29 @@ module ActiveRecord
563
708
  # Updates the associated record with values matching those of the instance attributes.
564
709
  # Returns the number of affected rows.
565
710
  def _update_record(attribute_names = self.attribute_names)
566
- attributes_values = arel_attributes_with_values_for_update(attribute_names)
567
- if attributes_values.empty?
568
- rows_affected = 0
711
+ attribute_names &= self.class.column_names
712
+ attribute_names = attributes_for_update(attribute_names)
713
+
714
+ if attribute_names.empty?
715
+ affected_rows = 0
569
716
  @_trigger_update_callback = true
570
717
  else
571
- rows_affected = self.class.unscoped._update_record attributes_values, id, id_in_database
572
- @_trigger_update_callback = rows_affected > 0
718
+ affected_rows = _update_row(attribute_names)
719
+ @_trigger_update_callback = affected_rows == 1
573
720
  end
574
721
 
575
722
  yield(self) if block_given?
576
723
 
577
- rows_affected
724
+ affected_rows
578
725
  end
579
726
 
580
727
  # Creates a record with values matching those of the instance attributes
581
728
  # and returns its id.
582
729
  def _create_record(attribute_names = self.attribute_names)
583
- attributes_values = arel_attributes_with_values_for_create(attribute_names)
730
+ attribute_names &= self.class.column_names
731
+ attributes_values = attributes_with_values_for_create(attribute_names)
584
732
 
585
- new_id = self.class.unscoped.insert attributes_values
733
+ new_id = self.class._insert_record(attributes_values)
586
734
  self.id ||= new_id if self.class.primary_key
587
735
 
588
736
  @new_record = false
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record Query Cache
3
5
  class QueryCache
@@ -5,35 +7,31 @@ module ActiveRecord
5
7
  # Enable the query cache within the block if Active Record is configured.
6
8
  # If it's not, it will execute the given block.
7
9
  def cache(&block)
8
- if configurations.empty?
9
- yield
10
- else
10
+ if connected? || !configurations.empty?
11
11
  connection.cache(&block)
12
+ else
13
+ yield
12
14
  end
13
15
  end
14
16
 
15
17
  # Disable the query cache within the block if Active Record is configured.
16
18
  # If it's not, it will execute the given block.
17
19
  def uncached(&block)
18
- if configurations.empty?
19
- yield
20
- else
20
+ if connected? || !configurations.empty?
21
21
  connection.uncached(&block)
22
+ else
23
+ yield
22
24
  end
23
25
  end
24
26
  end
25
27
 
26
28
  def self.run
27
- caching_pool = ActiveRecord::Base.connection_pool
28
- caching_was_enabled = caching_pool.query_cache_enabled
29
-
30
- caching_pool.enable_query_cache!
31
-
32
- [caching_pool, caching_was_enabled]
29
+ ActiveRecord::Base.connection_handler.connection_pool_list.
30
+ reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
33
31
  end
34
32
 
35
- def self.complete((caching_pool, caching_was_enabled))
36
- caching_pool.disable_query_cache! unless caching_was_enabled
33
+ def self.complete(pools)
34
+ pools.each { |pool| pool.disable_query_cache! }
37
35
 
38
36
  ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
39
37
  pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Querying
3
5
  delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
@@ -5,7 +7,7 @@ module ActiveRecord
5
7
  delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
6
8
  delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
7
9
  delegate :find_by, :find_by!, to: :all
8
- delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, to: :all
10
+ delegate :destroy_all, :delete_all, :update_all, to: :all
9
11
  delegate :find_each, :find_in_batches, :in_batches, to: :all
10
12
  delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
11
13
  :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record"
2
4
  require "rails"
3
5
  require "active_model/railtie"
@@ -26,6 +28,9 @@ module ActiveRecord
26
28
  config.active_record.use_schema_cache_dump = true
27
29
  config.active_record.maintain_test_schema = true
28
30
 
31
+ config.active_record.sqlite3 = ActiveSupport::OrderedOptions.new
32
+ config.active_record.sqlite3.represent_boolean_as_integer = nil
33
+
29
34
  config.eager_load_namespaces << ActiveRecord
30
35
 
31
36
  rake_tasks do
@@ -54,6 +59,7 @@ module ActiveRecord
54
59
  console = ActiveSupport::Logger.new(STDERR)
55
60
  Rails.logger.extend ActiveSupport::Logger.broadcast console
56
61
  end
62
+ ActiveRecord::Base.verbose_query_logs = false
57
63
  end
58
64
 
59
65
  runner do
@@ -85,12 +91,16 @@ module ActiveRecord
85
91
  filename = File.join(app.config.paths["db"].first, "schema_cache.yml")
86
92
 
87
93
  if File.file?(filename)
94
+ current_version = ActiveRecord::Migrator.current_version
95
+
96
+ next if current_version.nil?
97
+
88
98
  cache = YAML.load(File.read(filename))
89
- if cache.version == ActiveRecord::Migrator.current_version
99
+ if cache.version == current_version
90
100
  connection.schema_cache = cache
91
101
  connection_pool.schema_cache = cache.dup
92
102
  else
93
- warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
103
+ warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
94
104
  end
95
105
  end
96
106
  end
@@ -108,7 +118,9 @@ module ActiveRecord
108
118
 
109
119
  initializer "active_record.set_configs" do |app|
110
120
  ActiveSupport.on_load(:active_record) do
111
- app.config.active_record.each do |k, v|
121
+ configs = app.config.active_record.dup
122
+ configs.delete(:sqlite3)
123
+ configs.each do |k, v|
112
124
  send "#{k}=", v
113
125
  end
114
126
  end
@@ -166,5 +178,51 @@ end_warning
166
178
  path = app.paths["db"].first
167
179
  config.watchable_files.concat ["#{path}/schema.rb", "#{path}/structure.sql"]
168
180
  end
181
+
182
+ initializer "active_record.clear_active_connections" do
183
+ config.after_initialize do
184
+ ActiveSupport.on_load(:active_record) do
185
+ # Ideally the application doesn't connect to the database during boot,
186
+ # but sometimes it does. In case it did, we want to empty out the
187
+ # connection pools so that a non-database-using process (e.g. a master
188
+ # process in a forking server model) doesn't retain a needless
189
+ # connection. If it was needed, the incremental cost of reestablishing
190
+ # this connection is trivial: the rest of the pool would need to be
191
+ # populated anyway.
192
+
193
+ clear_active_connections!
194
+ flush_idle_connections!
195
+ end
196
+ end
197
+ end
198
+
199
+ initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
200
+ config.after_initialize do
201
+ ActiveSupport.on_load(:active_record_sqlite3adapter) do
202
+ represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
203
+ unless represent_boolean_as_integer.nil?
204
+ ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
205
+ end
206
+
207
+ unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
208
+ ActiveSupport::Deprecation.warn <<-MSG
209
+ Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
210
+ set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
211
+ boolean values and must have old data converted to 1 and 0 (its native boolean
212
+ serialization) before setting this flag to true. Conversion can be accomplished
213
+ by setting up a rake task which runs
214
+
215
+ ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
216
+ ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
217
+
218
+ for all models and all boolean columns, after which the flag must be set to
219
+ true by adding the following to your application.rb file:
220
+
221
+ Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
222
+ MSG
223
+ end
224
+ end
225
+ end
226
+ end
169
227
  end
170
228
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ActiveRecord::Base.connection.begin_transaction(joinable: false)
2
4
 
3
5
  at_exit do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/attr_internal"
2
4
  require "active_record/log_subscriber"
3
5