activerecord 7.0.4.3 → 7.0.6
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 +159 -7
- data/README.rdoc +2 -2
- data/lib/active_record/associations/has_one_association.rb +4 -0
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/singular_association.rb +7 -5
- data/lib/active_record/associations.rb +15 -6
- data/lib/active_record/attribute_methods/read.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -4
- data/lib/active_record/attribute_methods.rb +5 -7
- data/lib/active_record/autosave_association.rb +9 -5
- data/lib/active_record/callbacks.rb +12 -14
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +20 -16
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -1
- data/lib/active_record/connection_adapters/abstract_adapter.rb +4 -0
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +7 -3
- data/lib/active_record/connection_adapters/mysql/quoting.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -5
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
- data/lib/active_record/disable_joins_association_relation.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/locking/optimistic.rb +32 -18
- data/lib/active_record/middleware/database_selector.rb +3 -3
- data/lib/active_record/migration/command_recorder.rb +1 -2
- data/lib/active_record/migration/compatibility.rb +7 -0
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/persistence.rb +4 -4
- data/lib/active_record/reflection.rb +8 -0
- data/lib/active_record/relation/calculations.rb +50 -23
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -1
- data/lib/active_record/relation/predicate_builder.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +11 -3
- data/lib/active_record/result.rb +6 -4
- data/lib/active_record/schema_dumper.rb +4 -0
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/table_metadata.rb +5 -1
- data/lib/active_record/type/serialized.rb +4 -4
- data/lib/arel/filter_predications.rb +1 -1
- data/lib/arel/nodes/filter.rb +1 -1
- metadata +13 -13
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
attr_reader :schema, :identifier
|
13
13
|
|
14
14
|
def initialize(schema, identifier)
|
15
|
-
@schema, @identifier =
|
15
|
+
@schema, @identifier = Utils.unquote_identifier(schema), Utils.unquote_identifier(identifier)
|
16
16
|
end
|
17
17
|
|
18
18
|
def to_s
|
@@ -40,15 +40,6 @@ module ActiveRecord
|
|
40
40
|
def parts
|
41
41
|
@parts ||= [@schema, @identifier].compact
|
42
42
|
end
|
43
|
-
|
44
|
-
private
|
45
|
-
def unquote(part)
|
46
|
-
if part && part.start_with?('"')
|
47
|
-
part[1..-2]
|
48
|
-
else
|
49
|
-
part
|
50
|
-
end
|
51
|
-
end
|
52
43
|
end
|
53
44
|
|
54
45
|
module Utils # :nodoc:
|
@@ -74,6 +65,14 @@ module ActiveRecord
|
|
74
65
|
end
|
75
66
|
PostgreSQL::Name.new(schema, table)
|
76
67
|
end
|
68
|
+
|
69
|
+
def unquote_identifier(identifier)
|
70
|
+
if identifier && identifier.start_with?('"')
|
71
|
+
identifier[1..-2]
|
72
|
+
else
|
73
|
+
identifier
|
74
|
+
end
|
75
|
+
end
|
77
76
|
end
|
78
77
|
end
|
79
78
|
end
|
@@ -977,7 +977,7 @@ module ActiveRecord
|
|
977
977
|
PG::TextDecoder::TimestampUtc :
|
978
978
|
PG::TextDecoder::TimestampWithoutTimeZone
|
979
979
|
|
980
|
-
@timestamp_decoder = decoder_class.new(
|
980
|
+
@timestamp_decoder = decoder_class.new(**@timestamp_decoder.to_h)
|
981
981
|
@connection.type_map_for_results.add_coder(@timestamp_decoder)
|
982
982
|
|
983
983
|
@default_timezone = ActiveRecord.default_timezone
|
@@ -480,6 +480,7 @@ module ActiveRecord
|
|
480
480
|
if column.has_default?
|
481
481
|
type = lookup_cast_type_from_column(column)
|
482
482
|
default = type.deserialize(column.default)
|
483
|
+
default = -> { column.default_function } if default.nil?
|
483
484
|
end
|
484
485
|
|
485
486
|
@definition.column(column_name, column.type,
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
21
21
|
# On the other hand, we want to monitor the performance of our real database
|
22
22
|
# queries, not the performance of the access to the query cache.
|
23
23
|
IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN)
|
24
|
-
EXPLAINED_SQLS = /\A\s*(with|select|update|delete|insert)\b/i
|
24
|
+
EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i
|
25
25
|
def ignore_payload?(payload)
|
26
26
|
payload[:exception] ||
|
27
27
|
payload[:cached] ||
|
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Locking
|
5
|
-
# == What is Optimistic Locking
|
5
|
+
# == What is \Optimistic \Locking
|
6
6
|
#
|
7
7
|
# Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of
|
8
8
|
# conflicts with the data. It does this by checking whether another process has made changes to a record since
|
9
|
-
# it was opened, an
|
9
|
+
# it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred
|
10
10
|
# and the update is ignored.
|
11
11
|
#
|
12
|
-
# Check out
|
12
|
+
# Check out +ActiveRecord::Locking::Pessimistic+ for an alternative.
|
13
13
|
#
|
14
14
|
# == Usage
|
15
15
|
#
|
@@ -69,6 +69,11 @@ module ActiveRecord
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
def initialize_dup(other) # :nodoc:
|
73
|
+
super
|
74
|
+
_clear_locking_column if locking_enabled?
|
75
|
+
end
|
76
|
+
|
72
77
|
private
|
73
78
|
def _create_record(attribute_names = self.attribute_names)
|
74
79
|
if locking_enabled?
|
@@ -91,8 +96,7 @@ module ActiveRecord
|
|
91
96
|
locking_column = self.class.locking_column
|
92
97
|
lock_attribute_was = @attributes[locking_column]
|
93
98
|
|
94
|
-
update_constraints =
|
95
|
-
update_constraints[locking_column] = _lock_value_for_database(locking_column)
|
99
|
+
update_constraints = _query_constraints_hash
|
96
100
|
|
97
101
|
attribute_names = attribute_names.dup if attribute_names.frozen?
|
98
102
|
attribute_names << locking_column
|
@@ -118,16 +122,9 @@ module ActiveRecord
|
|
118
122
|
end
|
119
123
|
|
120
124
|
def destroy_row
|
121
|
-
|
122
|
-
|
123
|
-
locking_column = self.class.locking_column
|
125
|
+
affected_rows = super
|
124
126
|
|
125
|
-
|
126
|
-
delete_constraints[locking_column] = _lock_value_for_database(locking_column)
|
127
|
-
|
128
|
-
affected_rows = self.class._delete_record(delete_constraints)
|
129
|
-
|
130
|
-
if affected_rows != 1
|
127
|
+
if locking_enabled? && affected_rows != 1
|
131
128
|
raise ActiveRecord::StaleObjectError.new(self, "destroy")
|
132
129
|
end
|
133
130
|
|
@@ -142,6 +139,18 @@ module ActiveRecord
|
|
142
139
|
end
|
143
140
|
end
|
144
141
|
|
142
|
+
def _clear_locking_column
|
143
|
+
self[self.class.locking_column] = nil
|
144
|
+
clear_attribute_change(self.class.locking_column)
|
145
|
+
end
|
146
|
+
|
147
|
+
def _query_constraints_hash
|
148
|
+
return super unless locking_enabled?
|
149
|
+
|
150
|
+
locking_column = self.class.locking_column
|
151
|
+
super.merge(locking_column => _lock_value_for_database(locking_column))
|
152
|
+
end
|
153
|
+
|
145
154
|
module ClassMethods
|
146
155
|
DEFAULT_LOCKING_COLUMN = "lock_version"
|
147
156
|
|
@@ -159,10 +168,7 @@ module ActiveRecord
|
|
159
168
|
end
|
160
169
|
|
161
170
|
# The version column used for optimistic locking. Defaults to +lock_version+.
|
162
|
-
|
163
|
-
@locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
|
164
|
-
@locking_column
|
165
|
-
end
|
171
|
+
attr_reader :locking_column
|
166
172
|
|
167
173
|
# Reset the column used for optimistic locking back to the +lock_version+ default.
|
168
174
|
def reset_locking_column
|
@@ -182,6 +188,14 @@ module ActiveRecord
|
|
182
188
|
end
|
183
189
|
super
|
184
190
|
end
|
191
|
+
|
192
|
+
private
|
193
|
+
def inherited(base)
|
194
|
+
super
|
195
|
+
base.class_eval do
|
196
|
+
@locking_column = DEFAULT_LOCKING_COLUMN
|
197
|
+
end
|
198
|
+
end
|
185
199
|
end
|
186
200
|
end
|
187
201
|
|
@@ -43,9 +43,9 @@ module ActiveRecord
|
|
43
43
|
# config.active_record.database_resolver = MyResolver
|
44
44
|
# config.active_record.database_resolver_context = MyResolver::MySession
|
45
45
|
#
|
46
|
-
# Note: If you are using
|
47
|
-
#
|
48
|
-
#
|
46
|
+
# Note: If you are using <tt>rails new my_app --minimal</tt> you will need
|
47
|
+
# to call <tt>require "active_support/core_ext/integer/time"</tt> to load
|
48
|
+
# the core extension in order to use +2.seconds+
|
49
49
|
class DatabaseSelector
|
50
50
|
def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
|
51
51
|
@app = app
|
@@ -12,7 +12,6 @@ module ActiveRecord
|
|
12
12
|
# * add_index
|
13
13
|
# * add_reference
|
14
14
|
# * add_timestamps
|
15
|
-
# * change_column
|
16
15
|
# * change_column_default (must supply a +:from+ and +:to+ option)
|
17
16
|
# * change_column_null
|
18
17
|
# * change_column_comment (must supply a +:from+ and +:to+ option)
|
@@ -24,7 +23,7 @@ module ActiveRecord
|
|
24
23
|
# * drop_table (must supply a block)
|
25
24
|
# * enable_extension
|
26
25
|
# * remove_column (must supply a type)
|
27
|
-
# * remove_columns (must
|
26
|
+
# * remove_columns (must supply a +:type+ option)
|
28
27
|
# * remove_foreign_key (must supply a second table)
|
29
28
|
# * remove_check_constraint
|
30
29
|
# * remove_index
|
@@ -1338,7 +1338,7 @@ module ActiveRecord
|
|
1338
1338
|
# Stores the current environment in the database.
|
1339
1339
|
def record_environment
|
1340
1340
|
return if down?
|
1341
|
-
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.
|
1341
|
+
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.pool.db_config.env_name
|
1342
1342
|
end
|
1343
1343
|
|
1344
1344
|
def ran?(migration)
|
@@ -813,7 +813,7 @@ module ActiveRecord
|
|
813
813
|
verify_readonly_attribute(name) || name
|
814
814
|
end
|
815
815
|
|
816
|
-
update_constraints =
|
816
|
+
update_constraints = _query_constraints_hash
|
817
817
|
attributes = attributes.each_with_object({}) do |(k, v), h|
|
818
818
|
h[k] = @attributes.write_cast_value(k, v)
|
819
819
|
clear_attribute_change(k)
|
@@ -1028,7 +1028,7 @@ module ActiveRecord
|
|
1028
1028
|
(self.class.default_scopes?(all_queries: true) || self.class.global_current_scope)
|
1029
1029
|
end
|
1030
1030
|
|
1031
|
-
def
|
1031
|
+
def _query_constraints_hash
|
1032
1032
|
{ @primary_key => id_in_database }
|
1033
1033
|
end
|
1034
1034
|
|
@@ -1041,7 +1041,7 @@ module ActiveRecord
|
|
1041
1041
|
end
|
1042
1042
|
|
1043
1043
|
def _delete_row
|
1044
|
-
self.class._delete_record(
|
1044
|
+
self.class._delete_record(_query_constraints_hash)
|
1045
1045
|
end
|
1046
1046
|
|
1047
1047
|
def _touch_row(attribute_names, time)
|
@@ -1057,7 +1057,7 @@ module ActiveRecord
|
|
1057
1057
|
def _update_row(attribute_names, attempted_action = "update")
|
1058
1058
|
self.class._update_record(
|
1059
1059
|
attributes_with_values(attribute_names),
|
1060
|
-
|
1060
|
+
_query_constraints_hash
|
1061
1061
|
)
|
1062
1062
|
end
|
1063
1063
|
|
@@ -485,6 +485,10 @@ module ActiveRecord
|
|
485
485
|
foreign_key
|
486
486
|
end
|
487
487
|
|
488
|
+
def join_primary_type
|
489
|
+
type
|
490
|
+
end
|
491
|
+
|
488
492
|
def join_foreign_key
|
489
493
|
active_record_primary_key
|
490
494
|
end
|
@@ -588,6 +592,10 @@ module ActiveRecord
|
|
588
592
|
options[:polymorphic]
|
589
593
|
end
|
590
594
|
|
595
|
+
def polymorphic_name
|
596
|
+
active_record.polymorphic_name
|
597
|
+
end
|
598
|
+
|
591
599
|
def add_as_source(seed)
|
592
600
|
seed
|
593
601
|
end
|
@@ -4,6 +4,47 @@ require "active_support/core_ext/enumerable"
|
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
module Calculations
|
7
|
+
class ColumnAliasTracker # :nodoc:
|
8
|
+
def initialize(connection)
|
9
|
+
@connection = connection
|
10
|
+
@aliases = Hash.new(0)
|
11
|
+
end
|
12
|
+
|
13
|
+
def alias_for(field)
|
14
|
+
aliased_name = column_alias_for(field)
|
15
|
+
|
16
|
+
if @aliases[aliased_name] == 0
|
17
|
+
@aliases[aliased_name] = 1
|
18
|
+
aliased_name
|
19
|
+
else
|
20
|
+
# Update the count
|
21
|
+
count = @aliases[aliased_name] += 1
|
22
|
+
"#{truncate(aliased_name)}_#{count}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
# Converts the given field to the value that the database adapter returns as
|
28
|
+
# a usable column name:
|
29
|
+
#
|
30
|
+
# column_alias_for("users.id") # => "users_id"
|
31
|
+
# column_alias_for("sum(id)") # => "sum_id"
|
32
|
+
# column_alias_for("count(distinct users.id)") # => "count_distinct_users_id"
|
33
|
+
# column_alias_for("count(*)") # => "count_all"
|
34
|
+
def column_alias_for(field)
|
35
|
+
column_alias = +field
|
36
|
+
column_alias.gsub!(/\*/, "all")
|
37
|
+
column_alias.gsub!(/\W+/, " ")
|
38
|
+
column_alias.strip!
|
39
|
+
column_alias.gsub!(/ +/, "_")
|
40
|
+
@connection.table_alias_for(column_alias)
|
41
|
+
end
|
42
|
+
|
43
|
+
def truncate(name)
|
44
|
+
name.slice(0, @connection.table_alias_length - 2)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
7
48
|
# Count the records.
|
8
49
|
#
|
9
50
|
# Person.count
|
@@ -86,7 +127,7 @@ module ActiveRecord
|
|
86
127
|
def sum(identity_or_column = nil, &block)
|
87
128
|
if block_given?
|
88
129
|
values = map(&block)
|
89
|
-
if identity_or_column.nil? && (values.first.is_a?(Numeric) || values.first(1) == [])
|
130
|
+
if identity_or_column.nil? && (values.first.is_a?(Numeric) || values.first(1) == [] || values.first.respond_to?(:coerce))
|
90
131
|
identity_or_column = 0
|
91
132
|
end
|
92
133
|
|
@@ -336,14 +377,16 @@ module ActiveRecord
|
|
336
377
|
end
|
337
378
|
group_fields = arel_columns(group_fields)
|
338
379
|
|
380
|
+
column_alias_tracker = ColumnAliasTracker.new(connection)
|
381
|
+
|
339
382
|
group_aliases = group_fields.map { |field|
|
340
383
|
field = connection.visitor.compile(field) if Arel.arel_node?(field)
|
341
|
-
|
384
|
+
column_alias_tracker.alias_for(field.to_s.downcase)
|
342
385
|
}
|
343
386
|
group_columns = group_aliases.zip(group_fields)
|
344
387
|
|
345
388
|
column = aggregate_column(column_name)
|
346
|
-
column_alias =
|
389
|
+
column_alias = column_alias_tracker.alias_for("#{operation} #{column_name.to_s.downcase}")
|
347
390
|
select_value = operation_over_aggregate_column(column, operation, distinct)
|
348
391
|
select_value.as(connection.quote_column_name(column_alias))
|
349
392
|
|
@@ -372,9 +415,10 @@ module ActiveRecord
|
|
372
415
|
end
|
373
416
|
|
374
417
|
key_types = group_columns.each_with_object({}) do |(aliaz, col_name), types|
|
375
|
-
types[aliaz] =
|
376
|
-
|
377
|
-
|
418
|
+
types[aliaz] = col_name.try(:type_caster) ||
|
419
|
+
type_for(col_name) do
|
420
|
+
calculated_data.column_types.fetch(aliaz, Type.default_value)
|
421
|
+
end
|
378
422
|
end
|
379
423
|
|
380
424
|
hash_rows = calculated_data.cast_values(key_types).map! do |row|
|
@@ -398,23 +442,6 @@ module ActiveRecord
|
|
398
442
|
end
|
399
443
|
end
|
400
444
|
|
401
|
-
# Converts the given field to the value that the database adapter returns as
|
402
|
-
# a usable column name:
|
403
|
-
#
|
404
|
-
# column_alias_for("users.id") # => "users_id"
|
405
|
-
# column_alias_for("sum(id)") # => "sum_id"
|
406
|
-
# column_alias_for("count(distinct users.id)") # => "count_distinct_users_id"
|
407
|
-
# column_alias_for("count(*)") # => "count_all"
|
408
|
-
def column_alias_for(field)
|
409
|
-
column_alias = +field
|
410
|
-
column_alias.gsub!(/\*/, "all")
|
411
|
-
column_alias.gsub!(/\W+/, " ")
|
412
|
-
column_alias.strip!
|
413
|
-
column_alias.gsub!(/ +/, "_")
|
414
|
-
|
415
|
-
connection.table_alias_for(column_alias)
|
416
|
-
end
|
417
|
-
|
418
445
|
def type_for(field, &block)
|
419
446
|
field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split(".").last
|
420
447
|
@klass.type_for_attribute(field_name, &block)
|
@@ -18,7 +18,10 @@ module ActiveRecord
|
|
18
18
|
def ids
|
19
19
|
case value
|
20
20
|
when Relation
|
21
|
-
|
21
|
+
relation = value
|
22
|
+
relation = relation.select(primary_key) if select_clause?
|
23
|
+
relation = relation.where(primary_type => polymorphic_name) if polymorphic_clause?
|
24
|
+
relation
|
22
25
|
when Array
|
23
26
|
value.map { |v| convert_to_id(v) }
|
24
27
|
else
|
@@ -30,6 +33,22 @@ module ActiveRecord
|
|
30
33
|
associated_table.join_primary_key
|
31
34
|
end
|
32
35
|
|
36
|
+
def primary_type
|
37
|
+
associated_table.join_primary_type
|
38
|
+
end
|
39
|
+
|
40
|
+
def polymorphic_name
|
41
|
+
associated_table.polymorphic_name_association
|
42
|
+
end
|
43
|
+
|
44
|
+
def select_clause?
|
45
|
+
value.select_values.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def polymorphic_clause?
|
49
|
+
primary_type && !value.where_values_hash.has_key?(primary_type)
|
50
|
+
end
|
51
|
+
|
33
52
|
def convert_to_id(value)
|
34
53
|
if value.respond_to?(primary_key)
|
35
54
|
value.public_send(primary_key)
|
@@ -65,7 +65,8 @@ module ActiveRecord
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def build_bind_attribute(column_name, value)
|
68
|
-
|
68
|
+
type = table.type(column_name)
|
69
|
+
Relation::QueryAttribute.new(column_name, type.immutable_value(value), type)
|
69
70
|
end
|
70
71
|
|
71
72
|
def resolve_arel_attribute(table_name, column_name, &block)
|
@@ -77,7 +77,11 @@ module ActiveRecord
|
|
77
77
|
associations.each do |association|
|
78
78
|
reflection = scope_association_reflection(association)
|
79
79
|
@scope.joins!(association)
|
80
|
-
|
80
|
+
if @scope.table_name == reflection.table_name
|
81
|
+
self.not(association => { reflection.association_primary_key => nil })
|
82
|
+
else
|
83
|
+
self.not(reflection.table_name => { reflection.association_primary_key => nil })
|
84
|
+
end
|
81
85
|
end
|
82
86
|
|
83
87
|
@scope
|
@@ -105,7 +109,11 @@ module ActiveRecord
|
|
105
109
|
associations.each do |association|
|
106
110
|
reflection = scope_association_reflection(association)
|
107
111
|
@scope.left_outer_joins!(association)
|
108
|
-
@scope.
|
112
|
+
if @scope.table_name == reflection.table_name
|
113
|
+
@scope.where!(association => { reflection.association_primary_key => nil })
|
114
|
+
else
|
115
|
+
@scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
|
116
|
+
end
|
109
117
|
end
|
110
118
|
|
111
119
|
@scope
|
@@ -289,7 +297,7 @@ module ActiveRecord
|
|
289
297
|
# You can also use one or more strings, which will be used unchanged as SELECT fields.
|
290
298
|
#
|
291
299
|
# Model.select('field AS field_one', 'other_field AS field_two')
|
292
|
-
# # => [#<Model id: nil,
|
300
|
+
# # => [#<Model id: nil, field_one: "value", field_two: "value">]
|
293
301
|
#
|
294
302
|
# If an alias was specified, it will be accessible from the resulting objects:
|
295
303
|
#
|
data/lib/active_record/result.rb
CHANGED
@@ -108,7 +108,7 @@ module ActiveRecord
|
|
108
108
|
type = if type_overrides.is_a?(Array)
|
109
109
|
type_overrides.first
|
110
110
|
else
|
111
|
-
column_type(columns.first, type_overrides)
|
111
|
+
column_type(columns.first, 0, type_overrides)
|
112
112
|
end
|
113
113
|
|
114
114
|
rows.map do |(value)|
|
@@ -118,7 +118,7 @@ module ActiveRecord
|
|
118
118
|
types = if type_overrides.is_a?(Array)
|
119
119
|
type_overrides
|
120
120
|
else
|
121
|
-
columns.map { |name| column_type(name, type_overrides) }
|
121
|
+
columns.map.with_index { |name, i| column_type(name, i, type_overrides) }
|
122
122
|
end
|
123
123
|
|
124
124
|
rows.map do |values|
|
@@ -135,9 +135,11 @@ module ActiveRecord
|
|
135
135
|
end
|
136
136
|
|
137
137
|
private
|
138
|
-
def column_type(name, type_overrides
|
138
|
+
def column_type(name, index, type_overrides)
|
139
139
|
type_overrides.fetch(name) do
|
140
|
-
column_types.fetch(
|
140
|
+
column_types.fetch(index) do
|
141
|
+
column_types.fetch(name, Type.default_value)
|
142
|
+
end
|
141
143
|
end
|
142
144
|
end
|
143
145
|
|
@@ -292,6 +292,10 @@ module ActiveRecord
|
|
292
292
|
end
|
293
293
|
|
294
294
|
def remove_prefix_and_suffix(table)
|
295
|
+
# This method appears at the top when profiling active_record test cases run.
|
296
|
+
# Avoid costly calculation when there are no prefix and suffix.
|
297
|
+
return table if @options[:table_name_prefix].blank? && @options[:table_name_suffix].blank?
|
298
|
+
|
295
299
|
prefix = Regexp.escape(@options[:table_name_prefix].to_s)
|
296
300
|
suffix = Regexp.escape(@options[:table_name_suffix].to_s)
|
297
301
|
table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
|
data/lib/active_record/store.rb
CHANGED
@@ -70,7 +70,7 @@ module ActiveRecord
|
|
70
70
|
#
|
71
71
|
# The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
|
72
72
|
#
|
73
|
-
# User.stored_attributes[:settings] # [:color, :homepage, :two_factor_auth, :login_retry]
|
73
|
+
# User.stored_attributes[:settings] # => [:color, :homepage, :two_factor_auth, :login_retry]
|
74
74
|
#
|
75
75
|
# == Overwriting default accessors
|
76
76
|
#
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
class TableMetadata # :nodoc:
|
5
|
-
delegate :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
|
5
|
+
delegate :join_primary_key, :join_primary_type, :join_foreign_key, :join_foreign_type, to: :reflection
|
6
6
|
|
7
7
|
def initialize(klass, arel_table, reflection = nil)
|
8
8
|
@klass = klass
|
@@ -54,6 +54,10 @@ module ActiveRecord
|
|
54
54
|
reflection&.polymorphic?
|
55
55
|
end
|
56
56
|
|
57
|
+
def polymorphic_name_association
|
58
|
+
reflection&.polymorphic_name
|
59
|
+
end
|
60
|
+
|
57
61
|
def through_association?
|
58
62
|
reflection&.through_reflection?
|
59
63
|
end
|
@@ -63,11 +63,11 @@ module ActiveRecord
|
|
63
63
|
def encoded(value)
|
64
64
|
return if default_value?(value)
|
65
65
|
payload = coder.dump(value)
|
66
|
-
if payload && binary?
|
67
|
-
|
68
|
-
|
66
|
+
if payload && @subtype.binary?
|
67
|
+
ActiveModel::Type::Binary::Data.new(payload)
|
68
|
+
else
|
69
|
+
payload
|
69
70
|
end
|
70
|
-
payload
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|