activerecord 4.2.0 → 5.0.0

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

Potentially problematic release.


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

Files changed (249) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1537 -789
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -8
  5. data/examples/performance.rb +2 -3
  6. data/examples/simple.rb +0 -1
  7. data/lib/active_record/aggregations.rb +37 -23
  8. data/lib/active_record/association_relation.rb +16 -3
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +23 -9
  11. data/lib/active_record/associations/association_scope.rb +74 -102
  12. data/lib/active_record/associations/belongs_to_association.rb +26 -29
  13. data/lib/active_record/associations/builder/association.rb +28 -34
  14. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  15. data/lib/active_record/associations/builder/collection_association.rb +12 -20
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +22 -15
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +11 -6
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  20. data/lib/active_record/associations/collection_association.rb +61 -33
  21. data/lib/active_record/associations/collection_proxy.rb +81 -35
  22. data/lib/active_record/associations/foreign_association.rb +11 -0
  23. data/lib/active_record/associations/has_many_association.rb +21 -57
  24. data/lib/active_record/associations/has_many_through_association.rb +15 -45
  25. data/lib/active_record/associations/has_one_association.rb +13 -5
  26. data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
  27. data/lib/active_record/associations/join_dependency.rb +37 -21
  28. data/lib/active_record/associations/preloader/association.rb +51 -53
  29. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  30. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  31. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  32. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  33. data/lib/active_record/associations/preloader.rb +18 -8
  34. data/lib/active_record/associations/singular_association.rb +8 -8
  35. data/lib/active_record/associations/through_association.rb +22 -9
  36. data/lib/active_record/associations.rb +321 -212
  37. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  38. data/lib/active_record/attribute.rb +79 -15
  39. data/lib/active_record/attribute_assignment.rb +20 -141
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +6 -1
  42. data/lib/active_record/attribute_methods/dirty.rb +51 -81
  43. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  44. data/lib/active_record/attribute_methods/query.rb +2 -2
  45. data/lib/active_record/attribute_methods/read.rb +31 -59
  46. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -14
  48. data/lib/active_record/attribute_methods/write.rb +14 -38
  49. data/lib/active_record/attribute_methods.rb +70 -45
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set/builder.rb +37 -15
  52. data/lib/active_record/attribute_set.rb +34 -3
  53. data/lib/active_record/attributes.rb +199 -73
  54. data/lib/active_record/autosave_association.rb +73 -25
  55. data/lib/active_record/base.rb +35 -27
  56. data/lib/active_record/callbacks.rb +39 -43
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +20 -8
  59. data/lib/active_record/collection_cache_key.rb +40 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +457 -181
  61. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  62. data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -59
  63. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
  64. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
  65. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -4
  66. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +246 -185
  68. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  69. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +438 -136
  70. data/lib/active_record/connection_adapters/abstract/transaction.rb +53 -40
  71. data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -66
  72. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +429 -335
  73. data/lib/active_record/connection_adapters/column.rb +28 -43
  74. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  75. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  78. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  79. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  83. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -177
  85. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  86. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +11 -73
  87. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -13
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  95. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  98. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  99. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  101. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
  102. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  103. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  106. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  107. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  108. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  109. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +248 -154
  111. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  112. data/lib/active_record/connection_adapters/postgresql_adapter.rb +258 -170
  113. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  114. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  115. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  116. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +150 -209
  119. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  120. data/lib/active_record/connection_handling.rb +38 -15
  121. data/lib/active_record/core.rb +109 -114
  122. data/lib/active_record/counter_cache.rb +14 -25
  123. data/lib/active_record/dynamic_matchers.rb +1 -20
  124. data/lib/active_record/enum.rb +115 -79
  125. data/lib/active_record/errors.rb +88 -48
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +2 -2
  128. data/lib/active_record/fixture_set/file.rb +26 -5
  129. data/lib/active_record/fixtures.rb +84 -46
  130. data/lib/active_record/gem_version.rb +2 -2
  131. data/lib/active_record/inheritance.rb +32 -40
  132. data/lib/active_record/integration.rb +4 -4
  133. data/lib/active_record/internal_metadata.rb +56 -0
  134. data/lib/active_record/legacy_yaml_adapter.rb +46 -0
  135. data/lib/active_record/locale/en.yml +3 -2
  136. data/lib/active_record/locking/optimistic.rb +27 -25
  137. data/lib/active_record/locking/pessimistic.rb +1 -1
  138. data/lib/active_record/log_subscriber.rb +43 -21
  139. data/lib/active_record/migration/command_recorder.rb +59 -18
  140. data/lib/active_record/migration/compatibility.rb +126 -0
  141. data/lib/active_record/migration.rb +372 -114
  142. data/lib/active_record/model_schema.rb +128 -38
  143. data/lib/active_record/nested_attributes.rb +71 -32
  144. data/lib/active_record/no_touching.rb +1 -1
  145. data/lib/active_record/null_relation.rb +16 -8
  146. data/lib/active_record/persistence.rb +124 -80
  147. data/lib/active_record/query_cache.rb +15 -18
  148. data/lib/active_record/querying.rb +10 -9
  149. data/lib/active_record/railtie.rb +28 -19
  150. data/lib/active_record/railties/controller_runtime.rb +1 -1
  151. data/lib/active_record/railties/databases.rake +67 -51
  152. data/lib/active_record/readonly_attributes.rb +1 -1
  153. data/lib/active_record/reflection.rb +318 -139
  154. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  155. data/lib/active_record/relation/batches.rb +139 -34
  156. data/lib/active_record/relation/calculations.rb +80 -102
  157. data/lib/active_record/relation/delegation.rb +7 -20
  158. data/lib/active_record/relation/finder_methods.rb +167 -97
  159. data/lib/active_record/relation/from_clause.rb +32 -0
  160. data/lib/active_record/relation/merger.rb +38 -41
  161. data/lib/active_record/relation/predicate_builder/array_handler.rb +12 -16
  162. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  163. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  164. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  165. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  166. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  167. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  168. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  169. data/lib/active_record/relation/predicate_builder.rb +124 -82
  170. data/lib/active_record/relation/query_attribute.rb +19 -0
  171. data/lib/active_record/relation/query_methods.rb +323 -257
  172. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  173. data/lib/active_record/relation/spawn_methods.rb +11 -10
  174. data/lib/active_record/relation/where_clause.rb +174 -0
  175. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  176. data/lib/active_record/relation.rb +176 -115
  177. data/lib/active_record/result.rb +4 -3
  178. data/lib/active_record/runtime_registry.rb +1 -1
  179. data/lib/active_record/sanitization.rb +95 -66
  180. data/lib/active_record/schema.rb +26 -22
  181. data/lib/active_record/schema_dumper.rb +62 -38
  182. data/lib/active_record/schema_migration.rb +11 -17
  183. data/lib/active_record/scoping/default.rb +24 -9
  184. data/lib/active_record/scoping/named.rb +49 -28
  185. data/lib/active_record/scoping.rb +32 -15
  186. data/lib/active_record/secure_token.rb +38 -0
  187. data/lib/active_record/serialization.rb +2 -4
  188. data/lib/active_record/statement_cache.rb +16 -14
  189. data/lib/active_record/store.rb +8 -3
  190. data/lib/active_record/suppressor.rb +58 -0
  191. data/lib/active_record/table_metadata.rb +68 -0
  192. data/lib/active_record/tasks/database_tasks.rb +59 -42
  193. data/lib/active_record/tasks/mysql_database_tasks.rb +32 -26
  194. data/lib/active_record/tasks/postgresql_database_tasks.rb +29 -9
  195. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  196. data/lib/active_record/timestamp.rb +20 -9
  197. data/lib/active_record/touch_later.rb +58 -0
  198. data/lib/active_record/transactions.rb +159 -67
  199. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  200. data/lib/active_record/type/date.rb +2 -41
  201. data/lib/active_record/type/date_time.rb +2 -38
  202. data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
  203. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  204. data/lib/active_record/type/internal/timezone.rb +15 -0
  205. data/lib/active_record/type/serialized.rb +21 -14
  206. data/lib/active_record/type/time.rb +10 -16
  207. data/lib/active_record/type/type_map.rb +4 -4
  208. data/lib/active_record/type.rb +66 -17
  209. data/lib/active_record/type_caster/connection.rb +29 -0
  210. data/lib/active_record/type_caster/map.rb +19 -0
  211. data/lib/active_record/type_caster.rb +7 -0
  212. data/lib/active_record/validations/absence.rb +23 -0
  213. data/lib/active_record/validations/associated.rb +10 -3
  214. data/lib/active_record/validations/length.rb +24 -0
  215. data/lib/active_record/validations/presence.rb +11 -12
  216. data/lib/active_record/validations/uniqueness.rb +29 -18
  217. data/lib/active_record/validations.rb +33 -32
  218. data/lib/active_record.rb +9 -2
  219. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  220. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -6
  221. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -7
  222. data/lib/rails/generators/active_record/migration.rb +7 -0
  223. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  224. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  225. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  226. metadata +60 -34
  227. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  228. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  229. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  231. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  232. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  233. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  234. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  235. data/lib/active_record/type/big_integer.rb +0 -13
  236. data/lib/active_record/type/binary.rb +0 -50
  237. data/lib/active_record/type/boolean.rb +0 -30
  238. data/lib/active_record/type/decimal.rb +0 -40
  239. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  240. data/lib/active_record/type/decorator.rb +0 -14
  241. data/lib/active_record/type/float.rb +0 -19
  242. data/lib/active_record/type/integer.rb +0 -55
  243. data/lib/active_record/type/mutable.rb +0 -16
  244. data/lib/active_record/type/numeric.rb +0 -36
  245. data/lib/active_record/type/string.rb +0 -36
  246. data/lib/active_record/type/text.rb +0 -11
  247. data/lib/active_record/type/time_value.rb +0 -38
  248. data/lib/active_record/type/unsigned_integer.rb +0 -15
  249. data/lib/active_record/type/value.rb +0 -101
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
- # = Active Record Persistence
2
+ # = Active Record \Persistence
3
3
  module Persistence
