activerecord 4.2.11.3 → 5.0.0.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 (246) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1281 -1204
  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 +35 -24
  8. data/lib/active_record/association_relation.rb +3 -3
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +11 -9
  11. data/lib/active_record/associations/association_scope.rb +73 -102
  12. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  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 +7 -19
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  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 +49 -41
  21. data/lib/active_record/associations/collection_proxy.rb +67 -27
  22. data/lib/active_record/associations/foreign_association.rb +1 -1
  23. data/lib/active_record/associations/has_many_association.rb +20 -71
  24. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  25. data/lib/active_record/associations/has_one_association.rb +12 -5
  26. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  27. data/lib/active_record/associations/join_dependency.rb +29 -19
  28. data/lib/active_record/associations/preloader/association.rb +46 -52
  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 +14 -4
  34. data/lib/active_record/associations/singular_association.rb +7 -1
  35. data/lib/active_record/associations/through_association.rb +11 -3
  36. data/lib/active_record/associations.rb +317 -209
  37. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute_assignment.rb +19 -140
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  42. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  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 +61 -14
  48. data/lib/active_record/attribute_methods/write.rb +13 -37
  49. data/lib/active_record/attribute_methods.rb +76 -47
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set/builder.rb +6 -4
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attributes.rb +199 -81
  54. data/lib/active_record/autosave_association.rb +49 -16
  55. data/lib/active_record/base.rb +32 -23
  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 +452 -182
  61. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  62. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  63. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  64. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  65. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  66. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -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 +380 -141
  70. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  71. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  72. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  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 +29 -166
  85. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  86. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  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 -57
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -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 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  100. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  105. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  106. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  107. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  108. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  109. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  110. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  111. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  112. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  113. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  114. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  115. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  117. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  118. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  119. data/lib/active_record/connection_handling.rb +37 -14
  120. data/lib/active_record/core.rb +89 -107
  121. data/lib/active_record/counter_cache.rb +13 -24
  122. data/lib/active_record/dynamic_matchers.rb +1 -20
  123. data/lib/active_record/enum.rb +113 -76
  124. data/lib/active_record/errors.rb +87 -48
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +1 -1
  127. data/lib/active_record/fixture_set/file.rb +26 -5
  128. data/lib/active_record/fixtures.rb +76 -40
  129. data/lib/active_record/gem_version.rb +4 -4
  130. data/lib/active_record/inheritance.rb +32 -40
  131. data/lib/active_record/integration.rb +4 -4
  132. data/lib/active_record/internal_metadata.rb +56 -0
  133. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  134. data/lib/active_record/locale/en.yml +3 -2
  135. data/lib/active_record/locking/optimistic.rb +15 -15
  136. data/lib/active_record/locking/pessimistic.rb +1 -1
  137. data/lib/active_record/log_subscriber.rb +43 -21
  138. data/lib/active_record/migration/command_recorder.rb +59 -18
  139. data/lib/active_record/migration/compatibility.rb +126 -0
  140. data/lib/active_record/migration.rb +363 -133
  141. data/lib/active_record/model_schema.rb +129 -41
  142. data/lib/active_record/nested_attributes.rb +58 -29
  143. data/lib/active_record/null_relation.rb +16 -8
  144. data/lib/active_record/persistence.rb +121 -80
  145. data/lib/active_record/query_cache.rb +15 -18
  146. data/lib/active_record/querying.rb +10 -9
  147. data/lib/active_record/railtie.rb +23 -16
  148. data/lib/active_record/railties/controller_runtime.rb +1 -1
  149. data/lib/active_record/railties/databases.rake +69 -46
  150. data/lib/active_record/readonly_attributes.rb +1 -1
  151. data/lib/active_record/reflection.rb +282 -115
  152. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  153. data/lib/active_record/relation/batches.rb +139 -34
  154. data/lib/active_record/relation/calculations.rb +79 -108
  155. data/lib/active_record/relation/delegation.rb +7 -20
  156. data/lib/active_record/relation/finder_methods.rb +163 -81
  157. data/lib/active_record/relation/from_clause.rb +32 -0
  158. data/lib/active_record/relation/merger.rb +16 -42
  159. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  160. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  161. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  162. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  163. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  166. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  167. data/lib/active_record/relation/predicate_builder.rb +120 -107
  168. data/lib/active_record/relation/query_attribute.rb +19 -0
  169. data/lib/active_record/relation/query_methods.rb +308 -244
  170. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  171. data/lib/active_record/relation/spawn_methods.rb +4 -7
  172. data/lib/active_record/relation/where_clause.rb +174 -0
  173. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  174. data/lib/active_record/relation.rb +176 -116
  175. data/lib/active_record/result.rb +4 -3
  176. data/lib/active_record/runtime_registry.rb +1 -1
  177. data/lib/active_record/sanitization.rb +95 -66
  178. data/lib/active_record/schema.rb +26 -22
  179. data/lib/active_record/schema_dumper.rb +62 -38
  180. data/lib/active_record/schema_migration.rb +11 -14
  181. data/lib/active_record/scoping/default.rb +23 -9
  182. data/lib/active_record/scoping/named.rb +49 -28
  183. data/lib/active_record/scoping.rb +32 -15
  184. data/lib/active_record/secure_token.rb +38 -0
  185. data/lib/active_record/serialization.rb +2 -4
  186. data/lib/active_record/statement_cache.rb +16 -14
  187. data/lib/active_record/store.rb +8 -3
  188. data/lib/active_record/suppressor.rb +58 -0
  189. data/lib/active_record/table_metadata.rb +68 -0
  190. data/lib/active_record/tasks/database_tasks.rb +57 -43
  191. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  192. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  193. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  194. data/lib/active_record/timestamp.rb +20 -9
  195. data/lib/active_record/touch_later.rb +58 -0
  196. data/lib/active_record/transactions.rb +138 -56
  197. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  198. data/lib/active_record/type/date.rb +2 -45
  199. data/lib/active_record/type/date_time.rb +2 -49
  200. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  201. data/lib/active_record/type/internal/timezone.rb +15 -0
  202. data/lib/active_record/type/serialized.rb +15 -14
  203. data/lib/active_record/type/time.rb +10 -16
  204. data/lib/active_record/type/type_map.rb +4 -4
  205. data/lib/active_record/type.rb +66 -17
  206. data/lib/active_record/type_caster/connection.rb +29 -0
  207. data/lib/active_record/type_caster/map.rb +19 -0
  208. data/lib/active_record/type_caster.rb +7 -0
  209. data/lib/active_record/validations/absence.rb +23 -0
  210. data/lib/active_record/validations/associated.rb +10 -3
  211. data/lib/active_record/validations/length.rb +24 -0
  212. data/lib/active_record/validations/presence.rb +11 -12
  213. data/lib/active_record/validations/uniqueness.rb +30 -29
  214. data/lib/active_record/validations.rb +33 -32
  215. data/lib/active_record.rb +8 -4
  216. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  217. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  218. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  219. data/lib/rails/generators/active_record/migration.rb +7 -0
  220. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  221. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  222. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  223. metadata +60 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  225. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  226. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  227. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  228. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  229. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  231. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  232. data/lib/active_record/type/big_integer.rb +0 -13
  233. data/lib/active_record/type/binary.rb +0 -50
  234. data/lib/active_record/type/boolean.rb +0 -31
  235. data/lib/active_record/type/decimal.rb +0 -64
  236. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  237. data/lib/active_record/type/decorator.rb +0 -14
  238. data/lib/active_record/type/float.rb +0 -19
  239. data/lib/active_record/type/integer.rb +0 -59
  240. data/lib/active_record/type/mutable.rb +0 -16
  241. data/lib/active_record/type/numeric.rb +0 -36
  242. data/lib/active_record/type/string.rb +0 -40
  243. data/lib/active_record/type/text.rb +0 -11
  244. data/lib/active_record/type/time_value.rb +0 -38
  245. data/lib/active_record/type/unsigned_integer.rb +0 -15
  246. data/lib/active_record/type/value.rb +0 -110
