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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +159 -7
  3. data/README.rdoc +2 -2
  4. data/lib/active_record/associations/has_one_association.rb +4 -0
  5. data/lib/active_record/associations/preloader/through_association.rb +1 -1
  6. data/lib/active_record/associations/singular_association.rb +7 -5
  7. data/lib/active_record/associations.rb +15 -6
  8. data/lib/active_record/attribute_methods/read.rb +1 -1
  9. data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -4
  10. data/lib/active_record/attribute_methods.rb +5 -7
  11. data/lib/active_record/autosave_association.rb +9 -5
  12. data/lib/active_record/callbacks.rb +12 -14
  13. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +20 -16
  14. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -1
  15. data/lib/active_record/connection_adapters/abstract_adapter.rb +4 -0
  16. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +7 -3
  17. data/lib/active_record/connection_adapters/mysql/quoting.rb +8 -0
  18. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +4 -1
  19. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
  20. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -5
  21. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  22. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
  23. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +3 -2
  24. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  25. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -1
  26. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  27. data/lib/active_record/disable_joins_association_relation.rb +1 -1
  28. data/lib/active_record/explain_subscriber.rb +1 -1
  29. data/lib/active_record/gem_version.rb +2 -2
  30. data/lib/active_record/locking/optimistic.rb +32 -18
  31. data/lib/active_record/middleware/database_selector.rb +3 -3
  32. data/lib/active_record/migration/command_recorder.rb +1 -2
  33. data/lib/active_record/migration/compatibility.rb +7 -0
  34. data/lib/active_record/migration.rb +1 -1
  35. data/lib/active_record/persistence.rb +4 -4
  36. data/lib/active_record/reflection.rb +8 -0
  37. data/lib/active_record/relation/calculations.rb +50 -23
  38. data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -1
  39. data/lib/active_record/relation/predicate_builder.rb +2 -1
  40. data/lib/active_record/relation/query_methods.rb +11 -3
  41. data/lib/active_record/result.rb +6 -4
  42. data/lib/active_record/schema_dumper.rb +4 -0
  43. data/lib/active_record/store.rb +1 -1
  44. data/lib/active_record/table_metadata.rb +5 -1
  45. data/lib/active_record/type/serialized.rb +4 -4
  46. data/lib/arel/filter_predications.rb +1 -1
  47. data/lib/arel/nodes/filter.rb +1 -1
  48. 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 = unquote(schema), unquote(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(@timestamp_decoder.to_h)
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,
@@ -30,7 +30,7 @@ module ActiveRecord
30
30
  record[key]
31
31
  end
32
32
 
33
- records = ids.flat_map { |id| records_by_id[id.to_i] }
33
+ records = ids.flat_map { |id| records_by_id[id] }
34
34
  records.compact!
35
35
 
36
36
  @records = records
@@ -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] ||
@@ -9,8 +9,8 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 4
13
- PRE = "3"
12
+ TINY = 6
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -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 <tt>ActiveRecord::StaleObjectError</tt> exception is thrown if that has occurred
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 <tt>ActiveRecord::Locking::Pessimistic</tt> for an alternative.
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 = _primary_key_constraints_hash
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
- return super unless locking_enabled?
122
-
123
- locking_column = self.class.locking_column
125
+ affected_rows = super
124
126
 
125
- delete_constraints = _primary_key_constraints_hash
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
- def locking_column
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 `rails new my_app --minimal` you will need to call
47
- # `require "active_support/core_ext/integer/time"` to load the libraries
48
- # for +Time+.
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 specify at least one column name or more)
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
@@ -159,6 +159,13 @@ module ActiveRecord
159
159
  options[:precision] ||= nil
160
160
  super
161
161
  end
162
+
163
+ private
164
+ def raise_on_if_exist_options(options)
165
+ end
166
+
167
+ def raise_on_duplicate_column(name)
168
+ end
162
169
  end
163
170
 
164
171
  module CommandRecorder
@@ -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.migration_context.current_environment
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 = _primary_key_constraints_hash
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 _primary_key_constraints_hash
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(_primary_key_constraints_hash)
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
- _primary_key_constraints_hash
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
- column_alias_for(field.to_s.downcase)
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 = column_alias_for("#{operation} #{column_name.to_s.downcase}")
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] = type_for(col_name) do
376
- calculated_data.column_types.fetch(aliaz, Type.default_value)
377
- end
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
- value.select_values.empty? ? value.select(primary_key) : value
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
- Relation::QueryAttribute.new(column_name, value, table.type(column_name))
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
- self.not(reflection.table_name => { reflection.association_primary_key => nil })
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.where!(reflection.table_name => { reflection.association_primary_key => nil })
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, field: "value", other_field: "value">]
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
  #
@@ -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(name, Type.default_value)
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")
@@ -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? && payload.encoding != Encoding::BINARY
67
- payload = payload.dup if payload.frozen?
68
- payload.force_encoding(Encoding::BINARY)
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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Arel
3
+ module Arel # :nodoc: all
4
4
  module FilterPredications
5
5
  def filter(expr)
6
6
  Nodes::Filter.new(self, expr)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Arel
3
+ module Arel # :nodoc: all
4
4
  module Nodes
5
5
  class Filter < Binary
6
6
  include Arel::WindowPredications