4
4
  extend ActiveSupport::Concern
5
5
 
@@ -61,7 +61,7 @@ module ActiveRecord
61
61
  # +instantiate+ instead of +new+, finder methods ensure they get new
62
62
  # instances of the appropriate class for each record.
63
63
  #
64
- # See +ActiveRecord::Inheritance#discriminate_class_for_record+ to see
64
+ # See <tt>ActiveRecord::Inheritance#discriminate_class_for_record</tt> to see
65
65
  # how this "single-table" inheritance mapping is implemented.
66
66
  def instantiate(attributes, column_types = {})
67
67
  klass = discriminate_class_for_record(attributes)
@@ -96,50 +96,60 @@ module ActiveRecord
96
96
  # Returns true if the record is persisted, i.e. it's not a new record and it was
97
97
  # not destroyed, otherwise returns false.
98
98
  def persisted?
99
- !(new_record? || destroyed?)
99
+ sync_with_transaction_state
100
+ !(@new_record || @destroyed)
100
101
  end
101
102
 
102
103
  # Saves the model.
103
104
  #
104
- # If the model is new a record gets created in the database, otherwise
105
+ # If the model is new, a record gets created in the database, otherwise
105
106
  # the existing record gets updated.
106
107
  #
107
- # By default, save always run validations. If any of them fail the action
108
- # is cancelled and +save+ returns +false+. However, if you supply
108
+ # By default, save always runs validations. If any of them fail the action
109
+ # is cancelled and #save returns +false+, and the record won't be saved. However, if you supply
109
110
  # validate: false, validations are bypassed altogether. See
