activerecord 5.1.7 → 5.2.0.beta1

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 (259) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +221 -900
  3. data/README.rdoc +3 -3
  4. data/examples/performance.rb +2 -0
  5. data/examples/simple.rb +2 -0
  6. data/lib/active_record.rb +10 -3
  7. data/lib/active_record/aggregations.rb +2 -0
  8. data/lib/active_record/association_relation.rb +2 -0
  9. data/lib/active_record/associations.rb +13 -42
  10. data/lib/active_record/associations/alias_tracker.rb +17 -17
  11. data/lib/active_record/associations/association.rb +11 -22
  12. data/lib/active_record/associations/association_scope.rb +32 -44
  13. data/lib/active_record/associations/belongs_to_association.rb +6 -4
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
  15. data/lib/active_record/associations/builder/association.rb +2 -5
  16. data/lib/active_record/associations/builder/belongs_to.rb +7 -12
  17. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  19. data/lib/active_record/associations/builder/has_many.rb +2 -0
  20. data/lib/active_record/associations/builder/has_one.rb +2 -0
  21. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  22. data/lib/active_record/associations/collection_association.rb +41 -33
  23. data/lib/active_record/associations/collection_proxy.rb +11 -14
  24. data/lib/active_record/associations/foreign_association.rb +2 -0
  25. data/lib/active_record/associations/has_many_association.rb +4 -2
  26. data/lib/active_record/associations/has_many_through_association.rb +4 -2
  27. data/lib/active_record/associations/has_one_association.rb +3 -1
  28. data/lib/active_record/associations/has_one_through_association.rb +3 -1
  29. data/lib/active_record/associations/join_dependency.rb +22 -40
  30. data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
  31. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  32. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  33. data/lib/active_record/associations/preloader.rb +17 -37
  34. data/lib/active_record/associations/preloader/association.rb +42 -58
  35. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  36. data/lib/active_record/associations/singular_association.rb +14 -10
  37. data/lib/active_record/associations/through_association.rb +3 -1
  38. data/lib/active_record/attribute_assignment.rb +2 -0
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods.rb +47 -7
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  42. data/lib/active_record/attribute_methods/dirty.rb +25 -214
  43. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  44. data/lib/active_record/attribute_methods/query.rb +2 -0
  45. data/lib/active_record/attribute_methods/read.rb +8 -2
  46. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  48. data/lib/active_record/attribute_methods/write.rb +21 -9
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +5 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +6 -8
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +2 -0
  55. data/lib/active_record/collection_cache_key.rb +10 -5
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +120 -28
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +3 -1
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -6
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +3 -5
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -0
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +47 -82
  116. data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +19 -2
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  122. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  123. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  124. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -89
  125. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  126. data/lib/active_record/connection_handling.rb +4 -2
  127. data/lib/active_record/core.rb +27 -57
  128. data/lib/active_record/counter_cache.rb +15 -12
  129. data/lib/active_record/define_callbacks.rb +5 -3
  130. data/lib/active_record/dynamic_matchers.rb +9 -9
  131. data/lib/active_record/enum.rb +15 -13
  132. data/lib/active_record/errors.rb +54 -21
  133. data/lib/active_record/explain.rb +3 -1
  134. data/lib/active_record/explain_registry.rb +2 -0
  135. data/lib/active_record/explain_subscriber.rb +2 -0
  136. data/lib/active_record/fixture_set/file.rb +2 -0
  137. data/lib/active_record/fixtures.rb +40 -24
  138. data/lib/active_record/gem_version.rb +5 -3
  139. data/lib/active_record/inheritance.rb +6 -5
  140. data/lib/active_record/integration.rb +58 -19
  141. data/lib/active_record/internal_metadata.rb +2 -0
  142. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  143. data/lib/active_record/locking/optimistic.rb +31 -20
  144. data/lib/active_record/locking/pessimistic.rb +10 -7
  145. data/lib/active_record/log_subscriber.rb +2 -0
  146. data/lib/active_record/migration.rb +47 -21
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +20 -2
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/model_schema.rb +29 -38
  151. data/lib/active_record/nested_attributes.rb +18 -6
  152. data/lib/active_record/no_touching.rb +3 -1
  153. data/lib/active_record/null_relation.rb +2 -0
  154. data/lib/active_record/persistence.rb +184 -40
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +3 -1
  157. data/lib/active_record/railtie.rb +54 -1
  158. data/lib/active_record/railties/console_sandbox.rb +2 -0
  159. data/lib/active_record/railties/controller_runtime.rb +2 -0
  160. data/lib/active_record/railties/databases.rake +41 -28
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +100 -182
  163. data/lib/active_record/relation.rb +61 -193
  164. data/lib/active_record/relation/batches.rb +20 -5
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  166. data/lib/active_record/relation/calculations.rb +40 -23
  167. data/lib/active_record/relation/delegation.rb +10 -27
  168. data/lib/active_record/relation/finder_methods.rb +53 -49
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +22 -19
  171. data/lib/active_record/relation/predicate_builder.rb +42 -79
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  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 +2 -2
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  179. data/lib/active_record/relation/query_attribute.rb +9 -2
  180. data/lib/active_record/relation/query_methods.rb +80 -69
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +2 -0
  183. data/lib/active_record/relation/where_clause.rb +50 -67
  184. data/lib/active_record/relation/where_clause_factory.rb +4 -46
  185. data/lib/active_record/result.rb +2 -0
  186. data/lib/active_record/runtime_registry.rb +2 -0
  187. data/lib/active_record/sanitization.rb +15 -9
  188. data/lib/active_record/schema.rb +3 -1
  189. data/lib/active_record/schema_dumper.rb +24 -23
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping.rb +9 -8
  192. data/lib/active_record/scoping/default.rb +6 -7
  193. data/lib/active_record/scoping/named.rb +15 -7
  194. data/lib/active_record/secure_token.rb +2 -0
  195. data/lib/active_record/serialization.rb +2 -0
  196. data/lib/active_record/statement_cache.rb +22 -12
  197. data/lib/active_record/store.rb +2 -0
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +3 -1
  200. data/lib/active_record/tasks/database_tasks.rb +23 -12
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -12
  205. data/lib/active_record/touch_later.rb +2 -0
  206. data/lib/active_record/transactions.rb +9 -7
  207. data/lib/active_record/translation.rb +2 -0
  208. data/lib/active_record/type.rb +4 -1
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +2 -4
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type_caster.rb +2 -0
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +2 -0
  224. data/lib/active_record/validations.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +36 -6
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/rails/generators/active_record.rb +3 -1
  232. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  233. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  234. data/lib/rails/generators/active_record/migration.rb +2 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  238. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  239. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  241. metadata +25 -38
  242. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  243. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  244. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  245. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  246. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  248. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  249. data/lib/active_record/attribute.rb +0 -240
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute_mutation_tracker.rb +0 -122
  252. data/lib/active_record/attribute_set.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -126
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  256. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  257. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  258. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  259. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # Returns the version of the currently loaded Active Record as a <tt>Gem::Version</tt>
3
5
  def self.gem_version
