activerecord 4.2.11.3 → 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 (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 +59 -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,11 +1,9 @@
1
1
  require 'yaml'
2
- require 'set'
3
2
  require 'active_support/benchmarkable'
4
3
  require 'active_support/dependencies'
5
4
  require 'active_support/descendants_tracker'
6
5
  require 'active_support/time'
7
6
  require 'active_support/core_ext/module/attribute_accessors'
8
- require 'active_support/core_ext/class/delegating_attributes'
9
7
  require 'active_support/core_ext/array/extract_options'
10
8
  require 'active_support/core_ext/hash/deep_merge'
11
9
  require 'active_support/core_ext/hash/slice'
@@ -15,13 +13,13 @@ require 'active_support/core_ext/kernel/singleton_class'
15
13
  require 'active_support/core_ext/module/introspection'
16
14
  require 'active_support/core_ext/object/duplicable'
17
15
  require 'active_support/core_ext/class/subclasses'
18
- require 'arel'
19
16
  require 'active_record/attribute_decorators'
20
17
  require 'active_record/errors'
21
18
  require 'active_record/log_subscriber'
22
19
  require 'active_record/explain_subscriber'
23
20
  require 'active_record/relation/delegation'
24
21
  require 'active_record/attributes'
22
+ require 'active_record/type_caster'
25
23
 
26
24
  module ActiveRecord #:nodoc:
27
25
  # = Active Record
@@ -133,14 +131,11 @@ module ActiveRecord #:nodoc:
133
131
  # end
134
132
  # end
135
133
  #
136
- # You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt>
137
- # or <tt>write_attribute(:attribute, value)</tt> and <tt>read_attribute(:attribute)</tt>.
138
- #
139
134
  # == Attribute query methods
140
135
  #
141
136
  # In addition to the basic accessors, query methods are also automatically available on the Active Record object.
142
137
  # Query methods allow you to test whether an attribute value is present.
143
- # For numeric values, present is defined as non-zero.
138
+ # Additionally, when dealing with numeric values, a query method will return false if the value is zero.
144
139
  #
145
140
  # For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
146
141
  # to determine whether the user has a name:
@@ -171,10 +166,11 @@ module ActiveRecord #:nodoc:
171
166
  # <tt>Person.find_by_user_name(user_name)</tt>.
172
167
  #
173
168
  # It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
174
- # <tt>ActiveRecord::RecordNotFound</tt> error if they do not return any records,
169
+ # ActiveRecord::RecordNotFound error if they do not return any records,
175
170
  # like <tt>Person.find_by_last_name!</tt>.
176
171
  #
177
- # It's also possible to use multiple attributes in the same find by separating them with "_and_".
172
+ # It's also possible to use multiple attributes in the same <tt>find_by_</tt> by separating them with
173
+ # "_and_".
178
174
  #
179
175
  # Person.find_by(user_name: user_name, password: password)
180
176
  # Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
@@ -186,7 +182,8 @@ module ActiveRecord #:nodoc:
186
182
  # == Saving arrays, hashes, and other non-mappable objects in text columns
187
183
  #
188
184
  # Active Record can serialize any object in text columns using YAML. To do so, you must
189
- # specify this with a call to the class method +serialize+.
185
+ # specify this with a call to the class method
186
+ # {serialize}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#serialize].
190
187
  # This makes it possible to store arrays, hashes, and other non-mappable objects without doing
191
188
  # any additional work.
192
189
  #
@@ -226,39 +223,47 @@ module ActiveRecord #:nodoc:
226
223
  #
227
224
  # == Connection to multiple databases in different models
228
225
  #
229
- # Connections are usually created through ActiveRecord::Base.establish_connection and retrieved
226
+ # Connections are usually created through
227
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] and retrieved
230
228
  # by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this
231
229
  # connection. But you can also set a class-specific connection. For example, if Course is an
232
230
  # ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
233
231
  # and Course and all of its subclasses will use this connection instead.
234
232
  #
235
233
  # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is
236
- # a Hash indexed by the class. If a connection is requested, the retrieve_connection method
234
+ # a hash indexed by the class. If a connection is requested, the
235
+ # {ActiveRecord::Base.retrieve_connection}[rdoc-ref:ConnectionHandling#retrieve_connection] method
237
236
  # will go up the class-hierarchy until a connection is found in the connection pool.
238
237
  #
239
238
  # == Exceptions
240
239
  #
241
240
  # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