110
111
  # ActiveRecord::Validations for more information.
111
112
  #
112
- # There's a series of callbacks associated with +save+. If any of the
113
- # <tt>before_*</tt> callbacks return +false+ the action is cancelled and
114
- # +save+ returns +false+. See ActiveRecord::Callbacks for further
113
+ # By default, #save also sets the +updated_at+/+updated_on+ attributes to
114
+ # the current time. However, if you supply <tt>touch: false</tt>, these
115
+ # timestamps will not be updated.
116
+ #
117
+ # There's a series of callbacks associated with #save. If any of the
118
+ # <tt>before_*</tt> callbacks throws +:abort+ the action is cancelled and
119
+ # #save returns +false+. See ActiveRecord::Callbacks for further
115
120
  # details.
116
121
  #
117
122
  # Attributes marked as readonly are silently ignored if the record is
118
123
  # being updated.
119
- def save(*)
120
- create_or_update
124
+ def save(*args)
125
+ create_or_update(*args)
121
126
  rescue ActiveRecord::RecordInvalid
122
127
  false
123
128
  end
124
129
 
125
130
  # Saves the model.
126
131
  #
127
- # If the model is new a record gets created in the database, otherwise
132
+ # If the model is new, a record gets created in the database, otherwise
128
133
  # the existing record gets updated.
129
134
  #
130
- # With <tt>save!</tt> validations always run. If any of them fail
131
- # ActiveRecord::RecordInvalid gets raised. See ActiveRecord::Validations
132
- # for more information.
135
+ # By default, #save! always runs validations. If any of them fail
136
+ # ActiveRecord::RecordInvalid gets raised, and the record won't be saved. However, if you supply
137
+ # validate: false, validations are bypassed altogether. See
138
+ # ActiveRecord::Validations for more information.
139
+ #
140
+ # By default, #save! also sets the +updated_at+/+updated_on+ attributes to
141
+ # the current time. However, if you supply <tt>touch: false</tt>, these
142
+ # timestamps will not be updated.
133
143
  #
134
- # There's a series of callbacks associated with <tt>save!</tt>. If any of
135
- # the <tt>before_*</tt> callbacks return +false+ the action is cancelled
136
- # and <tt>save!</tt> raises ActiveRecord::RecordNotSaved. See
144
+ # There's a series of callbacks associated with #save!. If any of
145
+ # the <tt>before_*</tt> callbacks throws +:abort+ the action is cancelled
146
+ # and #save! raises ActiveRecord::RecordNotSaved. See
137
147
  # ActiveRecord::Callbacks for further details.
138
148
  #
139
149
  # Attributes marked as readonly are silently ignored if the record is
140
150
  # being updated.
141
- def save!(*)
142
- create_or_update || raise(RecordNotSaved.new(nil, self))
151
+ def save!(*args)
152
+ create_or_update(*args) || raise(RecordNotSaved.new("Failed to save the record", self))
143
153
  end
144
154
 
145
155
  # Deletes the record in the database and freezes this instance to
@@ -149,6 +159,8 @@ module ActiveRecord
149
159
  # The row is simply removed with an SQL +DELETE+ statement on the