@@ -6,9 +8,9 @@ module ActiveRecord
6
8
 
7
9
  module VERSION
8
10
  MAJOR = 5
9
- MINOR = 1
10
- TINY = 7
11
- PRE = nil
11
+ MINOR = 2
12
+ TINY = 0
13
+ PRE = "beta1"
12
14
 
13
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
16
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/indifferent_access"
2
4
 
3
5
  module ActiveRecord
@@ -30,7 +32,7 @@ module ActiveRecord
30
32
  # for differentiating between them or reloading the right type with find.
31
33
  #
32
34
  # Note, all the attributes for all the cases are kept in the same table. Read more:
33
- # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
35
+ # https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
34
36
  #
35
37
  module Inheritance
36
38
  extend ActiveSupport::Concern
@@ -38,8 +40,7 @@ module ActiveRecord
38
40
  included do
39
41
  # Determines whether to store the full constant name including namespace when using STI.
40
42
  # This is true, by default.
41
- class_attribute :store_full_sti_class, instance_writer: false
42
- self.store_full_sti_class = true
43
+ class_attribute :store_full_sti_class, instance_writer: false, default: true
43
44
  end
44
45
 
45
46
  module ClassMethods
@@ -217,7 +218,7 @@ module ActiveRecord
217
218
  def subclass_from_attributes(attrs)
