activerecord 6.0.0.beta3 → 6.0.0.rc1

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +286 -6
  3. data/README.rdoc +3 -1
  4. data/lib/active_record.rb +0 -1
  5. data/lib/active_record/associations.rb +3 -2
  6. data/lib/active_record/associations/association.rb +1 -1
  7. data/lib/active_record/associations/builder/association.rb +14 -18
  8. data/lib/active_record/associations/builder/belongs_to.rb +5 -2
  9. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  10. data/lib/active_record/associations/builder/has_many.rb +2 -0
  11. data/lib/active_record/associations/builder/has_one.rb +35 -1
  12. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  13. data/lib/active_record/associations/collection_proxy.rb +1 -1
  14. data/lib/active_record/associations/has_many_through_association.rb +4 -11
  15. data/lib/active_record/associations/preloader.rb +11 -6
  16. data/lib/active_record/associations/preloader/association.rb +32 -30
  17. data/lib/active_record/associations/preloader/through_association.rb +48 -28
  18. data/lib/active_record/attribute_methods.rb +4 -3
  19. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
  20. data/lib/active_record/attribute_methods/dirty.rb +42 -14
  21. data/lib/active_record/attribute_methods/primary_key.rb +7 -15
  22. data/lib/active_record/attribute_methods/query.rb +2 -3
  23. data/lib/active_record/attribute_methods/read.rb +3 -9
  24. data/lib/active_record/attribute_methods/write.rb +6 -12
  25. data/lib/active_record/attributes.rb +13 -0
  26. data/lib/active_record/autosave_association.rb +13 -3
  27. data/lib/active_record/base.rb +0 -1
  28. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -0
  29. data/lib/active_record/connection_adapters/abstract/database_limits.rb +8 -4
  30. data/lib/active_record/connection_adapters/abstract/database_statements.rb +84 -61
  31. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -1
  32. data/lib/active_record/connection_adapters/abstract/quoting.rb +10 -6
  33. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -7
  34. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +70 -14
  35. data/lib/active_record/connection_adapters/abstract_adapter.rb +56 -11
  36. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -69
  37. data/lib/active_record/connection_adapters/column.rb +17 -13
  38. data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -7
  39. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +4 -4
  40. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +9 -6
  41. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  42. data/lib/active_record/connection_adapters/mysql2_adapter.rb +6 -2
  43. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -30
  44. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +5 -1
  45. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +34 -38
  46. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +23 -27
  47. data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -27
  48. data/lib/active_record/connection_adapters/schema_cache.rb +32 -14
  49. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  50. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  51. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -2
  52. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +50 -112
  53. data/lib/active_record/connection_handling.rb +17 -10
  54. data/lib/active_record/core.rb +15 -20
  55. data/lib/active_record/database_configurations.rb +14 -14
  56. data/lib/active_record/database_configurations/hash_config.rb +11 -11
  57. data/lib/active_record/database_configurations/url_config.rb +12 -12
  58. data/lib/active_record/dynamic_matchers.rb +1 -1
  59. data/lib/active_record/enum.rb +6 -0
  60. data/lib/active_record/errors.rb +1 -1
  61. data/lib/active_record/gem_version.rb +1 -1
  62. data/lib/active_record/insert_all.rb +180 -0
  63. data/lib/active_record/integration.rb +13 -1
  64. data/lib/active_record/internal_metadata.rb +5 -1
  65. data/lib/active_record/locking/optimistic.rb +3 -4
  66. data/lib/active_record/log_subscriber.rb +1 -1
  67. data/lib/active_record/migration.rb +25 -18
  68. data/lib/active_record/migration/command_recorder.rb +28 -14
  69. data/lib/active_record/migration/compatibility.rb +10 -0
  70. data/lib/active_record/persistence.rb +206 -13
  71. data/lib/active_record/querying.rb +17 -12
  72. data/lib/active_record/railties/databases.rake +68 -6
  73. data/lib/active_record/reflection.rb +2 -2
  74. data/lib/active_record/relation.rb +98 -20
  75. data/lib/active_record/relation/calculations.rb +39 -39
  76. data/lib/active_record/relation/delegation.rb +22 -30
  77. data/lib/active_record/relation/finder_methods.rb +3 -9
  78. data/lib/active_record/relation/merger.rb +7 -16
  79. data/lib/active_record/relation/query_methods.rb +153 -38
  80. data/lib/active_record/relation/where_clause.rb +9 -5
  81. data/lib/active_record/sanitization.rb +3 -2
  82. data/lib/active_record/schema_dumper.rb +5 -0
  83. data/lib/active_record/schema_migration.rb +1 -1
  84. data/lib/active_record/scoping/default.rb +6 -7
  85. data/lib/active_record/scoping/named.rb +1 -1
  86. data/lib/active_record/statement_cache.rb +2 -2
  87. data/lib/active_record/store.rb +48 -0
  88. data/lib/active_record/table_metadata.rb +3 -3
  89. data/lib/active_record/tasks/database_tasks.rb +36 -1
  90. data/lib/active_record/touch_later.rb +2 -2
  91. data/lib/active_record/transactions.rb +52 -41
  92. data/lib/active_record/validations/uniqueness.rb +3 -5
  93. data/lib/arel/insert_manager.rb +3 -3
  94. data/lib/arel/nodes.rb +2 -1
  95. data/lib/arel/nodes/comment.rb +29 -0
  96. data/lib/arel/nodes/select_core.rb +16 -12
  97. data/lib/arel/nodes/unary.rb +1 -0
  98. data/lib/arel/nodes/values_list.rb +2 -17
  99. data/lib/arel/select_manager.rb +10 -10
  100. data/lib/arel/visitors/depth_first.rb +6 -1
  101. data/lib/arel/visitors/dot.rb +7 -2
  102. data/lib/arel/visitors/ibm_db.rb +13 -0
  103. data/lib/arel/visitors/informix.rb +6 -0
  104. data/lib/arel/visitors/mssql.rb +15 -1
  105. data/lib/arel/visitors/oracle12.rb +4 -5
  106. data/lib/arel/visitors/postgresql.rb +4 -10
  107. data/lib/arel/visitors/to_sql.rb +87 -108
  108. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
  109. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  110. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  111. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  112. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  113. metadata +12 -11
  114. data/lib/active_record/collection_cache_key.rb +0 -53
  115. data/lib/arel/nodes/values.rb +0 -16