150
160
  # record's primary key, and no callbacks are executed.
151
161
  #
162
+ # Note that this will also delete records marked as {#readonly?}[rdoc-ref:Core#readonly?].
163
+ #
152
164
  # To enforce the object's +before_destroy+ and +after_destroy+
153
165
  # callbacks or any <tt>:dependent</tt> association
154
166
  # options, use <tt>#destroy</tt>.
@@ -161,13 +173,14 @@ module ActiveRecord
161
173
  # Deletes the record in the database and freezes this instance to reflect
162
174
  # that no changes should be made (since they can't be persisted).
163
175
  #
164
- # There's a series of callbacks associated with <tt>destroy</tt>. If
165
- # the <tt>before_destroy</tt> callback return +false+ the action is cancelled
166
- # and <tt>destroy</tt> returns +false+. See
167
- # ActiveRecord::Callbacks for further details.
176
+ # There's a series of callbacks associated with #destroy. If the
177
+ # <tt>before_destroy</tt> callback throws +:abort+ the action is cancelled
178
+ # and #destroy returns +false+.
179
+ # See ActiveRecord::Callbacks for further details.
168
180
  def destroy
169
181
  raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
170
182
  destroy_associations
183
+ self.class.connection.add_transaction_record(self)
171
184
  destroy_row if persisted?
172
185
  @destroyed = true
173
186
  freeze
@@ -176,12 +189,12 @@ module ActiveRecord
176
189
  # Deletes the record in the database and freezes this instance to reflect
177
190
  # that no changes should be made (since they can't be persisted).
178
191
  #
179
- # There's a series of callbacks associated with <tt>destroy!</tt>. If
180
- # the <tt>before_destroy</tt> callback return +false+ the action is cancelled
181
- # and <tt>destroy!</tt> raises ActiveRecord::RecordNotDestroyed. See
182
- # ActiveRecord::Callbacks for further details.
192
+ # There's a series of callbacks associated with #destroy!. If the
193
+ # <tt>before_destroy</tt> callback throws +:abort+ the action is cancelled
194
+ # and #destroy! raises ActiveRecord::RecordNotDestroyed.
195
+ # See ActiveRecord::Callbacks for further details.
183
196
  def destroy!
184
- destroy || raise(ActiveRecord::RecordNotDestroyed, self)
197
+ destroy || _raise_record_not_destroyed
185
198
  end
186
199
 
187
200
  # Returns an instance of the specified +klass+ with the attributes of the
@@ -193,18 +206,21 @@ module ActiveRecord
193
206
  # instance using the companies/company partial instead of clients/client.
194
207
  #
195
208
  # Note: The new instance will share a link to the same attributes as the original class.
196
- # So any change to the attributes in either instance will affect the other.
209
+ # Therefore the sti column value will still be the same.
210
+ # Any change to the attributes on either instance will affect both instances.
211
+ # If you want to change the sti column as well, use #becomes! instead.
197
212
  def becomes(klass)
198
213
  became = klass.new
199
214
  became.instance_variable_set("@attributes", @attributes)
200
- became.instance_variable_set("@changed_attributes", @changed_attributes) if defined?(@changed_attributes)
215
+ became.instance_variable_set("@mutation_tracker", @mutation_tracker) if defined?(@mutation_tracker)
216
+ became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
201
217
  became.instance_variable_set("@new_record", new_record?)
202
218
  became.instance_variable_set("@destroyed", destroyed?)
203
- became.instance_variable_set("@errors", errors)
219
+ became.errors.copy!(errors)
204
220
  became
205
221
  end
206
222
 
207
- # Wrapper around +becomes+ that also changes the instance's sti column value.
223
+ # Wrapper around #becomes that also changes the instance's sti column value.
208
224
  # This is especially useful if you want to persist the changed class in your
209
225
  # database.
210
226
  #
@@ -224,19 +240,19 @@ module ActiveRecord
224
240
  # This is especially useful for boolean flags on existing records. Also note that
225
241
  #
226
242
  # * Validation is skipped.
227
- # * Callbacks are invoked.
243
+ # * \Callbacks are invoked.
228
244
  # * updated_at/updated_on column is updated if that column is available.
229
245
  # * Updates all the attributes that are dirty in this object.
230
246
  #
231
- # This method raises an +ActiveRecord::ActiveRecordError+ if the
247
+ # This method raises an ActiveRecord::ActiveRecordError if the
232
248
  # attribute is marked as readonly.
233
249
  #
234
- # See also +update_column+.
250
+ # Also see #update_column.
235
251
  def update_attribute(name, value)
236
252
  name = name.to_s
237
253
  verify_readonly_attribute(name)
238
- send("#{name}=", value)
239
- save(validate: false)
254
+ public_send("#{name}=", value)
255
+ save(validate: false) if changed?
240
256
  end
241
257
 
242
258
  # Updates the attributes of the model from the passed-in hash and saves the
@@ -253,8 +269,8 @@ module ActiveRecord
253
269
 