242
- # * AdapterNotSpecified - The configuration hash used in <tt>establish_connection</tt> didn't include an
243
- # <tt>:adapter</tt> key.
244
- # * AdapterNotFound - The <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified a
245
- # non-existent adapter
241
+ # * AdapterNotSpecified - The configuration hash used in
242
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
243
+ # didn't include an <tt>:adapter</tt> key.
244
+ # * AdapterNotFound - The <tt>:adapter</tt> key used in
245
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
246
+ # specified a non-existent adapter
246
247
  # (or a bad spelling of an existing one).
247
248
  # * AssociationTypeMismatch - The object assigned to the association wasn't of the type
248
249
  # specified in the association definition.
249
250
  # * AttributeAssignmentError - An error occurred while doing a mass assignment through the
250
- # <tt>attributes=</tt> method.
251
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
251
252
  # You can inspect the +attribute+ property of the exception object to determine which attribute
252
253
  # triggered the error.
253
- # * ConnectionNotEstablished - No connection has been established. Use <tt>establish_connection</tt>
254
- # before querying.
254
+ # * ConnectionNotEstablished - No connection has been established.
255
+ # Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
255
256
  # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
256
- # <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of
257
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
258
+ # The +errors+ property of this exception contains an array of
257
259
  # AttributeAssignmentError
258
260
  # objects that should be inspected to determine which attributes triggered the errors.
259
- # * RecordInvalid - raised by save! and create! when the record is invalid.
260
- # * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
261
- # or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
261
+ # * RecordInvalid - raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
262
+ # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
263
+ # when the record is invalid.
264
+ # * RecordNotFound - No record responded to the {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method.
265
+ # Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.
266
+ # Some {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal
262
267
  # nothing was found, please check its documentation for further details.
263
268
  # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
264
269
  # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
@@ -280,6 +285,7 @@ module ActiveRecord #:nodoc:
280
285
  extend Explain
281
286
  extend Enum
282
287
  extend Delegation::DelegateCache
288
+ extend CollectionCacheKey
283
289
 
284
290
  include Core
285
291
  include Persistence
@@ -307,9 +313,12 @@ module ActiveRecord #:nodoc:
307
313
  include Aggregations
308
314
  include Transactions
309
315
  include NoTouching
316
+ include TouchLater
310
317
  include Reflection
311
318
  include Serialization
312
319
  include Store
320
+ include SecureToken
321
+ include Suppressor
313
322
  end
314
323
 
315
324
  ActiveSupport.run_load_hooks(:active_record, Base)
@@ -1,11 +1,11 @@
1
1
  module ActiveRecord
2
- # = Active Record Callbacks
2
+ # = Active Record \Callbacks
3
3
  #
4
- # Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
4
+ # \Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
5
5
  # before or after an alteration of the object state. This can be used to make sure that associated and
6
- # dependent objects are deleted when +destroy+ is called (by overwriting +before_destroy+) or to massage attributes
7
- # before they're validated (by overwriting +before_validation+). As an example of the callbacks initiated, consider
8
- # the <tt>Base#save</tt> call for a new record:
6
+ # dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] is called (by overwriting +before_destroy+) or
7
+ # to massage attributes before they're validated (by overwriting +before_validation+).
8
+ # As an example of the callbacks initiated, consider the {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] call for a new record:
9
9
  #
10
10
  # * (-) <tt>save</tt>
11
11
  # * (-) <tt>valid</tt>
@@ -20,7 +20,7 @@ module ActiveRecord
20
20
  # * (7) <tt>after_commit</tt>
21
21
  #
22
22
  # Also, an <tt>after_rollback</tt> callback can be configured to be triggered whenever a rollback is issued.
23
- # Check out <tt>ActiveRecord::Transactions</tt> for more details about <tt>after_commit</tt> and
23
+ # Check out ActiveRecord::Transactions for more details about <tt>after_commit</tt> and
24
24
  # <tt>after_rollback</tt>.
25
25
  #
26
26
  # Additionally, an <tt>after_touch</tt> callback is triggered whenever an
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  # are instantiated as well.
32
32
  #
33
33
  # There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the
34
- # Active Record life cycle. The sequence for calling <tt>Base#save</tt> for an existing record is similar,
34
+ # Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
35
35
  # except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
36
36
  #
37
37
  # Examples:
@@ -53,9 +53,9 @@ module ActiveRecord
53
53
  # end
54
54
  #
55
55
  # class Firm < ActiveRecord::Base
56
- # # Destroys the associated clients and people when the firm is destroyed
57
- # before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" }
58
- # before_destroy { |record| Client.destroy_all "client_of = #{record.id}" }
56
+ # # Disables access to the system, for associated clients and people when the firm is destroyed
57
+ # before_destroy { |record| Person.where(firm_id: record.id).update_all(access: 'disabled') }
58
+ # before_destroy { |record| Client.where(client_of: record.id).update_all(access: 'disabled') }
59
59
  # end