@@ -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("Failed to save the record", 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,10 +173,10 @@ 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
@@ -177,12 +189,12 @@ module ActiveRecord
177
189
  # Deletes the record in the database and freezes this instance to reflect
178
190
  # that no changes should be made (since they can't be persisted).
179
191
  #
180
- # There's a series of callbacks associated with <tt>destroy!</tt>. If
181
- # the <tt>before_destroy</tt> callback return +false+ the action is cancelled
182
- # and <tt>destroy!</tt> raises ActiveRecord::RecordNotDestroyed. See
183
- # 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.
184
196
  def destroy!
185
- destroy || raise(RecordNotDestroyed.new("Failed to destroy the record", self))
197
+ destroy || _raise_record_not_destroyed
186
198
  end
187
199
 
188
200
  # Returns an instance of the specified +klass+ with the attributes of the
@@ -194,19 +206,21 @@ module ActiveRecord
194
206
  # instance using the companies/company partial instead of clients/client.
195
207
  #
196
208
  # Note: The new instance will share a link to the same attributes as the original class.
197
- # 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.
198
212
  def becomes(klass)
199
213
  became = klass.new
200
214
  became.instance_variable_set("@attributes", @attributes)
201
- changed_attributes = @changed_attributes if defined?(@changed_attributes)
202
- became.instance_variable_set("@changed_attributes", 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)
203
217
  became.instance_variable_set("@new_record", new_record?)
204
218
  became.instance_variable_set("@destroyed", destroyed?)
205
- became.instance_variable_set("@errors", errors)
219
+ became.errors.copy!(errors)
206
220
  became
207
221
  end
208
222
 
209
- # 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.
210
224
  # This is especially useful if you want to persist the changed class in your
211
225
  # database.
212
226
  #
@@ -226,19 +240,19 @@ module ActiveRecord
226
240
  # This is especially useful for boolean flags on existing records. Also note that
227
241
  #
228
242
  # * Validation is skipped.
229
- # * Callbacks are invoked.
243
+ # * \Callbacks are invoked.
230
244
  # * updated_at/updated_on column is updated if that column is available.
231
245
  # * Updates all the attributes that are dirty in this object.
232
246
  #
233
- # This method raises an +ActiveRecord::ActiveRecordError+ if the
247
+ # This method raises an ActiveRecord::ActiveRecordError if the
234
248
  # attribute is marked as readonly.
235
249
  #
236
- # See also +update_column+.
250
+ # Also see #update_column.
237
251
  def update_attribute(name, value)
238
252
  name = name.to_s
239
253
  verify_readonly_attribute(name)
240
- send("#{name}=", value)
241
- save(validate: false)
254
+ public_send("#{name}=", value)
255
+ save(validate: false) if changed?
242
256
  end
243
257
 
244
258
  # Updates the attributes of the model from the passed-in hash and saves the
@@ -255,8 +269,8 @@ module ActiveRecord
255
269
 
256
270
  alias update_attributes update
257
271
 
258
- # Updates its receiver just like +update+ but calls <tt>save!</tt> instead
259
- # 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.
260
274
  def update!(attributes)
261
275
  # The following transaction covers any possible database side-effects of the
262
276
  # attributes assignment. For example, setting the IDs of a child collection.
@@ -282,11 +296,12 @@ module ActiveRecord
282
296
  # the database, but take into account that in consequence the regular update
283
297
  # procedures are totally bypassed. In particular:
284
298
  #
285
- # * Validations are skipped.
286
- # * Callbacks are skipped.
299
+ # * \Validations are skipped.
300
+ # * \Callbacks are skipped.
287
301
  # * +updated_at+/+updated_on+ are not updated.
302
+ # * However, attributes are serialized with the same rules as ActiveRecord::Relation#update_all
288
303
  #
289
- # This method raises an +ActiveRecord::ActiveRecordError+ when called on new
304
+ # This method raises an ActiveRecord::ActiveRecordError when called on new
290
305
  # objects, or when at least one of the attributes is marked as readonly.
291
306
  def update_columns(attributes)
292
307
  raise ActiveRecordError, "cannot update a new record" if new_record?
@@ -314,42 +329,52 @@ module ActiveRecord
314
329
  self
315
330
  end
316
331
 
317
- # Wrapper around +increment+ that saves the record. This method differs from
332
+ # Wrapper around #increment that saves the record. This method differs from
318
333
  # its non-bang version in that it passes through the attribute setter.
319
334
  # Saving is not subjected to validation checks. Returns +true+ if the
320
335
  # record could be saved.
321
336
  def increment!(attribute, by = 1)
322
- 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
323
342
  end
324
343
 
325
344
  # Initializes +attribute+ to zero if +nil+ and subtracts the value passed as +by+ (default is 1).
326
345
  # The decrement is performed directly on the underlying attribute, no setter is invoked.
327
346
  # Only makes sense for number-based attributes. Returns +self+.
328
347
  def decrement(attribute, by = 1)
329
- self[attribute] ||= 0
330
- self[attribute] -= by
331
- self
348
+ increment(attribute, -by)
332
349
  end
333
350
 
334
- # Wrapper around +decrement+ that saves the record. This method differs from
335
- # 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.
336
353
  # Saving is not subjected to validation checks. Returns +true+ if the
337
354
  # record could be saved.
338
355
  def decrement!(attribute, by = 1)
339
- decrement(attribute, by).update_attribute(attribute, self[attribute])
356
+ increment!(attribute, -by)
340
357
  end
341
358
 
342
359
  # Assigns to +attribute+ the boolean opposite of <tt>attribute?</tt>. So
343
360
  # if the predicate returns +true+ the attribute will become +false+. This
344
361
  # method toggles directly the underlying value without calling any setter.
345
362
  # Returns +self+.
363
+ #
364
+ # Example:
365
+ #
366
+ # user = User.first
367
+ # user.banned? # => false
368
+ # user.toggle(:banned)
369
+ # user.banned? # => true
370
+ #
346
371
  def toggle(attribute)
347
- self[attribute] = !send("#{attribute}?")
372
+ self[attribute] = !public_send("#{attribute}?")
348
373
  self
349
374
  end
350
375
 
351
- # Wrapper around +toggle+ that saves the record. This method differs from
352
- # 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.
353
378
  # Saving is not subjected to validation checks. Returns +true+ if the
354
379
  # record could be saved.
355
380
  def toggle!(attribute)
@@ -371,7 +396,7 @@ module ActiveRecord
371
396
  # Attributes are reloaded from the database, and caches busted, in
372
397
  # particular the associations cache and the QueryCache.
373
398
  #
374
- # 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
375
400
  # is raised. Otherwise, in addition to the in-place modification the method
376
401
  # returns +self+ for convenience.
377
402
  #
@@ -405,8 +430,6 @@ module ActiveRecord
405
430
  # end
406
431
  #
407
432
  def reload(options = nil)
408
- clear_aggregation_cache
409
- clear_association_cache
410
433
  self.class.connection.clear_query_cache
411
434
 
412
435
  fresh_object =
@@ -421,19 +444,22 @@ module ActiveRecord
421
444
  self
422
445
  end
423
446
 
424
- # 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.
425
449
  # Please note that no validation is performed and only the +after_touch+,
426
450
  # +after_commit+ and +after_rollback+ callbacks are executed.
427
451
  #
452
+ # This method can be passed attribute names and an optional time argument.
428
453
  # If attribute names are passed, they are updated along with updated_at/on
429
- # attributes.
454
+ # attributes. If no time argument is passed, the current time is used as default.
430
455
  #
431
- # 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
432
458
  # product.touch(:designed_at) # updates the designed_at attribute and updated_at/on
433
459
  # product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
434
460
  #
435
- # If used along with +belongs_to+ then +touch+ will invoke +touch+ method on
436
- # 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.
437
463
  #
438
464
  # class Brake < ActiveRecord::Base
439
465
  # belongs_to :car, touch: true
@@ -452,26 +478,38 @@ module ActiveRecord
452
478
  # ball = Ball.new
453
479
  # ball.touch(:updated_at) # => raises ActiveRecordError
454
480
  #
455
- def touch(*names)
481
+ def touch(*names, time: nil)
456
482
  raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
457
483
 
484
+ time ||= current_time_from_proper_timezone
458
485
  attributes = timestamp_attributes_for_update_in_model
459
486
  attributes.concat(names)
460
487
 
461
488
  unless attributes.empty?
462
- current_time = current_time_from_proper_timezone
463
489
  changes = {}
464
490
 
465
491
  attributes.each do |column|
466
492
  column = column.to_s
467
- changes[column] = write_attribute(column, current_time)
493
+ changes[column] = write_attribute(column, time)
468
494
  end
469
495
 
470
- changes[self.class.locking_column] = increment_lock if locking_enabled?
471
-
472
496
  clear_attribute_changes(changes.keys)
473
497
  primary_key = self.class.primary_key
474
- 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
475
513
  else
476
514
  true
477
515
  end
@@ -488,20 +526,12 @@ module ActiveRecord
488
526
  end
489
527
 
490
528
  def relation_for_destroy
491
- pk = self.class.primary_key
492
- column = self.class.columns_hash[pk]
493
- substitute = self.class.connection.substitute_at(column)
494
-
495
- relation = self.class.unscoped.where(
496
- self.class.arel_table[pk].eq(substitute))
497
-
498
- relation.bind_values = [[column, id]]
499
- relation
529
+ self.class.unscoped.where(self.class.primary_key => id)
500
530
  end
501
531
 
502
- def create_or_update
532
+ def create_or_update(*args)
503
533
  raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
504
- result = new_record? ? _create_record : _update_record
534
+ result = new_record? ? _create_record : _update_record(*args)
505
535
  result != false
506
536
  end
507
537
 
@@ -531,5 +561,16 @@ module ActiveRecord
531
561
  def verify_readonly_attribute(name)
532
562
  raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name)