254
270
  alias update_attributes update
255
271
 
256
- # Updates its receiver just like +update+ but calls <tt>save!</tt> instead
257
- # of +save+, so an exception is raised if the record is invalid.
272
+ # Updates its receiver just like #update but calls #save! instead
273
+ # of +save+, so an exception is raised if the record is invalid and saving will fail.
258
274
  def update!(attributes)
259
275
  # The following transaction covers any possible database side-effects of the
260
276
  # attributes assignment. For example, setting the IDs of a child collection.
@@ -280,11 +296,12 @@ module ActiveRecord
280
296
  # the database, but take into account that in consequence the regular update
281
297
  # procedures are totally bypassed. In particular:
282
298
  #
283
- # * Validations are skipped.
284
- # * Callbacks are skipped.
299
+ # * \Validations are skipped.
300
+ # * \Callbacks are skipped.
285
301
  # * +updated_at+/+updated_on+ are not updated.
302
+ # * However, attributes are serialized with the same rules as ActiveRecord::Relation#update_all
286
303
  #
287
- # This method raises an +ActiveRecord::ActiveRecordError+ when called on new
304
+ # This method raises an ActiveRecord::ActiveRecordError when called on new
288
305
  # objects, or when at least one of the attributes is marked as readonly.
289
306
  def update_columns(attributes)
290
307
  raise ActiveRecordError, "cannot update a new record" if new_record?
@@ -312,42 +329,52 @@ module ActiveRecord
312
329
  self
313
330
  end
314
331
 
315
- # Wrapper around +increment+ that saves the record. This method differs from
332
+ # Wrapper around #increment that saves the record. This method differs from
316
333
  # its non-bang version in that it passes through the attribute setter.
317
334
  # Saving is not subjected to validation checks. Returns +true+ if the
318
335
  # record could be saved.
319
336
  def increment!(attribute, by = 1)
320
- increment(attribute, by).update_attribute(attribute, self[attribute])
337
+ increment(attribute, by)
338
+ change = public_send(attribute) - (attribute_was(attribute.to_s) || 0)
339
+ self.class.update_counters(id, attribute => change)
340
+ clear_attribute_change(attribute) # eww
341
+ self
321
342
  end
322
343
 
323
344
  # Initializes +attribute+ to zero if +nil+ and subtracts the value passed as +by+ (default is 1).
324
345
  # The decrement is performed directly on the underlying attribute, no setter is invoked.
325
346
  # Only makes sense for number-based attributes. Returns +self+.
326
347
  def decrement(attribute, by = 1)
327
- self[attribute] ||= 0
328
- self[attribute] -= by
329
- self
348
+ increment(attribute, -by)
330
349
  end
331
350
 
332
- # Wrapper around +decrement+ that saves the record. This method differs from
333
- # its non-bang version in that it passes through the attribute setter.
351
+ # Wrapper around #decrement that saves the record. This method differs from
352
+ # its non-bang version in the sense that it passes through the attribute setter.
334
353
  # Saving is not subjected to validation checks. Returns +true+ if the
335
354
  # record could be saved.
336
355
  def decrement!(attribute, by = 1)
337
- decrement(attribute, by).update_attribute(attribute, self[attribute])
356
+ increment!(attribute, -by)
338
357
  end
339
358
 
340
359
  # Assigns to +attribute+ the boolean opposite of <tt>attribute?</tt>. So
341
360
  # if the predicate returns +true+ the attribute will become +false+. This
342
361
  # method toggles directly the underlying value without calling any setter.
343
362
  # Returns +self+.
363
+ #
364
+ # Example:
365
+ #
366
+ # user = User.first
367
+ # user.banned? # => false
368
+ # user.toggle(:banned)
369
+ # user.banned? # => true
370
+ #
344
371
  def toggle(attribute)
345
- self[attribute] = !send("#{attribute}?")
372
+ self[attribute] = !public_send("#{attribute}?")
346
373
  self
347
374
  end
348
375
 
349
- # Wrapper around +toggle+ that saves the record. This method differs from
350
- # its non-bang version in that it passes through the attribute setter.
376
+ # Wrapper around #toggle that saves the record. This method differs from
377
+ # its non-bang version in the sense that it passes through the attribute setter.
351
378
  # Saving is not subjected to validation checks. Returns +true+ if the
352
379
  # record could be saved.
353
380
  def toggle!(attribute)
@@ -367,9 +394,9 @@ module ActiveRecord
367
394
  # # => #<Account id: 1, email: 'account@example.com'>
368
395
  #
369
396
  # Attributes are reloaded from the database, and caches busted, in
370
- # particular the associations cache.
397
+ # particular the associations cache and the QueryCache.
371
398
  #
372
- # If the record no longer exists in the database <tt>ActiveRecord::RecordNotFound</tt>
399
+ # If the record no longer exists in the database ActiveRecord::RecordNotFound
373
400
  # is raised. Otherwise, in addition to the in-place modification the method
374
401
  # returns +self+ for convenience.