@@ -7,7 +7,7 @@ require "active_record/database_configurations/url_config"
7
7
  module ActiveRecord
8
8
  # ActiveRecord::DatabaseConfigurations returns an array of DatabaseConfig
9
9
  # objects (either a HashConfig or UrlConfig) that are constructed from the
10
- # application's database configuration hash or url string.
10
+ # application's database configuration hash or URL string.
11
11
  class DatabaseConfigurations
12
12
  attr_reader :configurations
13
13
  delegate :any?, to: :configurations
@@ -17,22 +17,22 @@ module ActiveRecord
17
17
  end
18
18
 
19
19
  # Collects the configs for the environment and optionally the specification
20
- # name passed in. To include replica configurations pass `include_replicas: true`.
20
+ # name passed in. To include replica configurations pass <tt>include_replicas: true</tt>.
21
21
  #
22
22
  # If a spec name is provided a single DatabaseConfig object will be
23
23
  # returned, otherwise an array of DatabaseConfig objects will be
24
24
  # returned that corresponds with the environment and type requested.
25
25
  #
26
- # Options:
26
+ # ==== Options
27
27
  #
28
- # <tt>env_name:</tt> The environment name. Defaults to +nil+ which will collect
29
- # configs for all environments.
30
- # <tt>spec_name:</tt> The specification name (i.e. primary, animals, etc.). Defaults
31
- # to +nil+.
32
- # <tt>include_replicas:</tt> Determines whether to include replicas in
33
- # the returned list. Most of the time we're only iterating over the write
34
- # connection (i.e. migrations don't need to run for the write and read connection).
35
- # Defaults to +false+.
28
+ # * <tt>env_name:</tt> The environment name. Defaults to +nil+ which will collect
29
+ # configs for all environments.
30
+ # * <tt>spec_name:</tt> The specification name (i.e. primary, animals, etc.). Defaults
31
+ # to +nil+.
32
+ # * <tt>include_replicas:</tt> Determines whether to include replicas in
33
+ # the returned list. Most of the time we're only iterating over the write
34
+ # connection (i.e. migrations don't need to run for the write and read connection).
35
+ # Defaults to +false+.
36
36
  def configs_for(env_name: nil, spec_name: nil, include_replicas: false)