533
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
534
575
  end
535
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
@@ -80,8 +74,8 @@ module ActiveRecord
80
74
 
81
75
  initializer "active_record.migration_error" do
82
76
  if config.active_record.delete(:migration_error) == :page_load
83
- config.app_middleware.insert_after "::ActionDispatch::Callbacks",
84
- "ActiveRecord::Migration::CheckPending"
77
+ config.app_middleware.insert_after ::ActionDispatch::Callbacks,
78
+ ActiveRecord::Migration::CheckPending
85
79
  end
86
80
  end
87
81
 
@@ -95,6 +89,7 @@ module ActiveRecord
95
89
  cache = Marshal.load File.binread filename
96
90
  if cache.version == ActiveRecord::Migrator.current_version
97
91
  self.connection.schema_cache = cache
92
+ self.connection_pool.schema_cache = cache.dup
98
93
  else
99
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}."
100
95
  end
@@ -104,6 +99,14 @@ module ActiveRecord
104
99
  end
105
100
  end
106
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
+
107
110
  initializer "active_record.set_configs" do |app|
108
111
  ActiveSupport.on_load(:active_record) do
109
112
  app.config.active_record.each do |k,v|
@@ -114,7 +117,7 @@ module ActiveRecord
114
117
 
115
118
  # This sets the database configuration from Configuration#database_configuration