375
402
  #
@@ -403,8 +430,7 @@ module ActiveRecord
403
430
  # end
404
431
  #
405
432
  def reload(options = nil)
406
- clear_aggregation_cache
407
- clear_association_cache
433
+ self.class.connection.clear_query_cache
408
434
 
409
435
  fresh_object =
410
436
  if options && options[:lock]
@@ -418,19 +444,22 @@ module ActiveRecord
418
444
  self
419
445
  end
420
446
 
421
- # Saves the record with the updated_at/on attributes set to the current time.
447
+ # Saves the record with the updated_at/on attributes set to the current time
448
+ # or the time specified.
422
449
  # Please note that no validation is performed and only the +after_touch+,
423
450
  # +after_commit+ and +after_rollback+ callbacks are executed.
424
451
  #
452
+ # This method can be passed attribute names and an optional time argument.
425
453
  # If attribute names are passed, they are updated along with updated_at/on
426
- # attributes.
454
+ # attributes. If no time argument is passed, the current time is used as default.
427
455
  #
428
- # product.touch # updates updated_at/on
456
+ # product.touch # updates updated_at/on with current time
457
+ # product.touch(time: Time.new(2015, 2, 16, 0, 0, 0)) # updates updated_at/on with specified time
429
458
  # product.touch(:designed_at) # updates the designed_at attribute and updated_at/on
430
459
  # product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
431
460
  #
432
- # If used along with +belongs_to+ then +touch+ will invoke +touch+ method on
433
- # associated object.
461
+ # If used along with {belongs_to}[rdoc-ref:Associations::ClassMethods#belongs_to]
462
+ # then +touch+ will invoke +touch+ method on associated object.
434
463
  #
435
464
  # class Brake < ActiveRecord::Base
436
465
  # belongs_to :car, touch: true
@@ -449,26 +478,38 @@ module ActiveRecord
449
478
  # ball = Ball.new
450
479
  # ball.touch(:updated_at) # => raises ActiveRecordError
451
480
  #
452
- def touch(*names)
481
+ def touch(*names, time: nil)
453
482
  raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
454
483
 
484
+ time ||= current_time_from_proper_timezone
455
485
  attributes = timestamp_attributes_for_update_in_model
456
486
  attributes.concat(names)
457
487
 
458
488
  unless attributes.empty?
459
- current_time = current_time_from_proper_timezone
460
489
  changes = {}
461
490
 
462
491
  attributes.each do |column|
463
492
  column = column.to_s
464
- changes[column] = write_attribute(column, current_time)
493
+ changes[column] = write_attribute(column, time)
465
494
  end
466
495
 
467
- changes[self.class.locking_column] = increment_lock if locking_enabled?
468
-
469
496
  clear_attribute_changes(changes.keys)
470
497
  primary_key = self.class.primary_key
471
- self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1
498
+ scope = self.class.unscoped.where(primary_key => _read_attribute(primary_key))
499
+
500
+ if locking_enabled?
501
+ locking_column = self.class.locking_column
502
+ scope = scope.where(locking_column => _read_attribute(locking_column))
503
+ changes[locking_column] = increment_lock
504
+ end
505
+
506
+ result = scope.update_all(changes) == 1
507
+
508
+ if !result && locking_enabled?
509
+ raise ActiveRecord::StaleObjectError.new(self, "touch")
510
+ end
511
+
512
+ result
472
513
  else
473
514
  true
474
515
  end
@@ -485,20 +526,12 @@ module ActiveRecord
485
526
  end
486
527
 
487
528
  def relation_for_destroy
488
- pk = self.class.primary_key
489
- column = self.class.columns_hash[pk]
490
- substitute = self.class.connection.substitute_at(column)
491
-
492
- relation = self.class.unscoped.where(
493
- self.class.arel_table[pk].eq(substitute))
494
-
495
- relation.bind_values = [[column, id]]
496
- relation
529
+ self.class.unscoped.where(self.class.primary_key => id)
497
530
  end
498
531
 
499
- def create_or_update
532
+ def create_or_update(*args)
500
533
  raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
501
- result = new_record? ? _create_record : _update_record
534
+ result = new_record? ? _create_record : _update_record(*args)
502
535
  result != false
503
536
  end
504
537
 
@@ -528,5 +561,16 @@ module ActiveRecord
528
561
  def verify_readonly_attribute(name)
529
562
  raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name)
530
563
  end
564
+
565
+ def _raise_record_not_destroyed
566
+ @_association_destroy_exception ||= nil
567
+ raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy the record", self)
568
+ ensure
569
+ @_association_destroy_exception = nil
570
+ end
571
+
572
+ def belongs_to_touch_method
573
+ :touch
574
+ end
531
575
  end
532
576
  end
@@ -5,7 +5,7 @@ module ActiveRecord
5
5
  # Enable the query cache within the block if Active Record is configured.
6
6
  # If it's not, it will execute the given block.
7
7
  def cache(&block)
