activerecord 3.2.22.5 → 5.2.8

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 (275) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -621
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +41 -46
  5. data/examples/performance.rb +55 -42
  6. data/examples/simple.rb +6 -5
  7. data/lib/active_record/aggregations.rb +264 -236
  8. data/lib/active_record/association_relation.rb +40 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -42
  10. data/lib/active_record/associations/association.rb +127 -75
  11. data/lib/active_record/associations/association_scope.rb +126 -92
  12. data/lib/active_record/associations/belongs_to_association.rb +78 -27
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -4
  14. data/lib/active_record/associations/builder/association.rb +117 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +135 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -54
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +120 -42
  18. data/lib/active_record/associations/builder/has_many.rb +10 -64
  19. data/lib/active_record/associations/builder/has_one.rb +19 -51
  20. data/lib/active_record/associations/builder/singular_association.rb +28 -18
  21. data/lib/active_record/associations/collection_association.rb +226 -293
  22. data/lib/active_record/associations/collection_proxy.rb +1067 -69
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +83 -47
  25. data/lib/active_record/associations/has_many_through_association.rb +98 -65
  26. data/lib/active_record/associations/has_one_association.rb +57 -20
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +48 -126
  29. data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
  30. data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
  31. data/lib/active_record/associations/join_dependency.rb +212 -164
  32. data/lib/active_record/associations/preloader/association.rb +95 -89
  33. data/lib/active_record/associations/preloader/through_association.rb +84 -44
  34. data/lib/active_record/associations/preloader.rb +123 -111
  35. data/lib/active_record/associations/singular_association.rb +33 -24
  36. data/lib/active_record/associations/through_association.rb +60 -26
  37. data/lib/active_record/associations.rb +1759 -1506
  38. data/lib/active_record/attribute_assignment.rb +60 -193
  39. data/lib/active_record/attribute_decorators.rb +90 -0
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +55 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +113 -74
  42. data/lib/active_record/attribute_methods/primary_key.rb +106 -77
  43. data/lib/active_record/attribute_methods/query.rb +8 -5
  44. data/lib/active_record/attribute_methods/read.rb +63 -114
  45. data/lib/active_record/attribute_methods/serialization.rb +60 -90
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -43
  47. data/lib/active_record/attribute_methods/write.rb +43 -45
  48. data/lib/active_record/attribute_methods.rb +366 -149
  49. data/lib/active_record/attributes.rb +266 -0
  50. data/lib/active_record/autosave_association.rb +312 -225
  51. data/lib/active_record/base.rb +114 -505
  52. data/lib/active_record/callbacks.rb +145 -67
  53. data/lib/active_record/coders/json.rb +15 -0
  54. data/lib/active_record/coders/yaml_column.rb +32 -23
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +883 -284
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +16 -2
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +350 -200
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -27
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +150 -65
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +477 -284
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1100 -310
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +450 -118
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +657 -446
  69. data/lib/active_record/connection_adapters/column.rb +50 -255
  70. data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -210
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +774 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +620 -1080
  117. data/lib/active_record/connection_adapters/schema_cache.rb +85 -36
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +545 -27
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +145 -0
  128. data/lib/active_record/core.rb +559 -0
  129. data/lib/active_record/counter_cache.rb +200 -105
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +107 -69
  132. data/lib/active_record/enum.rb +244 -0
  133. data/lib/active_record/errors.rb +245 -60
  134. data/lib/active_record/explain.rb +35 -71
  135. data/lib/active_record/explain_registry.rb +32 -0
  136. data/lib/active_record/explain_subscriber.rb +18 -9
  137. data/lib/active_record/fixture_set/file.rb +82 -0
  138. data/lib/active_record/fixtures.rb +418 -275
  139. data/lib/active_record/gem_version.rb +17 -0
  140. data/lib/active_record/inheritance.rb +209 -100
  141. data/lib/active_record/integration.rb +116 -21
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  144. data/lib/active_record/locale/en.yml +9 -1
  145. data/lib/active_record/locking/optimistic.rb +107 -94
  146. data/lib/active_record/locking/pessimistic.rb +20 -8
  147. data/lib/active_record/log_subscriber.rb +99 -34
  148. data/lib/active_record/migration/command_recorder.rb +199 -64
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +17 -0
  151. data/lib/active_record/migration.rb +893 -296
  152. data/lib/active_record/model_schema.rb +328 -175
  153. data/lib/active_record/nested_attributes.rb +338 -242
  154. data/lib/active_record/no_touching.rb +58 -0
  155. data/lib/active_record/null_relation.rb +68 -0
  156. data/lib/active_record/persistence.rb +557 -170
  157. data/lib/active_record/query_cache.rb +14 -43
  158. data/lib/active_record/querying.rb +36 -24
  159. data/lib/active_record/railtie.rb +147 -52
  160. data/lib/active_record/railties/console_sandbox.rb +5 -4
  161. data/lib/active_record/railties/controller_runtime.rb +13 -6
  162. data/lib/active_record/railties/databases.rake +206 -488
  163. data/lib/active_record/readonly_attributes.rb +4 -6
  164. data/lib/active_record/reflection.rb +734 -228
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +249 -52
  167. data/lib/active_record/relation/calculations.rb +330 -284
  168. data/lib/active_record/relation/delegation.rb +135 -37
  169. data/lib/active_record/relation/finder_methods.rb +450 -287
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +193 -0
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  179. data/lib/active_record/relation/predicate_builder.rb +132 -43
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +1037 -221
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +48 -151
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +451 -359
  187. data/lib/active_record/result.rb +129 -20
  188. data/lib/active_record/runtime_registry.rb +24 -0
  189. data/lib/active_record/sanitization.rb +164 -136
  190. data/lib/active_record/schema.rb +31 -19
  191. data/lib/active_record/schema_dumper.rb +154 -107
  192. data/lib/active_record/schema_migration.rb +56 -0
  193. data/lib/active_record/scoping/default.rb +108 -98
  194. data/lib/active_record/scoping/named.rb +125 -112
  195. data/lib/active_record/scoping.rb +77 -123
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +10 -6
  198. data/lib/active_record/statement_cache.rb +121 -0
  199. data/lib/active_record/store.rb +175 -16
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +337 -0
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
  206. data/lib/active_record/timestamp.rb +80 -41
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +240 -119
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +9 -0
  212. data/lib/active_record/type/date_time.rb +9 -0
  213. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  214. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +71 -0
  218. data/lib/active_record/type/text.rb +11 -0
  219. data/lib/active_record/type/time.rb +21 -0
  220. data/lib/active_record/type/type_map.rb +62 -0
  221. data/lib/active_record/type/unsigned_integer.rb +17 -0
  222. data/lib/active_record/type.rb +79 -0
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +35 -18
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +68 -0
  230. data/lib/active_record/validations/uniqueness.rb +133 -75
  231. data/lib/active_record/validations.rb +53 -43
  232. data/lib/active_record/version.rb +7 -7
  233. data/lib/active_record.rb +89 -57
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +61 -8
  237. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  238. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
  239. data/lib/rails/generators/active_record/migration.rb +28 -8
  240. data/lib/rails/generators/active_record/model/model_generator.rb +23 -22
  241. data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
  243. data/lib/rails/generators/active_record.rb +10 -16
  244. metadata +141 -62
  245. data/examples/associations.png +0 -0
  246. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  247. data/lib/active_record/associations/join_helper.rb +0 -55
  248. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  249. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  250. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  251. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  252. data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
  253. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  254. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  255. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  256. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  257. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  258. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  259. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  260. data/lib/active_record/dynamic_finder_match.rb +0 -68
  261. data/lib/active_record/dynamic_scope_match.rb +0 -23
  262. data/lib/active_record/fixtures/file.rb +0 -65
  263. data/lib/active_record/identity_map.rb +0 -162
  264. data/lib/active_record/observer.rb +0 -121
  265. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  266. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  267. data/lib/active_record/session_store.rb +0 -360
  268. data/lib/active_record/test_case.rb +0 -73
  269. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
  270. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  271. data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
  272. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  273. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  274. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  275. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,13 +1,13 @@