218
219
  attrs = attrs.to_h if attrs.respond_to?(:permitted?)
219
220
  if attrs.is_a?(Hash)
220
- subclass_name = attrs.with_indifferent_access[inheritance_column]
221
+ subclass_name = attrs[inheritance_column] || attrs[inheritance_column.to_sym]
221
222
 
222
223
  if subclass_name.present?
223
224
  find_sti_class(subclass_name)
@@ -246,7 +247,7 @@ module ActiveRecord
246
247
  def ensure_proper_type
247
248
  klass = self.class
248
249
  if klass.finder_needs_type_condition?
249
- write_attribute(klass.inheritance_column, klass.sti_name)
250
+ _write_attribute(klass.inheritance_column, klass.sti_name)
250
251
  end
251
252
  end
252
253
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/filters"
2
4
 
3
5
  module ActiveRecord
@@ -7,12 +9,19 @@ module ActiveRecord
7
9
  included do
8
10
  ##
9
11
  # :singleton-method:
10
- # Indicates the format used to generate the timestamp in the cache key.
11
- # Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
12
+ # Indicates the format used to generate the timestamp in the cache key, if
13
+ # versioning is off. Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
12
14
  #
13
15
  # This is +:usec+, by default.
14
- class_attribute :cache_timestamp_format, instance_writer: false
15
- self.cache_timestamp_format = :usec
16
+ class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
17
+
18
+ ##
19
+ # :singleton-method:
20
+ # Indicates whether to use a stable #cache_key method that is accompanied
21
+ # by a changing version in the #cache_version method.
22
+ #
23
+ # This is +false+, by default until Rails 6.0.
24
+ class_attribute :cache_versioning, instance_writer: false, default: false
16
25
  end
17
26
 
18
27
  # Returns a +String+, which Action Pack uses for constructing a URL to this
@@ -42,35 +51,65 @@ module ActiveRecord
42
51
  id && id.to_s # Be sure to stringify the id for routes
43
52
  end
44
53
 
45
- # Returns a cache key that can be used to identify this record.
54
+ # Returns a stable cache key that can be used to identify this record.
46
55
  #
47
56
  # Product.new.cache_key # => "products/new"
48
- # Product.find(5).cache_key # => "products/5" (updated_at not available)
49
- # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
57
+ # Product.find(5).cache_key # => "products/5"
50
58
  #
51
- # You can also pass a list of named timestamps, and the newest in the list will be
52
- # used to generate the key:
59
+ # If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier,
60
+ # the cache key will also include a version.
53
61
  #
54
- # Person.find(5).cache_key(:updated_at, :last_reviewed_at)
62
+ # Product.cache_versioning = false
63
+ # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
55
64
  def cache_key(*timestamp_names)
56
65
  if new_record?
57
66
  "#{model_name.cache_key}/new"
58
67
  else
59
- timestamp = if timestamp_names.any?
60
- max_updated_column_timestamp(timestamp_names)
68
+ if cache_version && timestamp_names.none?
69
+ "#{model_name.cache_key}/#{id}"
61
70
  else
62
- max_updated_column_timestamp
63
- end
71
+ timestamp = if timestamp_names.any?
72
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
73
+ Specifying a timestamp name for #cache_key has been deprecated in favor of
74
+ the explicit #cache_version method that can be overwritten.
75
+ MSG
64
76
 
65
- if timestamp
66
- timestamp = timestamp.utc.to_s(cache_timestamp_format)
67
- "#{model_name.cache_key}/#{id}-#{timestamp}"
68
- else
69
- "#{model_name.cache_key}/#{id}"
77
+ max_updated_column_timestamp(timestamp_names)
78
+ else
79
+ max_updated_column_timestamp
80
+ end
81
+
82
+ if timestamp
83
+ timestamp = timestamp.utc.to_s(cache_timestamp_format)
84
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
85
+ else
86
+ "#{model_name.cache_key}/#{id}"
87
+ end
70
88
  end
71
89
  end
72
90
  end
73
91
 