8
- if ActiveRecord::Base.connected?
8
+ if connected?
9
9
  connection.cache(&block)
10
10
  else
11
11
  yield
@@ -15,7 +15,7 @@ module ActiveRecord
15
15
  # Disable the query cache within the block if Active Record is configured.
16
16
  # If it's not, it will execute the given block.
17
17
  def uncached(&block)
18
- if ActiveRecord::Base.connected?
18
+ if connected?
19
19
  connection.uncached(&block)
20
20
  else
21
21
  yield
@@ -23,34 +23,31 @@ module ActiveRecord
23
23
  end
24
24
  end
25
25
 
26
- def initialize(app)
27
- @app = app
28
- end
29
-
30
- def call(env)
26
+ def self.run
31
27
  connection = ActiveRecord::Base.connection
32
28
  enabled = connection.query_cache_enabled
33
29
  connection_id = ActiveRecord::Base.connection_id
34
30
  connection.enable_query_cache!
35
31
 
36
- response = @app.call(env)
37
- response[2] = Rack::BodyProxy.new(response[2]) do
38
- restore_query_cache_settings(connection_id, enabled)
39
- end
40
-
41
- response
42
- rescue Exception => e
43
- restore_query_cache_settings(connection_id, enabled)
44
- raise e
32
+ [enabled, connection_id]
45
33
  end
46
34
 
47
- private
35
+ def self.complete(state)
36
+ enabled, connection_id = state
48
37
 
49
- def restore_query_cache_settings(connection_id, enabled)
50
38
  ActiveRecord::Base.connection_id = connection_id
51
39
  ActiveRecord::Base.connection.clear_query_cache
52
40
  ActiveRecord::Base.connection.disable_query_cache! unless enabled
53
41
  end
54
42
 
43
+ def self.install_executor_hooks(executor = ActiveSupport::Executor)
44
+ executor.register_hook(self)
45
+
46
+ executor.to_complete do
47
+ unless ActiveRecord::Base.connection.transaction_open?
48
+ ActiveRecord::Base.clear_active_connections!
49
+ end
50
+ end
51
+ end
55
52
  end
56
53
  end
@@ -1,13 +1,13 @@
1
1
  module ActiveRecord
2
2
  module Querying
3
- delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, to: :all
4
- delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, to: :all
3
+ delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
4
+ delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!, to: :all
5
5
  delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
6
6
  delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
7
7
  delegate :find_by, :find_by!, to: :all
8
8
  delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, to: :all
9
- delegate :find_each, :find_in_batches, to: :all
10
- delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins,
9
+ delegate :find_each, :find_in_batches, :in_batches, to: :all
10
+ delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
11
11
  :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly,
12
12
  :having, :create_with, :uniq, :distinct, :references, :none, :unscope, to: :all
13
13
  delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
@@ -35,8 +35,8 @@ module ActiveRecord
35
35
  #
36
36
  # Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
37
37
  # Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
38
- def find_by_sql(sql, binds = [])
39
- result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds)
38
+ def find_by_sql(sql, binds = [], preparable: nil)
39
+ result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
40
40
  column_types = result_set.column_types.dup
41
41
  columns_hash.each_key { |k| column_types.delete k }
42
42
  message_bus = ActiveSupport::Notifications.instrumenter
@@ -55,11 +55,12 @@ module ActiveRecord
55
55
  # The use of this method should be restricted to complicated SQL queries that can't be executed
56
56
  # using the ActiveRecord::Calculations class methods. Look into those before using this.
57
57
  #
58
- # ==== Parameters
58
+ # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
59
+ # # => 12
59
60
  #
60
- # * +sql+ - An SQL statement which should return a count query from the database, see the example below.
61
+ # ==== Parameters
61
62
  #
62
- # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
63
+ # * +sql+ - An SQL statement which should return a count query from the database, see the example above.
63
64
  def count_by_sql(sql)
64
65
  sql = sanitize_conditions(sql)
65
66
  connection.select_value(sql, "#{name} Count").to_i
@@ -16,12 +16,6 @@ module ActiveRecord
16
16
  config.app_generators.orm :active_record, :migration => true,
17
17
  :timestamps => true
18
18
 
19
- config.app_middleware.insert_after "::ActionDispatch::Callbacks",
20
- "ActiveRecord::QueryCache"
21
-
22
- config.app_middleware.insert_after "::ActionDispatch::Callbacks",
23
- "ActiveRecord::ConnectionAdapters::ConnectionManagement"
24
-
25
19
  config.action_dispatch.rescue_responses.merge!(
26
20
  'ActiveRecord::RecordNotFound' => :not_found,
27
21
  'ActiveRecord::StaleObjectError' => :conflict,
@@ -40,7 +34,7 @@ module ActiveRecord
40
34
  task :load_config do
41
35
  ActiveRecord::Tasks::DatabaseTasks.database_configuration = Rails.application.config.database_configuration
42
36
 
43
- if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH)
37
+ if defined?(ENGINE_ROOT) && engine = Rails::Engine.find(ENGINE_ROOT)
44
38
  if engine.paths['db/migrate'].existent