1
- require 'active_support/core_ext/array/wrap'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
- # = Active Record Callbacks
4
+ # = Active Record \Callbacks
5
5
  #
6
- # Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
6
+ # \Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
7
7
  # before or after an alteration of the object state. This can be used to make sure that associated and
8
- # dependent objects are deleted when +destroy+ is called (by overwriting +before_destroy+) or to massage attributes
9
- # before they're validated (by overwriting +before_validation+). As an example of the callbacks initiated, consider
10
- # the <tt>Base#save</tt> call for a new record:
8
+ # dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] is called (by overwriting +before_destroy+) or
9
+ # to massage attributes before they're validated (by overwriting +before_validation+).
10
+ # As an example of the callbacks initiated, consider the {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] call for a new record:
11
11
  #
12
12
  # * (-) <tt>save</tt>
13
13
  # * (-) <tt>valid</tt>
@@ -22,22 +22,25 @@ module ActiveRecord
22
22
  # * (7) <tt>after_commit</tt>
23
23
  #
24
24
  # Also, an <tt>after_rollback</tt> callback can be configured to be triggered whenever a rollback is issued.
25
- # Check out <tt>ActiveRecord::Transactions</tt> for more details about <tt>after_commit</tt> and
25
+ # Check out ActiveRecord::Transactions for more details about <tt>after_commit</tt> and
26
26
  # <tt>after_rollback</tt>.
