activerecord 7.0.3.1 → 7.0.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +97 -0
- data/lib/active_record/associations/collection_association.rb +0 -1
- data/lib/active_record/associations/collection_proxy.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +7 -4
- data/lib/active_record/associations/join_dependency.rb +17 -13
- data/lib/active_record/associations.rb +6 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -0
- data/lib/active_record/coders/yaml_column.rb +11 -5
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +5 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +7 -2
- data/lib/active_record/delegated_type.rb +1 -1
- data/lib/active_record/encryption/message.rb +1 -1
- data/lib/active_record/encryption/properties.rb +1 -1
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/middleware/database_selector.rb +1 -1
- data/lib/active_record/model_schema.rb +21 -9
- data/lib/active_record/railtie.rb +6 -34
- data/lib/active_record/railties/databases.rake +15 -10
- data/lib/active_record/relation/query_methods.rb +19 -5
- data/lib/active_record/relation.rb +1 -0
- data/lib/active_record/scoping/default.rb +4 -2
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/store.rb +7 -2
- data/lib/active_record/test_fixtures.rb +9 -5
- data/lib/active_record.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18986b8f256d988204ff7b48287980a88e138a4280d637cf28310e551082987d
|
4
|
+
data.tar.gz: 8054f80c87f48a264d08f006b789e2c3680155e0ed7fb5a5698d962f7ff0d8bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a01f7c0f730da3cfc0bfcda6f7c9a2e3f4d2747137f87175671d79021643f09f34fcf373cb400f247159d6551589f51de73241f10ac3373159865db6e04f0fc
|
7
|
+
data.tar.gz: a4aa9659e71f1e8c11914727eacd07061128f8d68b0f609c08b272025c9923419a3a58f6d789da6a467258cad69795e3e0aa265f34ffcce4b39d8bd0cb5d8386
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,100 @@
|
|
1
|
+
## Rails 7.0.4 (September 09, 2022) ##
|
2
|
+
|
3
|
+
* Symbol is allowed by default for YAML columns
|
4
|
+
|
5
|
+
*Étienne Barrié*
|
6
|
+
|
7
|
+
* Fix `ActiveRecord::Store` to serialize as a regular Hash
|
8
|
+
|
9
|
+
Previously it would serialize as an `ActiveSupport::HashWithIndifferentAccess`
|
10
|
+
which is wasteful and cause problem with YAML safe_load.
|
11
|
+
|
12
|
+
*Jean Boussier*
|
13
|
+
|
14
|
+
* Add `timestamptz` as a time zone aware type for PostgreSQL
|
15
|
+
|
16
|
+
This is required for correctly parsing `timestamp with time zone` values in your database.
|
17
|
+
|
18
|
+
If you don't want this, you can opt out by adding this initializer:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
ActiveRecord::Base.time_zone_aware_types -= [:timestamptz]
|
22
|
+
```
|
23
|
+
|
24
|
+
*Alex Ghiculescu*
|
25
|
+
|
26
|
+
* Fix supporting timezone awareness for `tsrange` and `tstzrange` array columns.
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
# In database migrations
|
30
|
+
add_column :shops, :open_hours, :tsrange, array: true
|
31
|
+
# In app config
|
32
|
+
ActiveRecord::Base.time_zone_aware_types += [:tsrange]
|
33
|
+
# In the code times are properly converted to app time zone
|
34
|
+
Shop.create!(open_hours: [Time.current..8.hour.from_now])
|
35
|
+
```
|
36
|
+
|
37
|
+
*Wojciech Wnętrzak*
|
38
|
+
|
39
|
+
* Resolve issue where a relation cache_version could be left stale.
|
40
|
+
|
41
|
+
Previously, when `reset` was called on a relation object it did not reset the cache_versions
|
42
|
+
ivar. This led to a confusing situation where despite having the correct data the relation
|
43
|
+
still reported a stale cache_version.
|
44
|
+
|
45
|
+
Usage:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
developers = Developer.all
|
49
|
+
developers.cache_version
|
50
|
+
|
51
|
+
Developer.update_all(updated_at: Time.now.utc + 1.second)
|
52
|
+
|
53
|
+
developers.cache_version # Stale cache_version
|
54
|
+
developers.reset
|
55
|
+
developers.cache_version # Returns the current correct cache_version
|
56
|
+
```
|
57
|
+
|
58
|
+
Fixes #45341.
|
59
|
+
|
60
|
+
*Austen Madden*
|
61
|
+
|
62
|
+
* Fix `load_async` when called on an association proxy.
|
63
|
+
|
64
|
+
Calling `load_async` directly an association would schedule
|
65
|
+
a query but never use it.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
comments = post.comments.load_async # schedule a query
|
69
|
+
comments.to_a # perform an entirely new sync query
|
70
|
+
```
|
71
|
+
|
72
|
+
Now it does use the async query, however note that it doesn't
|
73
|
+
cause the association to be loaded.
|
74
|
+
|
75
|
+
*Jean Boussier*
|
76
|
+
|
77
|
+
* Fix eager loading for models without primary keys.
|
78
|
+
|
79
|
+
*Anmol Chopra*, *Matt Lawrence*, and *Jonathan Hefner*
|
80
|
+
|
81
|
+
* `rails db:schema:{dump,load}` now checks `ENV["SCHEMA_FORMAT"]` before config
|
82
|
+
|
83
|
+
Since `rails db:structure:{dump,load}` was deprecated there wasn't a simple
|
84
|
+
way to dump a schema to both SQL and Ruby formats. You can now do this with
|
85
|
+
an environment variable. For example:
|
86
|
+
|
87
|
+
```
|
88
|
+
SCHEMA_FORMAT=sql rake db:schema:dump
|
89
|
+
```
|
90
|
+
|
91
|
+
*Alex Ghiculescu*
|
92
|
+
|
93
|
+
* Fix Hstore deserialize regression.
|
94
|
+
|
95
|
+
*edsharp*
|
96
|
+
|
97
|
+
|
1
98
|
## Rails 7.0.3.1 (July 12, 2022) ##
|
2
99
|
|
3
100
|
* Change ActiveRecord::Coders::YAMLColumn default to safe_load
|
@@ -320,7 +320,6 @@ module ActiveRecord
|
|
320
320
|
# * Otherwise, attributes should have the value found in the database
|
321
321
|
def merge_target_lists(persisted, memory)
|
322
322
|
return persisted if memory.empty?
|
323
|
-
return memory if persisted.empty?
|
324
323
|
|
325
324
|
persisted.map! do |record|
|
326
325
|
if mem_record = memory.delete(record)
|
@@ -1108,7 +1108,7 @@ module ActiveRecord
|
|
1108
1108
|
].flat_map { |klass|
|
1109
1109
|
klass.public_instance_methods(false)
|
1110
1110
|
} - self.public_instance_methods(false) - [:select] + [
|
1111
|
-
:scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all
|
1111
|
+
:scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all, :load_async
|
1112
1112
|
]
|
1113
1113
|
|
1114
1114
|
delegate(*delegate_methods, to: :scope)
|
@@ -79,10 +79,13 @@ module ActiveRecord
|
|
79
79
|
scope.count(:all)
|
80
80
|
end
|
81
81
|
|
82
|
-
# If there's nothing in the database
|
83
|
-
#
|
84
|
-
#
|
85
|
-
|
82
|
+
# If there's nothing in the database, @target should only contain new
|
83
|
+
# records or be an empty array. This is a documented side-effect of
|
84
|
+
# the method that may avoid an extra SELECT.
|
85
|
+
if count == 0
|
86
|
+
target.select!(&:new_record?)
|
87
|
+
loaded!
|
88
|
+
end
|
86
89
|
|
87
90
|
[association_scope.limit_value, count].compact.min
|
88
91
|
end
|
@@ -252,35 +252,39 @@ module ActiveRecord
|
|
252
252
|
next
|
253
253
|
end
|
254
254
|
|
255
|
-
|
256
|
-
|
257
|
-
|
255
|
+
if node.primary_key
|
256
|
+
key = aliases.column_alias(node, node.primary_key)
|
257
|
+
id = row[key]
|
258
|
+
else
|
259
|
+
key = aliases.column_alias(node, node.reflection.join_primary_key.to_s)
|
260
|
+
id = nil # Avoid id-based model caching.
|
261
|
+
end
|
262
|
+
|
263
|
+
if row[key].nil?
|
258
264
|
nil_association = ar_parent.association(node.reflection.name)
|
259
265
|
nil_association.loaded!
|
260
266
|
next
|
261
267
|
end
|
262
268
|
|
263
|
-
model = seen[ar_parent][node][id]
|
264
|
-
|
265
|
-
if model
|
266
|
-
construct(model, node, row, seen, model_cache, strict_loading_value)
|
267
|
-
else
|
269
|
+
unless model = seen[ar_parent][node][id]
|
268
270
|
model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
|
269
|
-
|
270
|
-
seen[ar_parent][node][id] = model
|
271
|
-
construct(model, node, row, seen, model_cache, strict_loading_value)
|
271
|
+
seen[ar_parent][node][id] = model if id
|
272
272
|
end
|
273
|
+
|
274
|
+
construct(model, node, row, seen, model_cache, strict_loading_value)
|
273
275
|
end
|
274
276
|
end
|
275
277
|
|
276
278
|
def construct_model(record, node, row, model_cache, id, strict_loading_value)
|
277
279
|
other = record.association(node.reflection.name)
|
278
280
|
|
279
|
-
model = model_cache[node][id]
|
280
|
-
node.instantiate(row, aliases.column_aliases(node)) do |m|
|
281
|
+
unless model = model_cache[node][id]
|
282
|
+
model = node.instantiate(row, aliases.column_aliases(node)) do |m|
|
281
283
|
m.strict_loading! if strict_loading_value
|
282
284
|
other.set_inverse_instance(m)
|
283
285
|
end
|
286
|
+
model_cache[node][id] = model if id
|
287
|
+
end
|
284
288
|
|
285
289
|
if node.reflection.collection?
|
286
290
|
other.target.push(model)
|
@@ -628,15 +628,15 @@ module ActiveRecord
|
|
628
628
|
#
|
629
629
|
# Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
|
630
630
|
#
|
631
|
-
#
|
632
|
-
#
|
633
|
-
#
|
631
|
+
# * <tt>firm.clients.destroy(client)</tt>
|
632
|
+
# * <tt>firm.clients.destroy(*clients)</tt>
|
633
|
+
# * <tt>firm.clients.destroy_all</tt>
|
634
634
|
#
|
635
635
|
# +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
|
636
636
|
#
|
637
|
-
#
|
638
|
-
#
|
639
|
-
#
|
637
|
+
# * <tt>firm.clients.delete(client)</tt>
|
638
|
+
# * <tt>firm.clients.delete(*clients)</tt>
|
639
|
+
# * <tt>firm.clients.delete_all</tt>
|
640
640
|
#
|
641
641
|
# == Association extensions
|
642
642
|
#
|
@@ -19,6 +19,8 @@ module ActiveRecord
|
|
19
19
|
|
20
20
|
if value.is_a?(Hash)
|
21
21
|
set_time_zone_without_conversion(super)
|
22
|
+
elsif value.is_a?(Range)
|
23
|
+
Range.new(user_input_in_time_zone(value.begin), user_input_in_time_zone(value.end), value.exclude_end?)
|
22
24
|
elsif value.respond_to?(:in_time_zone)
|
23
25
|
begin
|
24
26
|
super(user_input_in_time_zone(value)) || super
|
@@ -40,6 +42,8 @@ module ActiveRecord
|
|
40
42
|
value.in_time_zone
|
41
43
|
elsif value.respond_to?(:infinite?) && value.infinite?
|
42
44
|
value
|
45
|
+
elsif value.is_a?(Range)
|
46
|
+
Range.new(convert_time_to_time_zone(value.begin), convert_time_to_time_zone(value.end), value.exclude_end?)
|
43
47
|
else
|
44
48
|
map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
|
45
49
|
end
|
@@ -45,14 +45,20 @@ module ActiveRecord
|
|
45
45
|
raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
|
46
46
|
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
else
|
52
|
-
if YAML.respond_to?(:unsafe_load)
|
48
|
+
if YAML.respond_to?(:unsafe_load)
|
49
|
+
def yaml_load(payload)
|
50
|
+
if ActiveRecord.use_yaml_unsafe_load
|
53
51
|
YAML.unsafe_load(payload)
|
54
52
|
else
|
53
|
+
YAML.safe_load(payload, permitted_classes: ActiveRecord.yaml_column_permitted_classes, aliases: true)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
else
|
57
|
+
def yaml_load(payload)
|
58
|
+
if ActiveRecord.use_yaml_unsafe_load
|
55
59
|
YAML.load(payload)
|
60
|
+
else
|
61
|
+
YAML.safe_load(payload, permitted_classes: ActiveRecord.yaml_column_permitted_classes, aliases: true)
|
56
62
|
end
|
57
63
|
end
|
58
64
|
end
|
@@ -139,7 +139,7 @@ module ActiveRecord
|
|
139
139
|
end
|
140
140
|
|
141
141
|
def field_ordered_value(column, values) # :nodoc:
|
142
|
-
field = Arel::Nodes::NamedFunction.new("FIELD", [column, values.reverse])
|
142
|
+
field = Arel::Nodes::NamedFunction.new("FIELD", [column, values.reverse.map { |value| Arel::Nodes.build_quoted(value) }])
|
143
143
|
Arel::Nodes::Descending.new(field)
|
144
144
|
end
|
145
145
|
|
@@ -711,6 +711,10 @@ module ActiveRecord
|
|
711
711
|
options[:comment] = column.comment
|
712
712
|
end
|
713
713
|
|
714
|
+
unless options.key?(:collation)
|
715
|
+
options[:collation] = column.collation
|
716
|
+
end
|
717
|
+
|
714
718
|
unless options.key?(:auto_increment)
|
715
719
|
options[:auto_increment] = column.auto_increment?
|
716
720
|
end
|
@@ -159,7 +159,7 @@ module ActiveRecord
|
|
159
159
|
end
|
160
160
|
|
161
161
|
def default_type(table_name, field_name)
|
162
|
-
match = create_table_info(table_name)
|
162
|
+
match = create_table_info(table_name)&.match(/`#{field_name}` (.+) DEFAULT ('|\d+|[A-z]+)/)
|
163
163
|
default_pre = match[2] if match
|
164
164
|
|
165
165
|
if default_pre == "'"
|
@@ -26,7 +26,7 @@ module ActiveRecord
|
|
26
26
|
raise(ArgumentError, ERROR % scanner.string.inspect)
|
27
27
|
end
|
28
28
|
|
29
|
-
unless key = scanner.
|
29
|
+
unless key = scanner.scan(/^(\\[\\"]|[^\\"])*?(?=")/)
|
30
30
|
raise(ArgumentError, ERROR % scanner.string.inspect)
|
31
31
|
end
|
32
32
|
|
@@ -41,7 +41,7 @@ module ActiveRecord
|
|
41
41
|
raise(ArgumentError, ERROR % scanner.string.inspect)
|
42
42
|
end
|
43
43
|
|
44
|
-
unless value = scanner.
|
44
|
+
unless value = scanner.scan(/^(\\[\\"]|[^\\"])*?(?=")/)
|
45
45
|
raise(ArgumentError, ERROR % scanner.string.inspect)
|
46
46
|
end
|
47
47
|
|
@@ -45,8 +45,10 @@ Rails needs superuser privileges to disable referential integrity.
|
|
45
45
|
BEGIN
|
46
46
|
FOR r IN (
|
47
47
|
SELECT FORMAT(
|
48
|
-
'UPDATE pg_constraint SET convalidated=false WHERE conname = ''%I''; ALTER TABLE %I VALIDATE CONSTRAINT %I;',
|
48
|
+
'UPDATE pg_constraint SET convalidated=false WHERE conname = ''%I'' AND connamespace::regnamespace = ''%I''::regnamespace; ALTER TABLE %I.%I VALIDATE CONSTRAINT %I;',
|
49
49
|
constraint_name,
|
50
|
+
table_schema,
|
51
|
+
table_schema,
|
50
52
|
table_name,
|
51
53
|
constraint_name
|
52
54
|
) AS constraint_check
|
@@ -1063,5 +1063,6 @@ module ActiveRecord
|
|
1063
1063
|
ActiveRecord::Type.register(:vector, OID::Vector, adapter: :postgresql)
|
1064
1064
|
ActiveRecord::Type.register(:xml, OID::Xml, adapter: :postgresql)
|
1065
1065
|
end
|
1066
|
+
ActiveSupport.run_load_hooks(:active_record_postgresqladapter, PostgreSQLAdapter)
|
1066
1067
|
end
|
1067
1068
|
end
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
21
21
|
WHERE name = #{quote(row['name'])} AND type = 'index'
|
22
22
|
SQL
|
23
23
|
|
24
|
-
/\bON\b\s*"?(\w+?)"?\s*\((?<expressions>.+?)\)(?:\s*WHERE\b\s*(?<where>.+))?\z/i =~ index_sql
|
24
|
+
/\bON\b\s*"?(\w+?)"?\s*\((?<expressions>.+?)\)(?:\s*WHERE\b\s*(?<where>.+))?(?:\s*\/\*.*\*\/)?\z/i =~ index_sql
|
25
25
|
|
26
26
|
columns = exec_query("PRAGMA index_info(#{quote(row['name'])})", "SCHEMA").map do |col|
|
27
27
|
col["name"]
|
@@ -341,7 +341,7 @@ module ActiveRecord
|
|
341
341
|
end
|
342
342
|
|
343
343
|
def get_database_version # :nodoc:
|
344
|
-
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
|
344
|
+
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)", "SCHEMA"))
|
345
345
|
end
|
346
346
|
|
347
347
|
def check_version # :nodoc:
|
@@ -477,8 +477,13 @@ module ActiveRecord
|
|
477
477
|
options[:rename][column.name.to_sym] ||
|
478
478
|
column.name) : column.name
|
479
479
|
|
480
|
+
if column.has_default?
|
481
|
+
type = lookup_cast_type_from_column(column)
|
482
|
+
default = type.deserialize(column.default)
|
483
|
+
end
|
484
|
+
|
480
485
|
@definition.column(column_name, column.type,
|
481
|
-
limit: column.limit, default:
|
486
|
+
limit: column.limit, default: default,
|
482
487
|
precision: column.precision, scale: column.scale,
|
483
488
|
null: column.null, collation: column.collation,
|
484
489
|
primary_key: column_name == from_primary_key
|
@@ -136,7 +136,7 @@ module ActiveRecord
|
|
136
136
|
# end
|
137
137
|
# end
|
138
138
|
#
|
139
|
-
# Now you can list a bunch of entries, call
|
139
|
+
# Now you can list a bunch of entries, call <tt>Entry#title</tt>, and polymorphism will provide you with the answer.
|
140
140
|
#
|
141
141
|
# == Nested Attributes
|
142
142
|
#
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
#
|
13
13
|
# message.headers.encrypted_data_key # instead of message.headers[:k]
|
14
14
|
#
|
15
|
-
# See +Properties
|
15
|
+
# See +Properties::DEFAULT_PROPERTIES+, Key, Message
|
16
16
|
class Properties
|
17
17
|
ALLOWED_VALUE_CLASSES = [String, ActiveRecord::Encryption::Message, Numeric, TrueClass, FalseClass, Symbol, NilClass]
|
18
18
|
|
@@ -44,7 +44,7 @@ module ActiveRecord
|
|
44
44
|
# config.active_record.database_resolver_context = MyResolver::MySession
|
45
45
|
#
|
46
46
|
# Note: If you are using `rails new my_app --minimal` you will need to call
|
47
|
-
# `require "active_support/core_ext/integer/time"` to load the
|
47
|
+
# `require "active_support/core_ext/integer/time"` to load the libraries
|
48
48
|
# for +Time+.
|
49
49
|
class DatabaseSelector
|
50
50
|
def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
|
@@ -126,6 +126,27 @@ module ActiveRecord
|
|
126
126
|
# +:immutable_string+. This setting does not affect the behavior of
|
127
127
|
# <tt>attribute :foo, :string</tt>. Defaults to false.
|
128
128
|
|
129
|
+
##
|
130
|
+
# :singleton-method: inheritance_column
|
131
|
+
# :call-seq: inheritance_column
|
132
|
+
#
|
133
|
+
# The name of the table column which stores the class name on single-table
|
134
|
+
# inheritance situations.
|
135
|
+
#
|
136
|
+
# The default inheritance column name is +type+, which means it's a
|
137
|
+
# reserved word inside Active Record. To be able to use single-table
|
138
|
+
# inheritance with another column name, or to use the column +type+ in
|
139
|
+
# your own model for something else, you can set +inheritance_column+:
|
140
|
+
#
|
141
|
+
# self.inheritance_column = 'zoink'
|
142
|
+
|
143
|
+
##
|
144
|
+
# :singleton-method: inheritance_column=
|
145
|
+
# :call-seq: inheritance_column=(column)
|
146
|
+
#
|
147
|
+
# Defines the name of the table column which will store the class name on single-table
|
148
|
+
# inheritance situations.
|
149
|
+
|
129
150
|
included do
|
130
151
|
class_attribute :primary_key_prefix_type, instance_writer: false
|
131
152
|
class_attribute :table_name_prefix, instance_writer: false, default: ""
|
@@ -136,15 +157,6 @@ module ActiveRecord
|
|
136
157
|
class_attribute :implicit_order_column, instance_accessor: false
|
137
158
|
class_attribute :immutable_strings_by_default, instance_accessor: false
|
138
159
|
|
139
|
-
# Defines the name of the table column which will store the class name on single-table
|
140
|
-
# inheritance situations.
|
141
|
-
#
|
142
|
-
# The default inheritance column name is +type+, which means it's a
|
143
|
-
# reserved word inside Active Record. To be able to use single-table
|
144
|
-
# inheritance with another column name, or to use the column +type+ in
|
145
|
-
# your own model for something else, you can set +inheritance_column+:
|
146
|
-
#
|
147
|
-
# self.inheritance_column = 'zoink'
|
148
160
|
class_attribute :inheritance_column, instance_accessor: false, default: "type"
|
149
161
|
singleton_class.class_eval do
|
150
162
|
alias_method :_inheritance_column=, :inheritance_column=
|
@@ -78,6 +78,12 @@ module ActiveRecord
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
+
initializer "active_record.postgresql_time_zone_aware_types" do
|
82
|
+
ActiveSupport.on_load(:active_record_postgresqladapter) do
|
83
|
+
ActiveRecord::Base.time_zone_aware_types << :timestamptz
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
81
87
|
initializer "active_record.logger" do
|
82
88
|
ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger }
|
83
89
|
end
|
@@ -94,22 +100,6 @@ module ActiveRecord
|
|
94
100
|
end
|
95
101
|
end
|
96
102
|
|
97
|
-
initializer "active_record.database_selector" do
|
98
|
-
if options = config.active_record.database_selector
|
99
|
-
resolver = config.active_record.database_resolver
|
100
|
-
operations = config.active_record.database_resolver_context
|
101
|
-
config.app_middleware.use ActiveRecord::Middleware::DatabaseSelector, resolver, operations, options
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
initializer "active_record.shard_selector" do
|
106
|
-
if resolver = config.active_record.shard_resolver
|
107
|
-
options = config.active_record.shard_selector || {}
|
108
|
-
|
109
|
-
config.app_middleware.use ActiveRecord::Middleware::ShardSelector, resolver, options
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
103
|
initializer "Check for cache versioning support" do
|
114
104
|
config.after_initialize do |app|
|
115
105
|
ActiveSupport.on_load(:active_record) do
|
@@ -403,23 +393,5 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
403
393
|
end
|
404
394
|
end
|
405
395
|
end
|
406
|
-
|
407
|
-
initializer "active_record.use_yaml_unsafe_load" do |app|
|
408
|
-
config.after_initialize do
|
409
|
-
unless app.config.active_record.use_yaml_unsafe_load.nil?
|
410
|
-
ActiveRecord.use_yaml_unsafe_load =
|
411
|
-
app.config.active_record.use_yaml_unsafe_load
|
412
|
-
end
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
initializer "active_record.yaml_column_permitted_classes" do |app|
|
417
|
-
config.after_initialize do
|
418
|
-
unless app.config.active_record.yaml_column_permitted_classes.nil?
|
419
|
-
ActiveRecord.yaml_column_permitted_classes =
|
420
|
-
app.config.active_record.yaml_column_permitted_classes
|
421
|
-
end
|
422
|
-
end
|
423
|
-
end
|
424
396
|
end
|
425
397
|
end
|
@@ -452,30 +452,32 @@ db_namespace = namespace :db do
|
|
452
452
|
end
|
453
453
|
|
454
454
|
namespace :schema do
|
455
|
-
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
|
455
|
+
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
|
456
456
|
task dump: :load_config do
|
457
457
|
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
|
458
458
|
if db_config.schema_dump
|
459
459
|
ActiveRecord::Base.establish_connection(db_config)
|
460
|
-
ActiveRecord
|
460
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
461
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
|
461
462
|
end
|
462
463
|
end
|
463
464
|
|
464
465
|
db_namespace["schema:dump"].reenable
|
465
466
|
end
|
466
467
|
|
467
|
-
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the database"
|
468
|
+
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the database"
|
468
469
|
task load: [:load_config, :check_protected_environments] do
|
469
470
|
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
|
470
471
|
end
|
471
472
|
|
472
473
|
namespace :dump do
|
473
474
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
474
|
-
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) for #{name} database"
|
475
|
+
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) for #{name} database"
|
475
476
|
task name => :load_config do
|
476
477
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
477
478
|
ActiveRecord::Base.establish_connection(db_config)
|
478
|
-
ActiveRecord
|
479
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
480
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
|
479
481
|
db_namespace["schema:dump:#{name}"].reenable
|
480
482
|
end
|
481
483
|
end
|
@@ -483,11 +485,12 @@ db_namespace = namespace :db do
|
|
483
485
|
|
484
486
|
namespace :load do
|
485
487
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
486
|
-
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the #{name} database"
|
488
|
+
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the #{name} database"
|
487
489
|
task name => [:load_config, :check_protected_environments] do
|
488
490
|
original_db_config = ActiveRecord::Base.connection_db_config
|
489
491
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
490
|
-
ActiveRecord
|
492
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
493
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
491
494
|
ensure
|
492
495
|
ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
|
493
496
|
end
|
@@ -545,12 +548,13 @@ db_namespace = namespace :db do
|
|
545
548
|
db_namespace["test:load_schema"].invoke
|
546
549
|
end
|
547
550
|
|
548
|
-
# desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `config.active_record.schema_format`)"
|
551
|
+
# desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
|
549
552
|
task load_schema: %w(db:test:purge) do
|
550
553
|
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
|
551
554
|
ActiveRecord::Schema.verbose = false
|
552
555
|
ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
|
553
|
-
ActiveRecord
|
556
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
557
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
554
558
|
end
|
555
559
|
ensure
|
556
560
|
if should_reconnect
|
@@ -586,7 +590,8 @@ db_namespace = namespace :db do
|
|
586
590
|
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
|
587
591
|
ActiveRecord::Schema.verbose = false
|
588
592
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
|
589
|
-
ActiveRecord
|
593
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
594
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
590
595
|
ensure
|
591
596
|
if should_reconnect
|
592
597
|
ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
|
@@ -10,10 +10,10 @@ module ActiveRecord
|
|
10
10
|
module QueryMethods
|
11
11
|
include ActiveModel::ForbiddenAttributesProtection
|
12
12
|
|
13
|
-
# WhereChain objects act as placeholder for queries in which
|
14
|
-
# In this case,
|
13
|
+
# WhereChain objects act as placeholder for queries in which +where+ does not have any parameter.
|
14
|
+
# In this case, +where+ can be chained to return a new relation.
|
15
15
|
class WhereChain
|
16
|
-
def initialize(scope)
|
16
|
+
def initialize(scope) # :nodoc:
|
17
17
|
@scope = scope
|
18
18
|
end
|
19
19
|
|
@@ -717,12 +717,26 @@ module ActiveRecord
|
|
717
717
|
# === no argument
|
718
718
|
#
|
719
719
|
# If no argument is passed, #where returns a new instance of WhereChain, that
|
720
|
-
# can be chained with #not
|
720
|
+
# can be chained with WhereChain#not, WhereChain#missing, or WhereChain#associated.
|
721
|
+
#
|
722
|
+
# Chaining with WhereChain#not:
|
721
723
|
#
|
722
724
|
# User.where.not(name: "Jon")
|
723
725
|
# # SELECT * FROM users WHERE name != 'Jon'
|
724
726
|
#
|
725
|
-
#
|
727
|
+
# Chaining with WhereChain#associated:
|
728
|
+
#
|
729
|
+
# Post.where.associated(:author)
|
730
|
+
# # SELECT "posts".* FROM "posts"
|
731
|
+
# # INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
|
732
|
+
# # WHERE "authors"."id" IS NOT NULL
|
733
|
+
#
|
734
|
+
# Chaining with WhereChain#missing:
|
735
|
+
#
|
736
|
+
# Post.where.missing(:author)
|
737
|
+
# # SELECT "posts".* FROM "posts"
|
738
|
+
# # LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id"
|
739
|
+
# # WHERE "authors"."id" IS NULL
|
726
740
|
#
|
727
741
|
# === blank condition
|
728
742
|
#
|
@@ -146,11 +146,13 @@ module ActiveRecord
|
|
146
146
|
end
|
147
147
|
elsif default_scopes.any?
|
148
148
|
evaluate_default_scope do
|
149
|
-
default_scopes.inject(relation) do |
|
149
|
+
default_scopes.inject(relation) do |combined_scope, scope_obj|
|
150
150
|
if execute_scope?(all_queries, scope_obj)
|
151
151
|
scope = scope_obj.scope.respond_to?(:to_proc) ? scope_obj.scope : scope_obj.scope.method(:call)
|
152
152
|
|
153
|
-
|
153
|
+
combined_scope.instance_exec(&scope) || combined_scope
|
154
|
+
else
|
155
|
+
combined_scope
|
154
156
|
end
|
155
157
|
end
|
156
158
|
end
|
@@ -97,7 +97,7 @@ module ActiveRecord
|
|
97
97
|
|
98
98
|
# Returns a signed id that's generated using a preconfigured +ActiveSupport::MessageVerifier+ instance.
|
99
99
|
# This signed id is tamper proof, so it's safe to send in an email or otherwise share with the outside world.
|
100
|
-
# It can
|
100
|
+
# It can furthermore be set to expire (the default is not to expire), and scoped down with a specific purpose.
|
101
101
|
# If the expiration date has been exceeded before +find_signed+ is called, the id won't find the designated
|
102
102
|
# record. If a purpose is set, this too must match.
|
103
103
|
#
|
data/lib/active_record/store.rb
CHANGED
@@ -59,7 +59,7 @@ module ActiveRecord
|
|
59
59
|
# u.color = 'green'
|
60
60
|
# u.color_changed? # => true
|
61
61
|
# u.color_was # => 'black'
|
62
|
-
# u.color_change # => ['black', '
|
62
|
+
# u.color_change # => ['black', 'green']
|
63
63
|
#
|
64
64
|
# # Add additional accessors to an existing store through store_accessor
|
65
65
|
# class SuperUser < User
|
@@ -268,7 +268,7 @@ module ActiveRecord
|
|
268
268
|
end
|
269
269
|
|
270
270
|
def dump(obj)
|
271
|
-
@coder.dump
|
271
|
+
@coder.dump as_regular_hash(obj)
|
272
272
|
end
|
273
273
|
|
274
274
|
def load(yaml)
|
@@ -285,6 +285,11 @@ module ActiveRecord
|
|
285
285
|
ActiveSupport::HashWithIndifferentAccess.new
|
286
286
|
end
|
287
287
|
end
|
288
|
+
|
289
|
+
private
|
290
|
+
def as_regular_hash(obj)
|
291
|
+
obj.respond_to?(:to_hash) ? obj.to_hash : {}
|
292
|
+
end
|
288
293
|
end
|
289
294
|
end
|
290
295
|
end
|
@@ -137,7 +137,7 @@ module ActiveRecord
|
|
137
137
|
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
138
138
|
spec_name = payload[:spec_name] if payload.key?(:spec_name)
|
139
139
|
shard = payload[:shard] if payload.key?(:shard)
|
140
|
-
setup_shared_connection_pool
|
140
|
+
setup_shared_connection_pool if ActiveRecord.legacy_connection_handling
|
141
141
|
|
142
142
|
if spec_name
|
143
143
|
begin
|
@@ -146,10 +146,14 @@ module ActiveRecord
|
|
146
146
|
connection = nil
|
147
147
|
end
|
148
148
|
|
149
|
-
if connection
|
150
|
-
|
151
|
-
|
152
|
-
|
149
|
+
if connection
|
150
|
+
setup_shared_connection_pool unless ActiveRecord.legacy_connection_handling
|
151
|
+
|
152
|
+
if !@fixture_connections.include?(connection)
|
153
|
+
connection.begin_transaction joinable: false, _lazy: false
|
154
|
+
connection.pool.lock_thread = true if lock_threads
|
155
|
+
@fixture_connections << connection
|
156
|
+
end
|
153
157
|
end
|
154
158
|
end
|
155
159
|
end
|
data/lib/active_record.rb
CHANGED
@@ -352,7 +352,7 @@ module ActiveRecord
|
|
352
352
|
# Application configurable array that provides additional permitted classes
|
353
353
|
# to Psych safe_load in the YAML Coder
|
354
354
|
singleton_class.attr_accessor :yaml_column_permitted_classes
|
355
|
-
self.yaml_column_permitted_classes = []
|
355
|
+
self.yaml_column_permitted_classes = [Symbol]
|
356
356
|
|
357
357
|
def self.eager_load!
|
358
358
|
super
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.
|
4
|
+
version: 7.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 7.0.
|
19
|
+
version: 7.0.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 7.0.
|
26
|
+
version: 7.0.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 7.0.
|
33
|
+
version: 7.0.4
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 7.0.
|
40
|
+
version: 7.0.4
|
41
41
|
description: Databases on Rails. Build a persistent domain model by mapping database
|
42
42
|
tables to Ruby classes. Strong conventions for associations, validations, aggregations,
|
43
43
|
migrations, and testing come baked-in.
|
@@ -434,10 +434,10 @@ licenses:
|
|
434
434
|
- MIT
|
435
435
|
metadata:
|
436
436
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
437
|
-
changelog_uri: https://github.com/rails/rails/blob/v7.0.
|
438
|
-
documentation_uri: https://api.rubyonrails.org/v7.0.
|
437
|
+
changelog_uri: https://github.com/rails/rails/blob/v7.0.4/activerecord/CHANGELOG.md
|
438
|
+
documentation_uri: https://api.rubyonrails.org/v7.0.4/
|
439
439
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
440
|
-
source_code_uri: https://github.com/rails/rails/tree/v7.0.
|
440
|
+
source_code_uri: https://github.com/rails/rails/tree/v7.0.4/activerecord
|
441
441
|
rubygems_mfa_required: 'true'
|
442
442
|
post_install_message:
|
443
443
|
rdoc_options:
|