45
39
  ActiveRecord::Tasks::DatabaseTasks.migrations_paths += engine.paths['db/migrate'].to_a
46
40
  end
@@ -57,8 +51,10 @@ module ActiveRecord
57
51
  console do |app|
58
52
  require "active_record/railties/console_sandbox" if app.sandbox?
59
53
  require "active_record/base"
60
- console = ActiveSupport::Logger.new(STDERR)
61
- Rails.logger.extend ActiveSupport::Logger.broadcast console
54
+ unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDERR, STDOUT)
55
+ console = ActiveSupport::Logger.new(STDERR)
56
+ Rails.logger.extend ActiveSupport::Logger.broadcast console
57
+ end
62
58
  end
63
59
 
64
60
  runner do
@@ -78,8 +74,8 @@ module ActiveRecord
78
74
 
79
75
  initializer "active_record.migration_error" do
80
76
  if config.active_record.delete(:migration_error) == :page_load
81
- config.app_middleware.insert_after "::ActionDispatch::Callbacks",
82
- "ActiveRecord::Migration::CheckPending"
77
+ config.app_middleware.insert_after ::ActionDispatch::Callbacks,
78
+ ActiveRecord::Migration::CheckPending
83
79
  end
84
80
  end
85
81
 
@@ -93,6 +89,7 @@ module ActiveRecord
93
89
  cache = Marshal.load File.binread filename
94
90
  if cache.version == ActiveRecord::Migrator.current_version
95
91
  self.connection.schema_cache = cache
92
+ self.connection_pool.schema_cache = cache.dup
96
93
  else
97
94
  warn "Ignoring db/schema_cache.dump because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
98
95
  end
@@ -102,6 +99,14 @@ module ActiveRecord
102
99
  end
103
100
  end
104
101
 
102
+ initializer "active_record.warn_on_records_fetched_greater_than" do
103
+ if config.active_record.warn_on_records_fetched_greater_than
104
+ ActiveSupport.on_load(:active_record) do
105
+ require 'active_record/relation/record_fetch_warning'
106
+ end
107
+ end
108
+ end
109
+
105
110
  initializer "active_record.set_configs" do |app|
106
111
  ActiveSupport.on_load(:active_record) do
107
112
  app.config.active_record.each do |k,v|
@@ -112,7 +117,7 @@ module ActiveRecord
112
117
 
113
118
  # This sets the database configuration from Configuration#database_configuration
114
119
  # and then establishes the connection.
115
- initializer "active_record.initialize_database" do |app|
120
+ initializer "active_record.initialize_database" do
116
121
  ActiveSupport.on_load(:active_record) do
117
122
  self.configurations = Rails.application.config.database_configuration
118
123
 
@@ -125,8 +130,8 @@ Oops - You have a database configured, but it doesn't exist yet!
125
130
  Here's how to get started:
126
131
 
127
132
  1. Configure your database in config/database.yml.
128
- 2. Run `bin/rake db:create` to create the database.
129
- 3. Run `bin/rake db:setup` to load your database schema.
133
+ 2. Run `bin/rails db:create` to create the database.
134
+ 3. Run `bin/rails db:setup` to load your database schema.
130
135
  end_warning
131
136
  raise
132
137
  end
@@ -141,19 +146,23 @@ end_warning
141
146
  end
142
147
  end
143
148
 
144
- initializer "active_record.set_reloader_hooks" do |app|
145
- hook = app.config.reload_classes_only_on_change ? :to_prepare : :to_cleanup
146
-
149
+ initializer "active_record.set_reloader_hooks" do
147
150
  ActiveSupport.on_load(:active_record) do
148
- ActionDispatch::Reloader.send(hook) do
151
+ ActiveSupport::Reloader.before_class_unload do
149
152
  if ActiveRecord::Base.connected?
150
- ActiveRecord::Base.clear_reloadable_connections!
151
153
  ActiveRecord::Base.clear_cache!
154
+ ActiveRecord::Base.clear_reloadable_connections!
152
155
  end
153
156
  end
154
157
  end
155
158
  end
156
159
 
160
+ initializer "active_record.set_executor_hooks" do
161
+ ActiveSupport.on_load(:active_record) do
162
+ ActiveRecord::QueryCache.install_executor_hooks
163
+ end
164
+ end
165
+
157
166
  initializer "active_record.add_watchable_files" do |app|
158
167
  path = app.paths["db"].first
159
168
  config.watchable_files.concat ["#{path}/schema.rb", "#{path}/structure.sql"]
@@ -19,7 +19,7 @@ module ActiveRecord
19
19
  end
20
20
 
21
21
  def cleanup_view_runtime
22
- if ActiveRecord::Base.connected?
22
+ if logger.info? && ActiveRecord::Base.connected?
23
23
  db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
24
24
  self.db_runtime = (db_runtime || 0) + db_rt_before_render
25
25
  runtime = super