92
+ # Returns a cache version that can be used together with the cache key to form
93
+ # a recyclable caching scheme. By default, the #updated_at column is used for the
94
+ # cache_version, but this method can be overwritten to return something else.
95
+ #
96
+ # Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
97
+ # +false+ (which it is by default until Rails 6.0).
98
+ def cache_version
99
+ if cache_versioning && timestamp = try(:updated_at)
100
+ timestamp.utc.to_s(:usec)
101
+ end
102
+ end
103
+
104
+ # Returns a cache key along with the version.
105
+ def cache_key_with_version
106
+ if version = cache_version
107
+ "#{cache_key}-#{version}"
108
+ else
109
+ cache_key
110
+ end
111
+ end
112
+
74
113
  module ClassMethods
75
114
  # Defines your model's +to_param+ method to generate "pretty" URLs
76
115
  # using +method_name+, which can be any attribute or method that
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record/scoping/default"
2
4
  require "active_record/scoping/named"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module LegacyYamlAdapter
3
5
  def self.convert(klass, coder)
@@ -6,7 +8,7 @@ module ActiveRecord
6
8
  case coder["active_record_yaml_version"]
7
9
  when 1, 2 then coder
8
10
  else
9
- if coder["attributes"].is_a?(AttributeSet)
11
+ if coder["attributes"].is_a?(ActiveModel::AttributeSet)
10
12
  Rails420.convert(klass, coder)
11
13
  else
12
14
  Rails41.convert(klass, coder)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Locking
3
5
  # == What is Optimistic Locking
@@ -51,8 +53,7 @@ module ActiveRecord
51
53
  extend ActiveSupport::Concern
52
54
 
53
55
  included do
54
- class_attribute :lock_optimistically, instance_writer: false
55
- self.lock_optimistically = true
56
+ class_attribute :lock_optimistically, instance_writer: false, default: true
56
57
  end
57
58
 
58
59
  def locking_enabled? #:nodoc:
@@ -60,6 +61,13 @@ module ActiveRecord
60
61
  end
61
62
 
62
63
  private
64
+
65
+ def increment_lock
66
+ lock_col = self.class.locking_column
67
+ previous_lock_value = send(lock_col)
68
+ send("#{lock_col}=", previous_lock_value + 1)
69
+ end
70
+
63
71
  def _create_record(attribute_names = self.attribute_names, *)
64
72
  if locking_enabled?
65
73
  # We always want to persist the locking version, even if we don't detect
@@ -69,37 +77,40 @@ module ActiveRecord
69
77
  super
70
78
  end
71
79
 
72
- def _touch_row(attribute_names, time)
73
- super
74
- ensure
75
- clear_attribute_change(self.class.locking_column) if locking_enabled?
76
- end
77
-
78
- def _update_row(attribute_names, attempted_action = "update")
80
+ def _update_record(attribute_names = self.attribute_names)
79
81
  return super unless locking_enabled?
82
+ return 0 if attribute_names.empty?
80
83
 
81
84
  begin
82
- locking_column = self.class.locking_column
83
- previous_lock_value = read_attribute_before_type_cast(locking_column)
84
- attribute_names << locking_column
85
+ lock_col = self.class.locking_column
86
+
87
+ previous_lock_value = read_attribute_before_type_cast(lock_col)
85
88
 
86
- self[locking_column] += 1
89
+ increment_lock
87
90
 