116
119
  # and then establishes the connection.
117
- initializer "active_record.initialize_database" do |app|
120
+ initializer "active_record.initialize_database" do
118
121
  ActiveSupport.on_load(:active_record) do
119
122
  self.configurations = Rails.application.config.database_configuration
120
123
 
@@ -127,8 +130,8 @@ Oops - You have a database configured, but it doesn't exist yet!
127
130
  Here's how to get started:
128
131
 
129
132
  1. Configure your database in config/database.yml.
130
- 2. Run `bin/rake db:create` to create the database.
131
- 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.
132
135
  end_warning
133
136
  raise
134
137
  end
@@ -143,11 +146,9 @@ end_warning
143
146
  end
144
147
  end
145
148
 
146
- initializer "active_record.set_reloader_hooks" do |app|
147
- hook = app.config.reload_classes_only_on_change ? :to_prepare : :to_cleanup
148
-
149
+ initializer "active_record.set_reloader_hooks" do
149
150
  ActiveSupport.on_load(:active_record) do
150
- ActionDispatch::Reloader.send(hook) do
151
+ ActiveSupport::Reloader.before_class_unload do
151
152
  if ActiveRecord::Base.connected?
152
153
  ActiveRecord::Base.clear_cache!
153
154
  ActiveRecord::Base.clear_reloadable_connections!
@@ -156,6 +157,12 @@ end_warning
156
157
  end
157
158
  end
158
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
+
159
166
  initializer "active_record.add_watchable_files" do |app|
160
167
  path = app.paths["db"].first
161
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