27
27
  #
28
- # Lastly an <tt>after_find</tt> and <tt>after_initialize</tt> callback is triggered for each object that
28
+ # Additionally, an <tt>after_touch</tt> callback is triggered whenever an
29
+ # object is touched.
30
+ #
31
+ # Lastly an <tt>after_find</tt> and <tt>after_initialize</tt> callback is triggered for each object that
29
32
  # is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
30
33
  # are instantiated as well.
31
34
  #
32
- # That's a total of twelve callbacks, which gives you immense power to react and prepare for each state in the
33
- # Active Record life cycle. The sequence for calling <tt>Base#save</tt> for an existing record is similar,
35
+ # There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the
36
+ # Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
34
37
  # except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
35
38
  #
36
39
  # Examples:
37
40
  # class CreditCard < ActiveRecord::Base
38
41
  # # Strip everything but digits, so the user can specify "555 234 34" or
39
- # # "5552-3434" or both will mean "55523434"
40
- # before_validation(:on => :create) do
42
+ # # "5552-3434" and both will mean "55523434"
43
+ # before_validation(on: :create) do
41
44
  # self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number")
42
45
  # end
43
46
  # end
@@ -52,9 +55,9 @@ module ActiveRecord
52
55
  # end
53
56
  #
54
57
  # class Firm < ActiveRecord::Base
55
- # # Destroys the associated clients and people when the firm is destroyed
56
- # before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" }
57
- # before_destroy { |record| Client.destroy_all "client_of = #{record.id}" }
58
+ # # Disables access to the system, for associated clients and people when the firm is destroyed
59
+ # before_destroy { |record| Person.where(firm_id: record.id).update_all(access: 'disabled') }
60
+ # before_destroy { |record| Client.where(client_of: record.id).update_all(access: 'disabled') }
58
61
  # end
59
62
  #
60
63
  # == Inheritable callback queues
@@ -85,7 +88,7 @@ module ActiveRecord
85
88
  #
86
89
  # In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
87
90
  # So, use the callback macros when you want to ensure that a certain callback is called for the entire
88
- # hierarchy, and use the regular overwriteable methods when you want to leave it up to each descendant
91
+ # hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
89
92
  # to decide whether they want to call +super+ and trigger the inherited callbacks.
90
93
  #
91
94
  # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
@@ -95,9 +98,9 @@ module ActiveRecord
95
98
  # == Types of callbacks
96
99
  #
97
100
  # There are four types of callbacks accepted by the callback macros: Method references (symbol), callback objects,
98
- # inline methods (using a proc), and inline eval methods (using a string). Method references and callback objects
101
+ # inline methods (using a proc). Method references and callback objects
99
102
  # are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for
100
- # creating mix-ins), and inline eval methods are deprecated.
103
+ # creating mix-ins).
101
104
  #
102
105
  # The method reference callbacks work by specifying a protected or private method available in the object, like this:
103
106
  #
@@ -127,7 +130,7 @@ module ActiveRecord
127
130
  # record.credit_card_number = decrypt(record.credit_card_number)
128
131
  # end
129
132
  #
130
- # alias_method :after_find, :after_save
133
+ # alias_method :after_initialize, :after_save
131
134
  #
132
135
  # private
133
136
  # def encrypt(value)
@@ -162,7 +165,7 @@ module ActiveRecord
162
165
  # record.send("#{@attribute}=", decrypt(record.send("#{@attribute}")))