60
60
  #
61
61
  # == Inheritable callback queues
@@ -175,43 +175,30 @@ module ActiveRecord
175
175
  # end
176
176
  # end
177
177
  #
178
- # The callback macros usually accept a symbol for the method they're supposed to run, but you can also
179
- # pass a "method string", which will then be evaluated within the binding of the callback. Example:
180
- #
181
- # class Topic < ActiveRecord::Base
182
- # before_destroy 'self.class.delete_all "parent_id = #{id}"'
183
- # end
184
- #
185
- # Notice that single quotes (') are used so the <tt>#{id}</tt> part isn't evaluated until the callback
186
- # is triggered. Also note that these inline callbacks can be stacked just like the regular ones:
187
- #
188
- # class Topic < ActiveRecord::Base
189
- # before_destroy 'self.class.delete_all "parent_id = #{id}"',
190
- # 'puts "Evaluated after parents are destroyed"'
191
- # end
192
- #
193
178
  # == <tt>before_validation*</tt> returning statements
194
179
  #
195
- # If the returning value of a +before_validation+ callback can be evaluated to +false+, the process will be
196
- # aborted and <tt>Base#save</tt> will return +false+. If Base#save! is called it will raise a
197
- # ActiveRecord::RecordInvalid exception. Nothing will be appended to the errors object.
180
+ # If the +before_validation+ callback throws +:abort+, the process will be
181
+ # aborted and {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] will return +false+.
182
+ # If {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] is called it will raise an ActiveRecord::RecordInvalid exception.
183
+ # Nothing will be appended to the errors object.
198
184
  #
199
185
  # == Canceling callbacks
200
186
  #
201
- # If a <tt>before_*</tt> callback returns +false+, all the later callbacks and the associated action are
202
- # cancelled.
187
+ # If a <tt>before_*</tt> callback throws +:abort+, all the later callbacks and
188
+ # the associated action are cancelled.
203
189
  # Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
204
190
  # methods on the model, which are called last.
205
191
  #
206
192
  # == Ordering callbacks
207
193
  #
208
194
  # Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
209
- # callback (+log_children+ in this case) should be executed before the children get destroyed by the +dependent: destroy+ option.
195
+ # callback (+log_children+ in this case) should be executed before the children get destroyed by the
196
+ # <tt>dependent: :destroy</tt> option.
210
197
  #
211
198
  # Let's look at the code below:
212
199
  #
213
200
  # class Topic < ActiveRecord::Base
214
- # has_many :children, dependent: destroy
201
+ # has_many :children, dependent: :destroy
215
202
  #
216
203
  # before_destroy :log_children
217
204
  #
@@ -222,10 +209,11 @@ module ActiveRecord
222
209
  # end
223
210
  #
224
211
  # In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
225
- # because the +destroy+ callback gets executed first. You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
212
+ # because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback gets executed first.
213
+ # You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
226
214
  #
227
215
  # class Topic < ActiveRecord::Base
228
- # has_many :children, dependent: destroy
216
+ # has_many :children, dependent: :destroy
229
217
  #
230
218
  # before_destroy :log_children, prepend: true
231
219
  #
@@ -235,23 +223,23 @@ module ActiveRecord
235
223
  # end
236
224
  # end
237
225
  #
238
- # This way, the +before_destroy+ gets executed before the <tt>dependent: destroy</tt> is called, and the data is still available.
226
+ # This way, the +before_destroy+ gets executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
239
227
  #
240
- # == Transactions
228
+ # == \Transactions
241
229
  #
242
- # The entire callback chain of a +save+, <tt>save!</tt>, or +destroy+ call runs
243
- # within a transaction. That includes <tt>after_*</tt> hooks. If everything
244
- # goes fine a COMMIT is executed once the chain has been completed.
230
+ # The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!],
231
+ # or {#destroy}[rdoc-ref:Persistence#destroy] call runs within a transaction. That includes <tt>after_*</tt> hooks.
232
+ # If everything goes fine a COMMIT is executed once the chain has been completed.
245
233
  #
246
234
  # If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
247
235
  # can also trigger a ROLLBACK raising an exception in any of the callbacks,
248
236
  # including <tt>after_*</tt> hooks. Note, however, that in that case the client
249
- # needs to be aware of it because an ordinary +save+ will raise such exception
237
+ # needs to be aware of it because an ordinary {#save}[rdoc-ref:Persistence#save] will raise such exception
250
238
  # instead of quietly returning +false+.
251
239
  #
252
240
  # == Debugging callbacks
253
241
  #
