activerecord 7.0.6 → 7.0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +149 -0
- data/lib/active_record/associations/collection_association.rb +1 -1
- data/lib/active_record/associations/collection_proxy.rb +5 -0
- data/lib/active_record/associations/has_one_association.rb +0 -4
- data/lib/active_record/associations/singular_association.rb +5 -7
- data/lib/active_record/autosave_association.rb +5 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +0 -17
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +8 -6
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +5 -2
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -4
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/migration/compatibility.rb +12 -54
- data/lib/active_record/migration.rb +52 -3
- data/lib/active_record/persistence.rb +3 -1
- data/lib/active_record/railties/controller_runtime.rb +3 -4
- data/lib/active_record/relation/predicate_builder.rb +1 -2
- data/lib/active_record/relation/query_attribute.rb +23 -0
- data/lib/active_record/relation/query_methods.rb +26 -7
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/transactions.rb +3 -3
- data/lib/active_record/type/serialized.rb +4 -0
- data/lib/arel/nodes/and.rb +4 -0
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e000d217346c1019c2f482509ab635db50acfd196f69616c86fff4146e25a555
|
4
|
+
data.tar.gz: f8c7e6d69f291a96633a58d71862cee5f7f032b58475909ee446ebad1ac40963
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da9bec970adfbb45cf2cc7e63726775d33bf49ee63b852414db9a777800faf95259b1589fb7512e0401be63e4e653caf65df37af64cec72636184a6394134eb5
|
7
|
+
data.tar.gz: e99c01e13ce496d927e6c28211f3780e97c5706bc735bb1371356c55ba9c695a7509b1613d45c127a2fbabdc96cf966168ba6f7155b7679f37566cf852cc74ca
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,148 @@
|
|
1
|
+
## Rails 7.0.8.4 (June 04, 2024) ##
|
2
|
+
|
3
|
+
* No changes.
|
4
|
+
|
5
|
+
|
6
|
+
## Rails 7.0.8.3 (May 17, 2024) ##
|
7
|
+
|
8
|
+
* No changes.
|
9
|
+
|
10
|
+
|
11
|
+
## Rails 7.0.8.2 (May 16, 2024) ##
|
12
|
+
|
13
|
+
* No changes.
|
14
|
+
|
15
|
+
|
16
|
+
## Rails 7.0.8.1 (February 21, 2024) ##
|
17
|
+
|
18
|
+
* No changes.
|
19
|
+
|
20
|
+
|
21
|
+
## Rails 7.0.8 (September 09, 2023) ##
|
22
|
+
|
23
|
+
* Fix `change_column` not setting `precision: 6` on `datetime` columns when
|
24
|
+
using 7.0+ Migrations and SQLite.
|
25
|
+
|
26
|
+
*Hartley McGuire*
|
27
|
+
|
28
|
+
* Fix unscope is not working in specific case
|
29
|
+
|
30
|
+
Before:
|
31
|
+
```ruby
|
32
|
+
Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts` WHERE `posts`.`id` >= 1 AND `posts`.`id` < 3"
|
33
|
+
|
34
|
+
```
|
35
|
+
|
36
|
+
After:
|
37
|
+
```ruby
|
38
|
+
Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts`"
|
39
|
+
```
|
40
|
+
|
41
|
+
Fixes #48094.
|
42
|
+
|
43
|
+
*Kazuya Hatanaka*
|
44
|
+
|
45
|
+
* Fix associations to a STI model including a `class_name` parameter
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class Product < ApplicationRecord
|
49
|
+
has_many :requests, as: :requestable, class_name: "ProductRequest", dependent: :destroy
|
50
|
+
end
|
51
|
+
|
52
|
+
# STI tables
|
53
|
+
class Request < ApplicationRecord
|
54
|
+
belongs_to :requestable, polymorphic: true
|
55
|
+
|
56
|
+
validate :request_type, presence: true
|
57
|
+
end
|
58
|
+
|
59
|
+
class ProductRequest < Request
|
60
|
+
belongs_to :user
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
Accessing such association would lead to:
|
65
|
+
|
66
|
+
```
|
67
|
+
table_metadata.rb:22:in `has_column?': undefined method `key?' for nil:NilClass (NoMethodError)
|
68
|
+
```
|
69
|
+
|
70
|
+
*Romain Filinto*
|
71
|
+
|
72
|
+
* Fix `change_table` setting datetime precision for 6.1 Migrations
|
73
|
+
|
74
|
+
*Hartley McGuire*
|
75
|
+
|
76
|
+
* Fix change_column setting datetime precision for 6.1 Migrations
|
77
|
+
|
78
|
+
*Hartley McGuire*
|
79
|
+
|
80
|
+
## Rails 7.0.7.2 (August 22, 2023) ##
|
81
|
+
|
82
|
+
* No changes.
|
83
|
+
|
84
|
+
|
85
|
+
## Rails 7.0.7.1 (August 22, 2023) ##
|
86
|
+
|
87
|
+
* No changes.
|
88
|
+
|
89
|
+
|
90
|
+
## Rails 7.0.7 (August 09, 2023) ##
|
91
|
+
|
92
|
+
* Restores functionality to the missing method when using enums and fixes.
|
93
|
+
|
94
|
+
*paulreece*
|
95
|
+
|
96
|
+
* Fix `StatementCache::Substitute` with serialized type.
|
97
|
+
|
98
|
+
*ywenc*
|
99
|
+
|
100
|
+
* Fix `:db_runtime` on notification payload when application have multiple databases.
|
101
|
+
|
102
|
+
*Eileen M. Uchitelle*
|
103
|
+
|
104
|
+
* Correctly dump check constraints for MySQL 8.0.16+.
|
105
|
+
|
106
|
+
*Steve Hill*
|
107
|
+
|
108
|
+
* Fix `ActiveRecord::QueryMethods#in_order_of` to include `nil`s, to match the
|
109
|
+
behavior of `Enumerable#in_order_of`.
|
110
|
+
|
111
|
+
For example, `Post.in_order_of(:title, [nil, "foo"])` will now include posts
|
112
|
+
with `nil` titles, the same as `Post.all.to_a.in_order_of(:title, [nil, "foo"])`.
|
113
|
+
|
114
|
+
*fatkodima*
|
115
|
+
|
116
|
+
* Revert "Fix autosave associations with validations added on `:base` of the associated objects."
|
117
|
+
|
118
|
+
This change intended to remove the :base attribute from the message,
|
119
|
+
but broke many assumptions which key these errors were stored.
|
120
|
+
|
121
|
+
*zzak*
|
122
|
+
|
123
|
+
* Fix `#previously_new_record?` to return true for destroyed records.
|
124
|
+
|
125
|
+
Before, if a record was created and then destroyed, `#previously_new_record?` would return true.
|
126
|
+
Now, any UPDATE or DELETE to a record is considered a change, and will result in `#previously_new_record?`
|
127
|
+
returning false.
|
128
|
+
|
129
|
+
*Adrianna Chang*
|
130
|
+
|
131
|
+
* Revert breaking changes to `has_one` relationship deleting the old record before the new one is validated.
|
132
|
+
|
133
|
+
*zzak*
|
134
|
+
|
135
|
+
* Fix support for Active Record instances being uses in queries.
|
136
|
+
|
137
|
+
As of `7.0.5`, query arguments were deep duped to avoid mutations impacting
|
138
|
+
the query cache, but this had the adverse effect to clearing the primary key when
|
139
|
+
the query argument contained an `ActiveRecord::Base` instance.
|
140
|
+
|
141
|
+
This broke the `noticed` gem.
|
142
|
+
|
143
|
+
*Jean Boussier*
|
144
|
+
|
145
|
+
|
1
146
|
## Rails 7.0.6 (June 29, 2023) ##
|
2
147
|
|
3
148
|
* Fix autosave associations with validations added on `:base` of the associated objects.
|
@@ -12,6 +157,10 @@
|
|
12
157
|
|
13
158
|
*fatkodima*
|
14
159
|
|
160
|
+
* Fix assignment into an `has_one` relationship deleting the old record before the new one is validated.
|
161
|
+
|
162
|
+
*Jean Boussier*
|
163
|
+
|
15
164
|
* Fix where on association with has_one/has_many polymorphic relations.
|
16
165
|
|
17
166
|
Before:
|
@@ -54,13 +54,11 @@ module ActiveRecord
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def _create_record(attributes, raise_error = false, &block)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
record
|
63
|
-
end
|
57
|
+
record = build_record(attributes, &block)
|
58
|
+
saved = record.save
|
59
|
+
set_new_record(record)
|
60
|
+
raise RecordInvalid.new(record) if !saved && raise_error
|
61
|
+
record
|
64
62
|
end
|
65
63
|
end
|
66
64
|
end
|
@@ -354,15 +354,11 @@ module ActiveRecord
|
|
354
354
|
end
|
355
355
|
|
356
356
|
def normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
end
|
363
|
-
|
364
|
-
normalized_attribute = "#{normalized_attribute}.#{attribute}" if attribute != :base
|
365
|
-
normalized_attribute
|
357
|
+
if indexed_attribute
|
358
|
+
"#{reflection.name}[#{index}].#{attribute}"
|
359
|
+
else
|
360
|
+
"#{reflection.name}.#{attribute}"
|
361
|
+
end
|
366
362
|
end
|
367
363
|
|
368
364
|
# Is used as an around_save callback to check while saving a collection
|
@@ -71,14 +71,6 @@ module ActiveRecord
|
|
71
71
|
/\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
|
72
72
|
end
|
73
73
|
|
74
|
-
def self.quoted_column_names # :nodoc:
|
75
|
-
@quoted_column_names ||= {}
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.quoted_table_names # :nodoc:
|
79
|
-
@quoted_table_names ||= {}
|
80
|
-
end
|
81
|
-
|
82
74
|
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
83
75
|
super()
|
84
76
|
|
@@ -665,15 +657,6 @@ module ActiveRecord
|
|
665
657
|
migration_context.current_version
|
666
658
|
end
|
667
659
|
|
668
|
-
def field_ordered_value(column, values) # :nodoc:
|
669
|
-
node = Arel::Nodes::Case.new(column)
|
670
|
-
values.each.with_index(1) do |value, order|
|
671
|
-
node.when(value).then(order)
|
672
|
-
end
|
673
|
-
|
674
|
-
Arel::Nodes::Ascending.new(node.else(values.length + 1))
|
675
|
-
end
|
676
|
-
|
677
660
|
class << self
|
678
661
|
private
|
679
662
|
def initialize_type_map(m)
|
@@ -138,11 +138,6 @@ module ActiveRecord
|
|
138
138
|
true
|
139
139
|
end
|
140
140
|
|
141
|
-
def field_ordered_value(column, values) # :nodoc:
|
142
|
-
field = Arel::Nodes::NamedFunction.new("FIELD", [column, values.reverse.map { |value| Arel::Nodes.build_quoted(value) }])
|
143
|
-
Arel::Nodes::Descending.new(field)
|
144
|
-
end
|
145
|
-
|
146
141
|
def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
|
147
142
|
query_value("SELECT GET_LOCK(#{quote(lock_name.to_s)}, #{timeout})") == 1
|
148
143
|
end
|
@@ -438,7 +433,8 @@ module ActiveRecord
|
|
438
433
|
name: row["name"]
|
439
434
|
}
|
440
435
|
expression = row["expression"]
|
441
|
-
expression = expression[1..-2]
|
436
|
+
expression = expression[1..-2] if expression.start_with?("(") && expression.end_with?(")")
|
437
|
+
expression = strip_whitespace_characters(expression)
|
442
438
|
CheckConstraintDefinition.new(table_name, expression, options)
|
443
439
|
end
|
444
440
|
else
|
@@ -619,6 +615,12 @@ module ActiveRecord
|
|
619
615
|
end
|
620
616
|
|
621
617
|
private
|
618
|
+
def strip_whitespace_characters(expression)
|
619
|
+
expression = expression.gsub(/\\n|\\\\/, "")
|
620
|
+
expression = expression.gsub(/\s{2,}/, " ")
|
621
|
+
expression
|
622
|
+
end
|
623
|
+
|
622
624
|
def text_type?(type)
|
623
625
|
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
|
624
626
|
end
|
@@ -6,6 +6,9 @@ module ActiveRecord
|
|
6
6
|
module ConnectionAdapters
|
7
7
|
module MySQL
|
8
8
|
module Quoting # :nodoc:
|
9
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
10
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
11
|
+
|
9
12
|
def quote_bound_value(value)
|
10
13
|
case value
|
11
14
|
when Rational
|
@@ -24,11 +27,11 @@ module ActiveRecord
|
|
24
27
|
end
|
25
28
|
|
26
29
|
def quote_column_name(name)
|
27
|
-
|
30
|
+
QUOTED_COLUMN_NAMES[name] ||= "`#{super.gsub('`', '``')}`"
|
28
31
|
end
|
29
32
|
|
30
33
|
def quote_table_name(name)
|
31
|
-
|
34
|
+
QUOTED_TABLE_NAMES[name] ||= super.gsub(".", "`.`").freeze
|
32
35
|
end
|
33
36
|
|
34
37
|
def unquoted_true
|
@@ -4,6 +4,9 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module PostgreSQL
|
6
6
|
module Quoting
|
7
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
8
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
9
|
+
|
7
10
|
class IntegerOutOf64BitRange < StandardError
|
8
11
|
def initialize(msg)
|
9
12
|
super(msg)
|
@@ -81,7 +84,7 @@ module ActiveRecord
|
|
81
84
|
# - "schema.name".table_name
|
82
85
|
# - "schema.name"."table.name"
|
83
86
|
def quote_table_name(name) # :nodoc:
|
84
|
-
|
87
|
+
QUOTED_TABLE_NAMES[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
|
85
88
|
end
|
86
89
|
|
87
90
|
# Quotes schema names for use in SQL queries.
|
@@ -95,7 +98,7 @@ module ActiveRecord
|
|
95
98
|
|
96
99
|
# Quotes column names for use in SQL queries.
|
97
100
|
def quote_column_name(name) # :nodoc:
|
98
|
-
|
101
|
+
QUOTED_COLUMN_NAMES[name] ||= PG::Connection.quote_ident(super).freeze
|
99
102
|
end
|
100
103
|
|
101
104
|
# Quote date/time values for use in SQL input.
|
@@ -4,6 +4,9 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module SQLite3
|
6
6
|
module Quoting # :nodoc:
|
7
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
8
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
9
|
+
|
7
10
|
def quote_string(s)
|
8
11
|
@connection.class.quote(s)
|
9
12
|
end
|
@@ -13,11 +16,11 @@ module ActiveRecord
|
|
13
16
|
end
|
14
17
|
|
15
18
|
def quote_table_name(name)
|
16
|
-
|
19
|
+
QUOTED_TABLE_NAMES[name] ||= super.gsub(".", "\".\"").freeze
|
17
20
|
end
|
18
21
|
|
19
22
|
def quote_column_name(name)
|
20
|
-
|
23
|
+
QUOTED_COLUMN_NAMES[name] ||= %Q("#{super.gsub('"', '""')}")
|
21
24
|
end
|
22
25
|
|
23
26
|
def quoted_time(value)
|
@@ -4,6 +4,12 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module SQLite3
|
6
6
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
7
|
+
def change_column(column_name, type, **options)
|
8
|
+
name = column_name.to_s
|
9
|
+
@columns_hash[name] = nil
|
10
|
+
column(name, type, **options)
|
11
|
+
end
|
12
|
+
|
7
13
|
def references(*args, **options)
|
8
14
|
super(*args, type: :integer, **options)
|
9
15
|
end
|
@@ -84,11 +84,11 @@ module ActiveRecord
|
|
84
84
|
table_sql = query_value(<<-SQL, "SCHEMA")
|
85
85
|
SELECT sql
|
86
86
|
FROM sqlite_master
|
87
|
-
WHERE name = #{
|
87
|
+
WHERE name = #{quote(table_name)} AND type = 'table'
|
88
88
|
UNION ALL
|
89
89
|
SELECT sql
|
90
90
|
FROM sqlite_temp_master
|
91
|
-
WHERE name = #{
|
91
|
+
WHERE name = #{quote(table_name)} AND type = 'table'
|
92
92
|
SQL
|
93
93
|
|
94
94
|
table_sql.to_s.scan(/CONSTRAINT\s+(?<name>\w+)\s+CHECK\s+\((?<expression>(:?[^()]|\(\g<expression>\))+)\)/i).map do |name, expression|
|
@@ -287,10 +287,7 @@ module ActiveRecord
|
|
287
287
|
|
288
288
|
def change_column(table_name, column_name, type, **options) # :nodoc:
|
289
289
|
alter_table(table_name) do |definition|
|
290
|
-
definition
|
291
|
-
self.type = aliased_types(type.to_s, type)
|
292
|
-
self.options.merge!(options)
|
293
|
-
end
|
290
|
+
definition.change_column(column_name, type, **options)
|
294
291
|
end
|
295
292
|
end
|
296
293
|
|
@@ -56,12 +56,13 @@ module ActiveRecord
|
|
56
56
|
super
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
60
|
-
if
|
61
|
-
|
62
|
-
else
|
63
|
-
super
|
59
|
+
def change_column(table_name, column_name, type, **options)
|
60
|
+
if type == :datetime
|
61
|
+
options[:precision] ||= nil
|
64
62
|
end
|
63
|
+
|
64
|
+
type = PostgreSQLCompat.compatible_timestamp_type(type, connection)
|
65
|
+
super
|
65
66
|
end
|
66
67
|
|
67
68
|
module TableDefinition
|
@@ -70,6 +71,11 @@ module ActiveRecord
|
|
70
71
|
super
|
71
72
|
end
|
72
73
|
|
74
|
+
def change(name, type, index: nil, **options)
|
75
|
+
options[:precision] ||= nil
|
76
|
+
super
|
77
|
+
end
|
78
|
+
|
73
79
|
def column(name, type, index: nil, **options)
|
74
80
|
options[:precision] ||= nil
|
75
81
|
super
|
@@ -81,7 +87,7 @@ module ActiveRecord
|
|
81
87
|
class << t
|
82
88
|
prepend TableDefinition
|
83
89
|
end
|
84
|
-
|
90
|
+
super
|
85
91
|
end
|
86
92
|
end
|
87
93
|
|
@@ -105,30 +111,6 @@ module ActiveRecord
|
|
105
111
|
end
|
106
112
|
end
|
107
113
|
|
108
|
-
def create_table(table_name, **options)
|
109
|
-
if block_given?
|
110
|
-
super { |t| yield compatible_table_definition(t) }
|
111
|
-
else
|
112
|
-
super
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def change_table(table_name, **options)
|
117
|
-
if block_given?
|
118
|
-
super { |t| yield compatible_table_definition(t) }
|
119
|
-
else
|
120
|
-
super
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def create_join_table(table_1, table_2, **options)
|
125
|
-
if block_given?
|
126
|
-
super { |t| yield compatible_table_definition(t) }
|
127
|
-
else
|
128
|
-
super
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
114
|
def add_reference(table_name, ref_name, **options)
|
133
115
|
if connection.adapter_name == "SQLite"
|
134
116
|
options[:type] = :integer
|
@@ -182,30 +164,6 @@ module ActiveRecord
|
|
182
164
|
end
|
183
165
|
end
|
184
166
|
|
185
|
-
def create_table(table_name, **options)
|
186
|
-
if block_given?
|
187
|
-
super { |t| yield compatible_table_definition(t) }
|
188
|
-
else
|
189
|
-
super
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def change_table(table_name, **options)
|
194
|
-
if block_given?
|
195
|
-
super { |t| yield compatible_table_definition(t) }
|
196
|
-
else
|
197
|
-
super
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def create_join_table(table_1, table_2, **options)
|
202
|
-
if block_given?
|
203
|
-
super { |t| yield compatible_table_definition(t) }
|
204
|
-
else
|
205
|
-
super
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
167
|
def add_timestamps(table_name, **options)
|
210
168
|
options[:precision] ||= nil
|
211
169
|
super
|
@@ -551,6 +551,41 @@ module ActiveRecord
|
|
551
551
|
|
552
552
|
# This must be defined before the inherited hook, below
|
553
553
|
class Current < Migration # :nodoc:
|
554
|
+
def create_table(table_name, **options)
|
555
|
+
if block_given?
|
556
|
+
super { |t| yield compatible_table_definition(t) }
|
557
|
+
else
|
558
|
+
super
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
def change_table(table_name, **options)
|
563
|
+
if block_given?
|
564
|
+
super { |t| yield compatible_table_definition(t) }
|
565
|
+
else
|
566
|
+
super
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
def create_join_table(table_1, table_2, **options)
|
571
|
+
if block_given?
|
572
|
+
super { |t| yield compatible_table_definition(t) }
|
573
|
+
else
|
574
|
+
super
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
def drop_table(table_name, **options)
|
579
|
+
if block_given?
|
580
|
+
super { |t| yield compatible_table_definition(t) }
|
581
|
+
else
|
582
|
+
super
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
586
|
+
def compatible_table_definition(t)
|
587
|
+
t
|
588
|
+
end
|
554
589
|
end
|
555
590
|
|
556
591
|
def self.inherited(subclass) # :nodoc:
|
@@ -916,9 +951,7 @@ module ActiveRecord
|
|
916
951
|
end
|
917
952
|
|
918
953
|
def method_missing(method, *arguments, &block)
|
919
|
-
|
920
|
-
|
921
|
-
say_with_time "#{method}(#{arg_list})" do
|
954
|
+
say_with_time "#{method}(#{format_arguments(arguments)})" do
|
922
955
|
unless connection.respond_to? :revert
|
923
956
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
924
957
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
@@ -1026,6 +1059,22 @@ module ActiveRecord
|
|
1026
1059
|
end
|
1027
1060
|
end
|
1028
1061
|
|
1062
|
+
def format_arguments(arguments)
|
1063
|
+
arg_list = arguments[0...-1].map(&:inspect)
|
1064
|
+
last_arg = arguments.last
|
1065
|
+
if last_arg.is_a?(Hash)
|
1066
|
+
last_arg = last_arg.reject { |k, _v| internal_option?(k) }
|
1067
|
+
arg_list << last_arg.inspect unless last_arg.empty?
|
1068
|
+
else
|
1069
|
+
arg_list << last_arg.inspect
|
1070
|
+
end
|
1071
|
+
arg_list.join(", ")
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
def internal_option?(option_name)
|
1075
|
+
option_name.start_with?("_")
|
1076
|
+
end
|
1077
|
+
|
1029
1078
|
def command_recorder
|
1030
1079
|
CommandRecorder.new(connection)
|
1031
1080
|
end
|
@@ -564,7 +564,7 @@ module ActiveRecord
|
|
564
564
|
end
|
565
565
|
|
566
566
|
# Returns true if this object was just created -- that is, prior to the last
|
567
|
-
#
|
567
|
+
# update or delete, the object didn't exist in the database and new_record? would have
|
568
568
|
# returned true.
|
569
569
|
def previously_new_record?
|
570
570
|
@previously_new_record
|
@@ -663,6 +663,7 @@ module ActiveRecord
|
|
663
663
|
def delete
|
664
664
|
_delete_row if persisted?
|
665
665
|
@destroyed = true
|
666
|
+
@previously_new_record = false
|
666
667
|
freeze
|
667
668
|
end
|
668
669
|
|
@@ -682,6 +683,7 @@ module ActiveRecord
|
|
682
683
|
true
|
683
684
|
end
|
684
685
|
@destroyed = true
|
686
|
+
@previously_new_record = false
|
685
687
|
freeze
|
686
688
|
end
|
687
689
|
|
@@ -28,7 +28,7 @@ module ActiveRecord
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def cleanup_view_runtime
|
31
|
-
if logger && logger.info?
|
31
|
+
if logger && logger.info?
|
32
32
|
db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
|
33
33
|
self.db_runtime = (db_runtime || 0) + db_rt_before_render
|
34
34
|
runtime = super
|
@@ -42,9 +42,8 @@ module ActiveRecord
|
|
42
42
|
|
43
43
|
def append_info_to_payload(payload)
|
44
44
|
super
|
45
|
-
|
46
|
-
|
47
|
-
end
|
45
|
+
|
46
|
+
payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
|
48
47
|
end
|
49
48
|
end
|
50
49
|
end
|
@@ -65,8 +65,7 @@ module ActiveRecord
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def build_bind_attribute(column_name, value)
|
68
|
-
|
69
|
-
Relation::QueryAttribute.new(column_name, type.immutable_value(value), type)
|
68
|
+
Relation::QueryAttribute.new(column_name, value, table.type(column_name))
|
70
69
|
end
|
71
70
|
|
72
71
|
def resolve_arel_attribute(table_name, column_name, &block)
|
@@ -5,6 +5,20 @@ require "active_model/attribute"
|
|
5
5
|
module ActiveRecord
|
6
6
|
class Relation
|
7
7
|
class QueryAttribute < ActiveModel::Attribute # :nodoc:
|
8
|
+
def initialize(...)
|
9
|
+
super
|
10
|
+
|
11
|
+
# The query attribute value may be mutated before we actually "compile" the query.
|
12
|
+
# To avoid that if the type uses a serializer we eagerly compute the value for database
|
13
|
+
if value_before_type_cast.is_a?(StatementCache::Substitute)
|
14
|
+
# we don't need to serialize StatementCache::Substitute
|
15
|
+
elsif @type.serialized?
|
16
|
+
value_for_database
|
17
|
+
elsif @type.mutable? # If the type is simply mutable, we deep_dup it.
|
18
|
+
@value_before_type_cast = @value_before_type_cast.deep_dup
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
8
22
|
def type_cast(value)
|
9
23
|
value
|
10
24
|
end
|
@@ -35,6 +49,15 @@ module ActiveRecord
|
|
35
49
|
@_unboundable
|
36
50
|
end
|
37
51
|
|
52
|
+
def ==(other)
|
53
|
+
super && value_for_database == other.value_for_database
|
54
|
+
end
|
55
|
+
alias eql? ==
|
56
|
+
|
57
|
+
def hash
|
58
|
+
[self.class, name, value_for_database, type].hash
|
59
|
+
end
|
60
|
+
|
38
61
|
private
|
39
62
|
def infinity?(value)
|
40
63
|
value.respond_to?(:infinite?) && value.infinite?
|
@@ -77,7 +77,7 @@ module ActiveRecord
|
|
77
77
|
associations.each do |association|
|
78
78
|
reflection = scope_association_reflection(association)
|
79
79
|
@scope.joins!(association)
|
80
|
-
if
|
80
|
+
if reflection.options[:class_name]
|
81
81
|
self.not(association => { reflection.association_primary_key => nil })
|
82
82
|
else
|
83
83
|
self.not(reflection.table_name => { reflection.association_primary_key => nil })
|
@@ -109,7 +109,7 @@ module ActiveRecord
|
|
109
109
|
associations.each do |association|
|
110
110
|
reflection = scope_association_reflection(association)
|
111
111
|
@scope.left_outer_joins!(association)
|
112
|
-
if
|
112
|
+
if reflection.options[:class_name]
|
113
113
|
@scope.where!(association => { reflection.association_primary_key => nil })
|
114
114
|
else
|
115
115
|
@scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
|
@@ -444,13 +444,16 @@ module ActiveRecord
|
|
444
444
|
self
|
445
445
|
end
|
446
446
|
|
447
|
-
# Allows to specify an order by a specific set of values.
|
448
|
-
# adapter this will either use a CASE statement or a built-in function.
|
447
|
+
# Allows to specify an order by a specific set of values.
|
449
448
|
#
|
450
449
|
# User.in_order_of(:id, [1, 5, 3])
|
451
450
|
# # SELECT "users".* FROM "users"
|
452
|
-
# # ORDER BY FIELD("users"."id", 1, 5, 3)
|
453
451
|
# # WHERE "users"."id" IN (1, 5, 3)
|
452
|
+
# # ORDER BY CASE
|
453
|
+
# # WHEN "users"."id" = 1 THEN 1
|
454
|
+
# # WHEN "users"."id" = 5 THEN 2
|
455
|
+
# # WHEN "users"."id" = 3 THEN 3
|
456
|
+
# # END ASC
|
454
457
|
#
|
455
458
|
def in_order_of(column, values)
|
456
459
|
klass.disallow_raw_sql!([column], permit: connection.column_name_with_order_matcher)
|
@@ -462,9 +465,16 @@ module ActiveRecord
|
|
462
465
|
values = values.map { |value| type_caster.type_cast_for_database(column, value) }
|
463
466
|
arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
|
464
467
|
|
468
|
+
where_clause =
|
469
|
+
if values.include?(nil)
|
470
|
+
arel_column.in(values.compact).or(arel_column.eq(nil))
|
471
|
+
else
|
472
|
+
arel_column.in(values)
|
473
|
+
end
|
474
|
+
|
465
475
|
spawn
|
466
|
-
.order!(
|
467
|
-
.where!(
|
476
|
+
.order!(build_case_for_value_position(arel_column, values))
|
477
|
+
.where!(where_clause)
|
468
478
|
end
|
469
479
|
|
470
480
|
# Replaces any existing order defined on the relation with the specified order.
|
@@ -1669,6 +1679,15 @@ module ActiveRecord
|
|
1669
1679
|
end
|
1670
1680
|
end
|
1671
1681
|
|
1682
|
+
def build_case_for_value_position(column, values)
|
1683
|
+
node = Arel::Nodes::Case.new
|
1684
|
+
values.each.with_index(1) do |value, order|
|
1685
|
+
node.when(column.eq(value)).then(order)
|
1686
|
+
end
|
1687
|
+
|
1688
|
+
Arel::Nodes::Ascending.new(node)
|
1689
|
+
end
|
1690
|
+
|
1672
1691
|
def resolve_arel_attributes(attrs)
|
1673
1692
|
attrs.flat_map do |attr|
|
1674
1693
|
case attr
|
@@ -336,9 +336,9 @@ module ActiveRecord
|
|
336
336
|
@_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
|
337
337
|
end
|
338
338
|
|
339
|
-
# Executes
|
340
|
-
# status flag. If the status is true the transaction is committed,
|
341
|
-
# a ROLLBACK is issued. In any case the status flag is returned.
|
339
|
+
# Executes a block within a transaction and captures its return value as a
|
340
|
+
# status flag. If the status is true, the transaction is committed,
|
341
|
+
# otherwise a ROLLBACK is issued. In any case, the status flag is returned.
|
342
342
|
#
|
343
343
|
# This method is available within the context of an ActiveRecord::Base
|
344
344
|
# instance.
|
data/lib/arel/nodes/and.rb
CHANGED
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.8.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-06-04 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.8.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.8.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.8.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.8.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,12 +434,12 @@ 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.8.4/activerecord/CHANGELOG.md
|
438
|
+
documentation_uri: https://api.rubyonrails.org/v7.0.8.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.8.4/activerecord
|
441
441
|
rubygems_mfa_required: 'true'
|
442
|
-
post_install_message:
|
442
|
+
post_install_message:
|
443
443
|
rdoc_options:
|
444
444
|
- "--main"
|
445
445
|
- README.rdoc
|
@@ -456,8 +456,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
456
456
|
- !ruby/object:Gem::Version
|
457
457
|
version: '0'
|
458
458
|
requirements: []
|
459
|
-
rubygems_version: 3.
|
460
|
-
signing_key:
|
459
|
+
rubygems_version: 3.3.27
|
460
|
+
signing_key:
|
461
461
|
specification_version: 4
|
462
462
|
summary: Object-relational mapper framework (part of Rails).
|
463
463
|
test_files: []
|