163
166
  # end
164
167
  #
165
- # alias_method :after_find, :after_save
168
+ # alias_method :after_initialize, :after_save
166
169
  #
167
170
  # private
168
171
  # def encrypt(value)
@@ -174,64 +177,135 @@ module ActiveRecord
174
177
  # end
175
178
  # end
176
179
  #
177
- # The callback macros usually accept a symbol for the method they're supposed to run, but you can also
178
- # pass a "method string", which will then be evaluated within the binding of the callback. Example:
180
+ # == <tt>before_validation*</tt> returning statements
181
+ #
182
+ # If the +before_validation+ callback throws +:abort+, the process will be
183
+ # aborted and {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] will return +false+.
184
+ # If {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] is called it will raise an ActiveRecord::RecordInvalid exception.
185
+ # Nothing will be appended to the errors object.
186
+ #
187
+ # == Canceling callbacks
188
+ #
189
+ # If a <tt>before_*</tt> callback throws +:abort+, all the later callbacks and
190
+ # the associated action are cancelled.
191
+ # Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
192
+ # methods on the model, which are called last.
193
+ #
194
+ # == Ordering callbacks
195
+ #
196
+ # Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
197
+ # callback (+log_children+ in this case) should be executed before the children get destroyed by the
198
+ # <tt>dependent: :destroy</tt> option.
199
+ #
200
+ # Let's look at the code below:
179
201
  #
180
202
  # class Topic < ActiveRecord::Base
181
- # before_destroy 'self.class.delete_all "parent_id = #{id}"'
203
+ # has_many :children, dependent: :destroy
204
+ #
205
+ # before_destroy :log_children
206
+ #
207
+ # private
208
+ # def log_children
209
+ # # Child processing
210
+ # end
182
211
  # end
183
212
  #
184
- # Notice that single quotes (') are used so the <tt>#{id}</tt> part isn't evaluated until the callback
185
- # is triggered. Also note that these inline callbacks can be stacked just like the regular ones:
213
+ # In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
214
+ # because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback gets executed first.
215
+ # You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
186
216
  #
187
217
  # class Topic < ActiveRecord::Base
188
- # before_destroy 'self.class.delete_all "parent_id = #{id}"',
189
- # 'puts "Evaluated after parents are destroyed"'
218
+ # has_many :children, dependent: :destroy
219
+ #
220
+ # before_destroy :log_children, prepend: true
221
+ #
222
+ # private
223
+ # def log_children
224
+ # # Child processing
225
+ # end
190
226
  # end
191
227
  #
192
- # == <tt>before_validation*</tt> returning statements
228
+ # This way, the +before_destroy+ gets executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
193
229
  #
194
- # If the returning value of a +before_validation+ callback can be evaluated to +false+, the process will be
195
- # aborted and <tt>Base#save</tt> will return +false+. If Base#save! is called it will raise a
196
- # ActiveRecord::RecordInvalid exception. Nothing will be appended to the errors object.
230
+ # Also, there are cases when you want several callbacks of the same type to
231
+ # be executed in order.
197
232
  #
198
- # == Canceling callbacks
233
+ # For example:
199
234
  #
200
- # If a <tt>before_*</tt> callback returns +false+, all the later callbacks and the associated action are
201
- # cancelled. If an <tt>after_*</tt> callback returns +false+, all the later callbacks are cancelled.
202
- # Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
203
- # methods on the model, which are called last.
235
+ # class Topic < ActiveRecord::Base
236
+ # has_many :children
237
+ #
238
+ # after_save :log_children
239
+ # after_save :do_something_else
204
240
  #
205
- # == Transactions
241
+ # private
206
242
  #