88
- affected_rows = self.class.unscoped._update_record(
89
- arel_attributes_with_values(attribute_names),
90
- self.class.primary_key => id_in_database,
91
- locking_column => previous_lock_value
91
+ attribute_names.push(lock_col)
92
+
93
+ relation = self.class.unscoped
94
+
95
+ affected_rows = relation.where(
96
+ self.class.primary_key => id,
97
+ lock_col => previous_lock_value
98
+ ).update_all(
99
+ attributes_for_update(attribute_names).map do |name|
100
+ [name, _read_attribute(name)]
101
+ end.to_h
92
102
  )
93
103
 
94
- if affected_rows != 1
95
- raise ActiveRecord::StaleObjectError.new(self, attempted_action)
104
+ unless affected_rows == 1
105
+ raise ActiveRecord::StaleObjectError.new(self, "update")
96
106
  end
97
107
 
98
108
  affected_rows
99
109
 
100
110
  # If something went wrong, revert the locking_column value.
101
111
  rescue Exception
102
- self[locking_column] = previous_lock_value.to_i
112
+ send("#{lock_col}=", previous_lock_value.to_i)
113
+
103
114
  raise
104
115
  end
105
116
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Locking
3
5
  # Locking::Pessimistic provides support for row-level locking using
@@ -51,8 +53,8 @@ module ActiveRecord
51
53
  # end
52
54
  #
53
55
  # Database-specific information on row locking:
54
- # MySQL: http://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
55
- # PostgreSQL: http://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
56
+ # MySQL: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
57
+ # PostgreSQL: https://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
56
58
  module Pessimistic
57
59
  # Obtain a row lock on this record. Reloads the record to obtain the requested
58
60
  # lock. Pass an SQL locking clause to append the end of the SELECT statement
@@ -60,13 +62,14 @@ module ActiveRecord
60
62
  # the locked record.
61
63
  def lock!(lock = true)
62
64
  if persisted?
63
- if has_changes_to_save?
64
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
65
- Locking a record with unpersisted changes is deprecated and will raise an
66
- exception in Rails 5.2. Use `save` to persist the changes, or `reload` to
67
- discard them explicitly.
65
+ if changed?
66
+ raise(<<-MSG.squish)
67
+ Locking a record with unpersisted changes is not supported. Use
68
+ `save` to persist the changes, or `reload` to discard them
69
+ explicitly.
68
70
  MSG
69
71
  end
72
+
70
73
  reload(lock: lock)
71
74
  end
72
75
  self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class LogSubscriber < ActiveSupport::LogSubscriber
3
5
  IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
4
  require "zlib"
3
5
  require "active_support/core_ext/module/attribute_accessors"
@@ -157,7 +159,7 @@ module ActiveRecord
157
159
 
158
160
  class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
159
161
  def initialize(env = "production")
160
- msg = "You are attempting to run a destructive action against your '#{env}' database.\n"
162
+ msg = "You are attempting to run a destructive action against your '#{env}' database.\n".dup
161
163
  msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
162
164
  msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
163
165
  super(msg)
@@ -166,7 +168,7 @@ module ActiveRecord
166
168
 
167
169
  class EnvironmentMismatchError < ActiveRecordError
168
170
  def initialize(current: nil, stored: nil)
169
- msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
171
+ msg = "You are attempting to modify a database that was last run in `#{ stored }` environment.\n".dup
170
172
  msg << "You are running in `#{ current }` environment. "
171
173
  msg << "If you are sure you want to continue, first set the environment using:\n\n"
172
174
  msg << " bin/rails db:environment:set"
@@ -352,9 +354,9 @@ module ActiveRecord
352
354
  # to match the structure of your database.
353
355
  #
354
356
  # To roll the database back to a previous migration version, use
355
- # <tt>rails db:migrate VERSION=X</tt> where <tt>X</tt> is the version to which
357
+ # <tt>rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
356
358
  # you wish to downgrade. Alternatively, you can also use the STEP option if you
357
- # wish to rollback last few migrations. <tt>rails db:migrate STEP=2</tt> will rollback
359
+ # wish to rollback last few migrations. <tt>rails db:rollback STEP=2</tt> will rollback
358
360
  # the latest two migrations.
359
361
  #
360
362
  # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
@@ -579,7 +581,8 @@ module ActiveRecord
579
581
  def load_schema_if_pending!
580
582
  if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
581
583
  # Roundtrip to Rake to allow plugins to hook into database initialization.
582
- FileUtils.cd Rails.root do
584
+ root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
585
+ FileUtils.cd(root) do
583
586
  current_config = Base.connection_config
584
587
  Base.clear_all_connections!
585
588
  system("bin/rails db:test:prepare")
@@ -731,6 +734,24 @@ module ActiveRecord
731
734
  execute_block { yield helper }
732
735
  end
733
736
 
737
+ # Used to specify an operation that is only run when migrating up
738
+ # (for example, populating a new column with its initial values).
739
+ #
740
+ # In the following example, the new column +published+ will be given
741
+ # the value +true+ for all existing records.
742
+ #
743
+ # class AddPublishedToPosts < ActiveRecord::Migration[5.2]
744
+ # def change
745
+ # add_column :posts, :published, :boolean, default: false
746
+ # up_only do
747
+ # execute "update posts set published = 'true'"
748
+ # end
749
+ # end
750
+ # end
751
+ def up_only
752
+ execute_block { yield } unless reverting?
753
+ end
754
+
734
755
  # Runs the given migration classes.
735
756
  # Last argument can specify options:
736
757
  # - :direction (default is :up)
@@ -863,15 +884,17 @@ module ActiveRecord
863
884
  source_migrations.each do |migration|
864
885
  source = File.binread(migration.filename)
865
886
  inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
866
- if /\A#.*\b(?:en)?coding:\s*\S+/ =~ source
887
+ magic_comments = "".dup
888
+ loop do
867
889
  # If we have a magic comment in the original migration,
868
890
  # insert our comment after the first newline(end of the magic comment line)
869
891
  # so the magic keep working.
870
892
  # Note that magic comments must be at the first line(except sh-bang).
871
- source[/\n/] = "\n#{inserted_comment}"
872
- else
873
- source = "#{inserted_comment}#{source}"
893
+ source.sub!(/\A(?:#.*\b(?:en)?coding:\s*\S+|#\s*frozen_string_literal:\s*(?:true|false)).*\n/) do |magic_comment|
894
+ magic_comments << magic_comment; ""
895
+ end || break
874
896
  end
897
+ source = "#{magic_comments}#{inserted_comment}#{source}"
875
898
 
876
899
  if duplicate = destination_migrations.detect { |m| m.name == migration.name }
877
900
  if options[:on_skip] && duplicate.scope != scope.to_s
@@ -1022,11 +1045,6 @@ module ActiveRecord
1022
1045
  new(:up, migrations(migrations_paths), nil)
1023
1046
  end
1024
1047
 
1025
- def schema_migrations_table_name
1026
- SchemaMigration.table_name
1027
- end
1028
- deprecate :schema_migrations_table_name
1029
-
1030
1048
  def get_all_versions(connection = Base.connection)
1031
1049
  if SchemaMigration.table_exists?
1032
1050
  SchemaMigration.all_versions.map(&:to_i)
@@ -1104,13 +1122,21 @@ module ActiveRecord
1104
1122
 
1105
1123
  def move(direction, migrations_paths, steps)
1106
1124
  migrator = new(direction, migrations(migrations_paths))
1107
- start_index = migrator.migrations.index(migrator.current_migration)
1108
1125
 
1109
- if start_index
1110
- finish = migrator.migrations[start_index + steps]
1111
- version = finish ? finish.version : 0
1112
- send(direction, migrations_paths, version)
1126
+ if current_version != 0 && !migrator.current_migration
1127
+ raise UnknownMigrationVersionError.new(current_version)
1113
1128
  end
1129
+
1130
+ start_index =
1131
+ if current_version == 0
1132
+ 0
1133
+ else
1134
+ migrator.migrations.index(migrator.current_migration)
1135
+ end
1136
+
1137
+ finish = migrator.migrations[start_index + steps]
1138
+ version = finish ? finish.version : 0
1139
+ send(direction, migrations_paths, version)
1114
1140
  end
1115
1141
  end
1116
1142
 
@@ -1217,7 +1243,7 @@ module ActiveRecord
1217
1243
 
1218
1244
  # Return true if a valid version is not provided.
1219
1245
  def invalid_target?
1220
- !target && @target_version && @target_version > 0
1246
+ @target_version && @target_version != 0 && !target
1221
1247
  end
1222
1248
 
1223
1249
  def execute_migration_in_transaction(migration, direction)
@@ -1231,7 +1257,7 @@ module ActiveRecord
1231
1257
  record_version_state_after_migrating(migration.version)
1232
1258
  end
1233
1259
  rescue => e
1234
- msg = "An error has occurred, "
1260
+ msg = "An error has occurred, ".dup
1235
1261
  msg << "this and " if use_transaction?(migration)
1236
1262
  msg << "all later migrations canceled:\n\n#{e}"
1237
1263
  raise StandardError, msg, e.backtrace