37
37
  configs = env_with_configs(env_name)
38
38
 
@@ -53,7 +53,7 @@ module ActiveRecord
53
53
 
54
54
  # Returns the config hash that corresponds with the environment
55
55
  #
56
- # If the application has multiple databases `default_hash` will
56
+ # If the application has multiple databases +default_hash+ will
57
57
  # return the first config hash for the environment.
58
58
  #
59
59
  # { database: "my_db", adapter: "mysql2" }
@@ -65,7 +65,7 @@ module ActiveRecord
65
65
 
66
66
  # Returns a single DatabaseConfig object based on the requested environment.
67
67
  #
68
- # If the application has multiple databases `find_db_config` will return
68
+ # If the application has multiple databases +find_db_config+ will return
69
69
  # the first DatabaseConfig for the environment.
70
70
  def find_db_config(env)
71
71
  configurations.find do |db_config|
@@ -106,7 +106,7 @@ module ActiveRecord
106
106
 
107
107
  build_db_config = configs.each_pair.flat_map do |env_name, config|
108
108
  walk_configs(env_name.to_s, "primary", config)
109
- end.compact
109
+ end.flatten.compact
110
110
 
111
111
  if url = ENV["DATABASE_URL"]
112
112
  build_url_config(url, build_db_config)
@@ -14,16 +14,16 @@ module ActiveRecord
14
14
  # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10
15
15
  # @env_name="development", @spec_name="primary", @config={"database"=>"db_name"}>
16
16
  #
17
- # Options are:
17
+ # ==== Options
18
18
  #
19
- # <tt>:env_name</tt> - The Rails environment, i.e. "development"
20
- # <tt>:spec_name</tt> - The specification name. In a standard two-tier
21
- # database configuration this will default to "primary". In a multiple
22
- # database three-tier database configuration this corresponds to the name
23
- # used in the second tier, for example "primary_readonly".
24
- # <tt>:config</tt> - The config hash. This is the hash that contains the
25
- # database adapter, name, and other important information for database
26
- # connections.
19
+ # * <tt>:env_name</tt> - The Rails environment, i.e. "development".
20
+ # * <tt>:spec_name</tt> - The specification name. In a standard two-tier
21
+ # database configuration this will default to "primary". In a multiple
22
+ # database three-tier database configuration this corresponds to the name
23
+ # used in the second tier, for example "primary_readonly".
24
+ # * <tt>:config</tt> - The config hash. This is the hash that contains the
25
+ # database adapter, name, and other important information for database
26
+ # connections.
27
27
  class HashConfig < DatabaseConfig
28
28
  attr_reader :config
29
29
 
@@ -33,14 +33,14 @@ module ActiveRecord
33
33
  end
34
34
 
35
35
  # Determines whether a database configuration is for a replica / readonly
36
- # connection. If the `replica` key is present in the config, `replica?` will
36
+ # connection. If the +replica+ key is present in the config, +replica?+ will
37
37
  # return +true+.
38
38
  def replica?
39
39
  config["replica"]
40
40
  end
41
41
 
42
42
  # The migrations paths for a database configuration. If the
43
- # `migrations_paths` key is present in the config, `migrations_paths`
43
+ # +migrations_paths+ key is present in the config, +migrations_paths+
44
44
  # will return its value.
45
45
  def migrations_paths
46
46
  config["migrations_paths"]
@@ -17,17 +17,17 @@ module ActiveRecord
17
17
  # @config={"adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost"},
18
18
  # @url="postgres://localhost/foo">
19
19
  #
20
- # Options are:
20
+ # ==== Options
21
21
  #