207
- # The entire callback chain of a +save+, <tt>save!</tt>, or +destroy+ call runs
208
- # within a transaction. That includes <tt>after_*</tt> hooks. If everything
209
- # goes fine a COMMIT is executed once the chain has been completed.
243
+ # def log_children
244
+ # # Child processing
245
+ # end
246
+ #
247
+ # def do_something_else
248
+ # # Something else
249
+ # end
250
+ # end
251
+ #
252
+ # In this case the +log_children+ gets executed before +do_something_else+.
253
+ # The same applies to all non-transactional callbacks.
254
+ #
255
+ # In case there are multiple transactional callbacks as seen below, the order
256
+ # is reversed.
257
+ #
258
+ # For example:
259
+ #
260
+ # class Topic < ActiveRecord::Base
261
+ # has_many :children
262
+ #
263
+ # after_commit :log_children
264
+ # after_commit :do_something_else
265
+ #
266
+ # private
267
+ #
268
+ # def log_children
269
+ # # Child processing
270
+ # end
271
+ #
272
+ # def do_something_else
273
+ # # Something else
274
+ # end
275
+ # end
276
+ #
277
+ # In this case the +do_something_else+ gets executed before +log_children+.
278
+ #
279
+ # == \Transactions
280
+ #
281
+ # The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!],
282
+ # or {#destroy}[rdoc-ref:Persistence#destroy] call runs within a transaction. That includes <tt>after_*</tt> hooks.
283
+ # If everything goes fine a COMMIT is executed once the chain has been completed.
210
284
  #
211
285
  # If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
212
286
  # can also trigger a ROLLBACK raising an exception in any of the callbacks,
213
287
  # including <tt>after_*</tt> hooks. Note, however, that in that case the client
214
- # needs to be aware of it because an ordinary +save+ will raise such exception
288
+ # needs to be aware of it because an ordinary {#save}[rdoc-ref:Persistence#save] will raise such exception
215
289
  # instead of quietly returning +false+.
216
290
  #
217
291
  # == Debugging callbacks
218
- #
219
- # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. ActiveModel Callbacks support
292
+ #
293
+ # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. Active Model \Callbacks support
220
294
  # <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
221
295
  # defines what part of the chain the callback runs in.
222
- #
223
- # To find all callbacks in the before_save callback chain:
224
- #
296
+ #
297
+ # To find all callbacks in the before_save callback chain:
298
+ #
225
299
  # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
226
- #
300
+ #
227
301
  # Returns an array of callback objects that form the before_save chain.
228
- #
302
+ #
229
303
  # To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
230
- #
304
+ #
231
305
  # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
232
- #
306
+ #
233
307
  # Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
234
- #
308
+ #
235
309
  module Callbacks
236
310
  extend ActiveSupport::Concern
237
311
 
@@ -242,34 +316,38 @@ module ActiveRecord
242
316
  :before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
243
317
  ]
244
318
 
245
- included do
246
- extend ActiveModel::Callbacks
247
- include ActiveModel::Validations::Callbacks
248
-
249
- define_model_callbacks :initialize, :find, :touch, :only => :after
250
- define_model_callbacks :save, :create, :update, :destroy
251
- end
252
-
253
319
  def destroy #:nodoc:
254
- run_callbacks(:destroy) { super }
320
+ @_destroy_callback_already_called ||= false
321
+ return if @_destroy_callback_already_called
322
+ @_destroy_callback_already_called = true
323
+ _run_destroy_callbacks { super }
324
+ rescue RecordNotDestroyed => e
325
+ @_association_destroy_exception = e
326
+ false
327
+ ensure
328
+ @_destroy_callback_already_called = false
255
329
  end
256
330
 
257
331
  def touch(*) #:nodoc:
258
- run_callbacks(:touch) { super }
332
+ _run_touch_callbacks { super }
333
+ end
334
+
335
+ def increment!(attribute, by = 1, touch: nil) # :nodoc:
336
+ touch ? _run_touch_callbacks { super } : super
259
337
  end
260
338
 
261
339
  private
262
340
 
263
- def create_or_update #:nodoc:
264
- run_callbacks(:save) { super }
341
+ def create_or_update(*)
342
+ _run_save_callbacks { super }
265
343
  end
266
344
 
267
- def create #:nodoc:
268
- run_callbacks(:create) { super }
345
+ def _create_record
346
+ _run_create_callbacks { super }
269
347
  end
270
348
 
271
- def update(*) #:nodoc:
272
- run_callbacks(:update) { super }
349
+ def _update_record(*)
350
+ _run_update_callbacks { super }
273
351
  end
274
352
  end
275
353
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Coders # :nodoc:
5
+ class JSON # :nodoc:
6
+ def self.dump(obj)
7
+ ActiveSupport::JSON.encode(obj)
8
+ end
9
+
10
+ def self.load(json)
11
+ ActiveSupport::JSON.decode(json) unless json.blank?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,41 +1,50 @@
1
- module ActiveRecord
2
- # :stopdoc:
3
- module Coders
4
- class YAMLColumn
5
- RESCUE_ERRORS = [ ArgumentError ]
1
+ # frozen_string_literal: true
6
2
 