254
- # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. ActiveModel Callbacks support
242
+ # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. Active Model \Callbacks support
255
243
  # <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
256
244
  # defines what part of the chain the callback runs in.
257
245
  #
@@ -277,7 +265,7 @@ module ActiveRecord
277
265
  :before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
278
266
  ]
279
267
 
280
- module ClassMethods
268
+ module ClassMethods # :nodoc:
281
269
  include ActiveModel::Callbacks
282
270
  end
283
271
 
@@ -289,7 +277,15 @@ module ActiveRecord
289
277
  end
290
278
 
291
279
  def destroy #:nodoc:
280
+ @_destroy_callback_already_called ||= false
281
+ return if @_destroy_callback_already_called
282
+ @_destroy_callback_already_called = true
292
283
  _run_destroy_callbacks { super }
284
+ rescue RecordNotDestroyed => e
285
+ @_association_destroy_exception = e
286
+ false
287
+ ensure
288
+ @_destroy_callback_already_called = false
293
289
  end
294
290
 
295
291
  def touch(*) #:nodoc:
@@ -298,7 +294,7 @@ module ActiveRecord
298
294
 
299
295
  private
300
296
 
301
- def create_or_update #:nodoc:
297
+ def create_or_update(*) #:nodoc:
302
298
  _run_save_callbacks { super }
303
299
  end
304
300
 
@@ -6,7 +6,7 @@ module ActiveRecord
6
6
  end
7
7
 
8
8
  def self.load(json)
9
- ActiveSupport::JSON.decode(json) unless json.nil?
9
+ ActiveSupport::JSON.decode(json) unless json.blank?
10
10
  end
11
11
  end
12
12
  end
@@ -8,15 +8,13 @@ module ActiveRecord
8
8
 
9
9
  def initialize(object_class = Object)
10
10
  @object_class = object_class
11
+ check_arity_of_constructor
11
12
  end
12
13
 
13
14
  def dump(obj)
14
15
  return if obj.nil?
15
16
 
16
- unless obj.is_a?(object_class)
17
- raise SerializationTypeMismatch,
18
- "Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
19
- end
17
+ assert_valid_value(obj)
20
18
  YAML.dump obj
21
19
  end
22
20
 
@@ -25,14 +23,28 @@ module ActiveRecord
25
23
  return yaml unless yaml.is_a?(String) && yaml =~ /^---/
26
24
  obj = YAML.load(yaml)
27
25
 
28
- unless obj.is_a?(object_class) || obj.nil?
29
- raise SerializationTypeMismatch,
30
- "Attribute was supposed to be a #{object_class}, but was a #{obj.class}"
31
- end
26
+ assert_valid_value(obj)
32
27
  obj ||= object_class.new if object_class != Object
33
28
 
34
29
  obj
35
30
  end
31
+
32
+ def assert_valid_value(obj)
33
+ unless obj.nil? || obj.is_a?(object_class)
34
+ raise SerializationTypeMismatch,
35
+ "Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def check_arity_of_constructor
42
+ begin
43
+ load(nil)
44
+ rescue ArgumentError
45
+ raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
46
+ end
47
+ end
36
48
  end
37
49
  end
38
50
  end
@@ -0,0 +1,40 @@
1
+ module ActiveRecord
2
+ module CollectionCacheKey
3
+
4
+ def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
5
+ query_signature = Digest::MD5.hexdigest(collection.to_sql)
6
+ key = "#{collection.model_name.cache_key}/query-#{query_signature}"
7
+
8
+ if collection.loaded?
9
+ size = collection.size
10
+ if size > 0
11
+ timestamp = collection.max_by(&timestamp_column).public_send(timestamp_column)
12
+ end
13
+ else
14
+ column_type = type_for_attribute(timestamp_column.to_s)
15
+ column = "#{connection.quote_table_name(collection.table_name)}.#{connection.quote_column_name(timestamp_column)}"
16
+
17
+ query = collection
18
+ .unscope(:select)
19
+ .select("COUNT(*) AS #{connection.quote_column_name("size")}", "MAX(#{column}) AS timestamp")
20
+ .unscope(:order)
21
+ result = connection.select_one(query)
22
+
23
+ if result.blank?
24
+ size = 0
25
+ timestamp = nil
26
+ else
27
+ size = result["size"]
28
+ timestamp = column_type.deserialize(result["timestamp"])
29
+ end
30
+
31
+ end
32
+
33
+ if timestamp
34
+ "#{key}-#{size}-#{timestamp.utc.to_s(cache_timestamp_format)}"
35
+ else
36
+ "#{key}-#{size}"
37
+ end
38
+ end
39
+ end
40
+ end