22
- # <tt>:env_name</tt> - The Rails environment, ie "development"
23
- # <tt>:spec_name</tt> - The specification name. In a standard two-tier
24
- # database configuration this will default to "primary". In a multiple
25
- # database three-tier database configuration this corresponds to the name
26
- # used in the second tier, for example "primary_readonly".
27
- # <tt>:url</tt> - The database URL.
28
- # <tt>:config</tt> - The config hash. This is the hash that contains the
29
- # database adapter, name, and other important information for database
30
- # connections.
22
+ # * <tt>:env_name</tt> - The Rails environment, ie "development".
23
+ # * <tt>:spec_name</tt> - The specification name. In a standard two-tier
24
+ # database configuration this will default to "primary". In a multiple
25
+ # database three-tier database configuration this corresponds to the name
26
+ # used in the second tier, for example "primary_readonly".
27
+ # * <tt>:url</tt> - The database URL.
28
+ # * <tt>:config</tt> - The config hash. This is the hash that contains the
29
+ # database adapter, name, and other important information for database
30
+ # connections.
31
31
  class UrlConfig < DatabaseConfig
32
32
  attr_reader :url, :config
33
33
 
@@ -42,14 +42,14 @@ module ActiveRecord
42
42
  end
43
43
 
44
44
  # Determines whether a database configuration is for a replica / readonly
45
- # connection. If the `replica` key is present in the config, `replica?` will
45
+ # connection. If the +replica+ key is present in the config, +replica?+ will
46
46
  # return +true+.
47
47
  def replica?
48
48
  config["replica"]
49
49
  end
50
50
 
51
51
  # The migrations paths for a database configuration. If the
52
- # `migrations_paths` key is present in the config, `migrations_paths`
52
+ # +migrations_paths+ key is present in the config, +migrations_paths+
53
53
  # will return its value.
54
54
  def migrations_paths
55
55
  config["migrations_paths"]
@@ -53,7 +53,7 @@ module ActiveRecord
53
53
  @model = model
54
54
  @name = name.to_s
55
55
  @attribute_names = @name.match(self.class.pattern)[1].split("_and_")
56
- @attribute_names.map! { |n| @model.attribute_aliases[n] || n }
56
+ @attribute_names.map! { |name| @model.attribute_aliases[name] || name }
57
57
  end
58
58
 
59
59
  def valid?
@@ -31,7 +31,9 @@ module ActiveRecord
31
31
  # as well. With the above example:
32
32
  #
33
33
  # Conversation.active
34
+ # Conversation.not_active
34
35
  # Conversation.archived
36
+ # Conversation.not_archived
35
37
  #
36
38
  # Of course, you can also query them directly if the scopes don't fit your
37
39
  # needs:
@@ -196,9 +198,13 @@ module ActiveRecord
196
198
  define_method("#{value_method_name}!") { update!(attr => value) }
197
199
 
198
200
  # scope :active, -> { where(status: 0) }
201
+ # scope :not_active, -> { where.not(status: 0) }
199
202
  if enum_scopes != false
200
203
  klass.send(:detect_enum_conflict!, name, value_method_name, true)
201
204
  klass.scope value_method_name, -> { where(attr => value) }
205
+
206
+ klass.send(:detect_enum_conflict!, name, "not_#{value_method_name}", true)
207
+ klass.scope "not_#{value_method_name}", -> { where.not(attr => value) }
202
208
  end
203
209
  end
204
210
  end
@@ -68,7 +68,7 @@ module ActiveRecord
68
68
 
69
69
  # Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
70
70
  # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
71
- # methods when a record is invalid and can not be saved.
71
+ # methods when a record is invalid and cannot be saved.
72
72
  class RecordNotSaved < ActiveRecordError
73
73
  attr_reader :record
74
74
 
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  MAJOR = 6
11
11
  MINOR = 0
12
12
  TINY = 0