7
- if defined?(Psych) && defined?(Psych::SyntaxError)
8
- RESCUE_ERRORS << Psych::SyntaxError
9
- end
3
+ require "yaml"
10
4
 
5
+ module ActiveRecord
6
+ module Coders # :nodoc:
7
+ class YAMLColumn # :nodoc:
11
8
  attr_accessor :object_class
12
9
 
13
- def initialize(object_class = Object)
10
+ def initialize(attr_name, object_class = Object)
11
+ @attr_name = attr_name
14
12
  @object_class = object_class
13
+ check_arity_of_constructor
15
14
  end
16
15
 
17
16
  def dump(obj)
17
+ return if obj.nil?
18
+
19
+ assert_valid_value(obj, action: "dump")
18
20
  YAML.dump obj
19
21
  end
20
22
 
21
23
  def load(yaml)
22
24
  return object_class.new if object_class != Object && yaml.nil?
23
- return yaml unless yaml.is_a?(String) && yaml =~ /^---/
24
- begin
25
- obj = YAML.load(yaml)
26
-
27
- unless obj.is_a?(object_class) || obj.nil?
28
- raise SerializationTypeMismatch,
29
- "Attribute was supposed to be a #{object_class}, but was a #{obj.class}"
30
- end
31
- obj ||= object_class.new if object_class != Object
32
-
33
- obj
34
- rescue *RESCUE_ERRORS
35
- yaml
25
+ return yaml unless yaml.is_a?(String) && /^---/.match?(yaml)
26
+ obj = YAML.load(yaml)
27
+
28
+ assert_valid_value(obj, action: "load")
29
+ obj ||= object_class.new if object_class != Object
30
+
31
+ obj
32
+ end
33
+
34
+ def assert_valid_value(obj, action:)
35
+ unless obj.nil? || obj.is_a?(object_class)
36
+ raise SerializationTypeMismatch,
37
+ "can't #{action} `#{@attr_name}`: was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
36
38
  end
37
39
  end
40
+
41
+ private
42
+
43
+ def check_arity_of_constructor
44
+ load(nil)
45
+ rescue ArgumentError
46
+ raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
47
+ end
38
48
  end
39
49
  end
40
- # :startdoc
41
50
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module CollectionCacheKey
5
+ def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
6
+ query_signature = ActiveSupport::Digest.hexdigest(collection.to_sql)
7
+ key = "#{collection.model_name.cache_key}/query-#{query_signature}"
8
+
9
+ if collection.loaded? || collection.distinct_value
10
+ size = collection.records.size
11
+ if size > 0
12
+ timestamp = collection.max_by(&timestamp_column)._read_attribute(timestamp_column)
13
+ end
14
+ else
15
+ if collection.eager_loading?
16
+ collection = collection.send(:apply_join_dependency)
17
+ end
18
+ column_type = type_for_attribute(timestamp_column)
19
+ column = connection.column_name_from_arel_node(collection.arel_attribute(timestamp_column))
20
+ select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
21
+
22
+ if collection.has_limit_or_offset?
23
+ query = collection.select("#{column} AS collection_cache_key_timestamp")
24
+ subquery_alias = "subquery_for_cache_key"
25
+ subquery_column = "#{subquery_alias}.collection_cache_key_timestamp"
26
+ subquery = query.arel.as(subquery_alias)
27
+ arel = Arel::SelectManager.new(subquery).project(select_values % subquery_column)
28
+ else
29
+ query = collection.unscope(:order)
30
+ query.select_values = [select_values % column]
31
+ arel = query.arel
32
+ end
33
+
34
+ result = connection.select_one(arel, nil)
35
+
36
+ if result.blank?
37
+ size = 0
38
+ timestamp = nil
39
+ else
40
+ size = result["size"]
41
+ timestamp = column_type.deserialize(result["timestamp"])
42
+ end
43
+
44
+ end
45
+
46
+ if timestamp
47
+ "#{key}-#{size}-#{timestamp.utc.to_s(cache_timestamp_format)}"
48
+ else
49
+ "#{key}-#{size}"
50
+ end
51
+ end
52
+ end
53
+ end