13
- PRE = "beta3"
13
+ PRE = "rc1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -0,0 +1,180 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class InsertAll # :nodoc:
5
+ attr_reader :model, :connection, :inserts, :keys
6
+ attr_reader :on_duplicate, :returning, :unique_by
7
+
8
+ def initialize(model, inserts, on_duplicate:, returning: nil, unique_by: nil)
9
+ raise ArgumentError, "Empty list of attributes passed" if inserts.blank?
10
+
11
+ @model, @connection, @inserts, @keys = model, model.connection, inserts, inserts.first.keys.map(&:to_s).to_set
12
+ @on_duplicate, @returning, @unique_by = on_duplicate, returning, unique_by
13
+
14
+ @returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
15
+ @returning = false if @returning == []
16
+
17
+ @unique_by = find_unique_index_for(unique_by) if unique_by
18
+ @on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?
19
+
20
+ ensure_valid_options_for_connection!
21
+ end
22
+
23
+ def execute
24
+ message = +"#{model} "
25
+ message << "Bulk " if inserts.many?
26
+ message << (on_duplicate == :update ? "Upsert" : "Insert")
27
+ connection.exec_query to_sql, message
28
+ end
29
+
30
+ def updatable_columns
31
+ keys - readonly_columns - unique_by_columns
32
+ end
33
+
34
+ def primary_keys
35
+ Array(model.primary_key)
36
+ end
37
+
38
+
39
+ def skip_duplicates?
40
+ on_duplicate == :skip
41
+ end
42
+
43
+ def update_duplicates?
44
+ on_duplicate == :update
45
+ end
46
+
47
+ def map_key_with_value
48
+ inserts.map do |attributes|
49
+ attributes = attributes.stringify_keys
50
+ verify_attributes(attributes)
51
+
52
+ keys.map do |key|
53
+ yield key, attributes[key]
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+ def find_unique_index_for(unique_by)
60
+ match = Array(unique_by).map(&:to_s)
61
+
62
+ if index = unique_indexes.find { |i| match.include?(i.name) || i.columns == match }
63
+ index
64
+ else
65
+ raise ArgumentError, "No unique index found for #{unique_by}"
66
+ end
67
+ end
68
+
69
+ def unique_indexes
70
+ connection.schema_cache.indexes(model.table_name).select(&:unique)
71
+ end
72
+
73
+
74
+ def ensure_valid_options_for_connection!
75
+ if returning && !connection.supports_insert_returning?
76
+ raise ArgumentError, "#{connection.class} does not support :returning"
77
+ end
78
+
79
+ if skip_duplicates? && !connection.supports_insert_on_duplicate_skip?
80
+ raise ArgumentError, "#{connection.class} does not support skipping duplicates"
81
+ end
82
+
83
+ if update_duplicates? && !connection.supports_insert_on_duplicate_update?
84
+ raise ArgumentError, "#{connection.class} does not support upsert"
85
+ end
86
+
87
+ if unique_by && !connection.supports_insert_conflict_target?
88
+ raise ArgumentError, "#{connection.class} does not support :unique_by"
89
+ end
90
+ end
91
+
92
+
93
+ def to_sql
94
+ connection.build_insert_sql(ActiveRecord::InsertAll::Builder.new(self))
95
+ end
96
+
97
+
98
+ def readonly_columns
99
+ primary_keys + model.readonly_attributes.to_a
100
+ end
101
+
102
+ def unique_by_columns
103
+ Array(unique_by&.columns)
104
+ end
105
+
106
+
107
+ def verify_attributes(attributes)
108
+ if keys != attributes.keys.to_set
109
+ raise ArgumentError, "All objects being inserted must have the same keys"
110
+ end
111
+ end
112
+
113
+
114
+ class Builder
115
+ attr_reader :model
116
+
117
+ delegate :skip_duplicates?, :update_duplicates?, :keys, to: :insert_all
118
+
119
+ def initialize(insert_all)
120
+ @insert_all, @model, @connection = insert_all, insert_all.model, insert_all.connection
121
+ end
122
+
123
+ def into
124
+ "INTO #{model.quoted_table_name}(#{columns_list})"
125
+ end
126
+
127
+ def values_list
128
+ types = extract_types_from_columns_on(model.table_name, keys: keys)
129
+
130
+ values_list = insert_all.map_key_with_value do |key, value|
131
+ connection.with_yaml_fallback(types[key].serialize(value))
132
+ end
133
+
134
+ Arel::InsertManager.new.create_values_list(values_list).to_sql
135
+ end
136
+
137
+ def returning
138
+ format_columns(insert_all.returning) if insert_all.returning
139
+ end
140
+
141
+ def conflict_target
142
+ if index = insert_all.unique_by
143
+ sql = +"(#{format_columns(index.columns)})"
144
+ sql << " WHERE #{index.where}" if index.where
145
+ sql
146
+ elsif update_duplicates?
147
+ "(#{format_columns(insert_all.primary_keys)})"
148
+ end
149
+ end
150
+
151
+ def updatable_columns
152
+ quote_columns(insert_all.updatable_columns)
153
+ end
154
+
155
+ private
156
+ attr_reader :connection, :insert_all
157
+
158
+ def columns_list
159
+ format_columns(insert_all.keys)
160
+ end
161
+
162
+ def extract_types_from_columns_on(table_name, keys:)
163
+ columns = connection.schema_cache.columns_hash(table_name)
164
+
165
+ unknown_column = (keys - columns.keys).first
166
+ raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
167
+
168
+ keys.map { |key| [ key, connection.lookup_cast_type_from_column(columns[key]) ] }.to_h
169
+ end
170
+
171
+ def format_columns(columns)
172
+ quote_columns(columns).join(",")
173
+ end
174
+
175
+ def quote_columns(columns)
176
+ columns.map(&connection.method(:quote_column_name))
177
+ end
178
+ end
179
+ end
180
+ end
@@ -22,6 +22,14 @@ module ActiveRecord
22
22
  #
23
23
  # This is +true+, by default on Rails 5.2 and above.
24
24
  class_attribute :cache_versioning, instance_writer: false, default: false
25
+
26
+ ##
27
+ # :singleton-method:
28
+ # Indicates whether to use a stable #cache_key method that is accompanied
29
+ # by a changing version in the #cache_version method on collections.
30
+ #
31
+ # This is +false+, by default until Rails 6.1.
32
+ class_attribute :collection_cache_versioning, instance_writer: false, default: false
25
33
  end
26
34
 
27
35
  # Returns a +String+, which Action Pack uses for constructing a URL to this
@@ -152,6 +160,10 @@ module ActiveRecord
152
160
  end
153
161
  end
154
162
  end
163
+
164
+ def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
165
+ collection.send(:compute_cache_key, timestamp_column)
166
+ end
155
167
  end
156
168
 
157
169
  private
@@ -180,7 +192,7 @@ module ActiveRecord
180
192
  # raw_timestamp_to_cache_version(timestamp)
181
193
  # # => "20181015200215266505"
182
194
  #
183
- # Postgres truncates trailing zeros,
195
+ # PostgreSQL truncates trailing zeros,
184
196
  # https://github.com/postgres/postgres/commit/3e1beda2cde3495f41290e1ece5d544525810214
185
197
  # to account for this we pad the output with zeros
186
198
  def raw_timestamp_to_cache_version(timestamp)
@@ -17,7 +17,7 @@ module ActiveRecord
17
17
  end
18
18
 
19
19
  def table_name
20
- "#{table_name_prefix}#{ActiveRecord::Base.internal_metadata_table_name}#{table_name_suffix}"
20
+ "#{table_name_prefix}#{internal_metadata_table_name}#{table_name_suffix}"
21
21
  end
22
22
 
23
23
  def []=(key, value)
@@ -44,6 +44,10 @@ module ActiveRecord
44
44
  end
45
45
  end
46
46
  end
47
+
48
+ def drop_table
49
+ connection.drop_table table_name, if_exists: true
50
+ end
47
51
  end
48
52
  end
49
53
  end
@@ -71,9 +71,8 @@ module ActiveRecord
71
71
  end
72
72
 
73
73
  def _touch_row(attribute_names, time)
74
+ @_touch_attr_names << self.class.locking_column if locking_enabled?
74
75
  super
75
- ensure
76
- clear_attribute_change(self.class.locking_column) if locking_enabled?
77
76
  end
78
77
 
79
78
  def _update_row(attribute_names, attempted_action = "update")
@@ -88,7 +87,7 @@ module ActiveRecord
88
87
 
89
88
  affected_rows = self.class._update_record(
90
89
  attributes_with_values(attribute_names),
91
- self.class.primary_key => id_in_database,
90
+ @primary_key => id_in_database,
92
91
  locking_column => previous_lock_value
93
92
  )
94
93
 
@@ -111,7 +110,7 @@ module ActiveRecord
111
110
  locking_column = self.class.locking_column
112
111
 
113
112
  affected_rows = self.class._delete_record(
114
- self.class.primary_key => id_in_database,
113
+ @primary_key => id_in_database,
115
114
  locking_column => read_attribute_before_type_cast(locking_column)
116
115
  )
117
116