activerecord 7.0.2.4 → 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.

Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +172 -0
  3. data/lib/active_record/associations/collection_association.rb +1 -2
  4. data/lib/active_record/associations/collection_proxy.rb +2 -2
  5. data/lib/active_record/associations/has_many_association.rb +7 -4
  6. data/lib/active_record/associations/join_dependency.rb +17 -13
  7. data/lib/active_record/associations.rb +15 -15
  8. data/lib/active_record/attribute_methods/serialization.rb +34 -50
  9. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -0
  10. data/lib/active_record/attribute_methods.rb +1 -1
  11. data/lib/active_record/base.rb +3 -3
  12. data/lib/active_record/coders/yaml_column.rb +10 -2
  13. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +1 -1
  14. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -0
  15. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +3 -3
  16. data/lib/active_record/connection_adapters/abstract_adapter.rb +5 -5
  17. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +9 -1
  18. data/lib/active_record/connection_adapters/mysql/quoting.rb +3 -1
  19. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +19 -1
  20. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
  21. data/lib/active_record/connection_adapters/postgresql/quoting.rb +1 -1
  22. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -1
  23. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +2 -0
  24. data/lib/active_record/connection_adapters/postgresql_adapter.rb +4 -3
  25. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -2
  26. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +7 -2
  27. data/lib/active_record/connection_handling.rb +2 -2
  28. data/lib/active_record/core.rb +3 -3
  29. data/lib/active_record/delegated_type.rb +1 -1
  30. data/lib/active_record/encryption/configurable.rb +8 -2
  31. data/lib/active_record/encryption/contexts.rb +3 -3
  32. data/lib/active_record/encryption/derived_secret_key_provider.rb +1 -1
  33. data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
  34. data/lib/active_record/encryption/encryptable_record.rb +2 -4
  35. data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
  36. data/lib/active_record/encryption/encryptor.rb +7 -7
  37. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
  38. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -4
  39. data/lib/active_record/encryption/message.rb +1 -1
  40. data/lib/active_record/encryption/properties.rb +1 -1
  41. data/lib/active_record/encryption/scheme.rb +1 -1
  42. data/lib/active_record/enum.rb +1 -1
  43. data/lib/active_record/fixtures.rb +4 -4
  44. data/lib/active_record/gem_version.rb +3 -3
  45. data/lib/active_record/locking/pessimistic.rb +3 -3
  46. data/lib/active_record/log_subscriber.rb +10 -5
  47. data/lib/active_record/middleware/database_selector.rb +13 -6
  48. data/lib/active_record/middleware/shard_selector.rb +4 -4
  49. data/lib/active_record/migration/command_recorder.rb +3 -3
  50. data/lib/active_record/migration/compatibility.rb +7 -26
  51. data/lib/active_record/migration.rb +5 -4
  52. data/lib/active_record/model_schema.rb +22 -10
  53. data/lib/active_record/persistence.rb +9 -8
  54. data/lib/active_record/querying.rb +1 -1
  55. data/lib/active_record/railtie.rb +20 -16
  56. data/lib/active_record/railties/databases.rake +16 -11
  57. data/lib/active_record/reflection.rb +6 -0
  58. data/lib/active_record/relation/batches.rb +3 -3
  59. data/lib/active_record/relation/query_methods.rb +27 -6
  60. data/lib/active_record/relation.rb +7 -6
  61. data/lib/active_record/sanitization.rb +6 -5
  62. data/lib/active_record/scoping/default.rb +5 -7
  63. data/lib/active_record/serialization.rb +5 -0
  64. data/lib/active_record/signed_id.rb +2 -2
  65. data/lib/active_record/store.rb +7 -2
  66. data/lib/active_record/tasks/database_tasks.rb +26 -21
  67. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -2
  68. data/lib/active_record/test_fixtures.rb +12 -5
  69. data/lib/active_record/translation.rb +1 -1
  70. data/lib/active_record/validations/associated.rb +3 -3
  71. data/lib/active_record/validations/presence.rb +2 -2
  72. data/lib/active_record/validations/uniqueness.rb +3 -3
  73. data/lib/active_record/version.rb +1 -1
  74. data/lib/active_record.rb +14 -0
  75. metadata +10 -10
@@ -7,11 +7,11 @@ module ActiveRecord
7
7
  # shard to switch to and allows for applications to write custom strategies
8
8
  # for swapping if needed.
9
9
  #
10
- # The ShardSelector takes a set of options (currently only `lock` is supported)
11
- # that can be used by the middleware to alter behavior. `lock` is
10
+ # The ShardSelector takes a set of options (currently only +lock+ is supported)
11
+ # that can be used by the middleware to alter behavior. +lock+ is
12
12
  # true by default and will prohibit the request from switching shards once
13
- # inside the block. If `lock` is false, then shard swapping will be allowed.
14
- # For tenant based sharding, `lock` should always be true to prevent application
13
+ # inside the block. If +lock+ is false, then shard swapping will be allowed.
14
+ # For tenant based sharding, +lock+ should always be true to prevent application
15
15
  # code from mistakenly switching between tenants.
16
16
  #
17
17
  # Options can be set in the config:
@@ -13,10 +13,10 @@ module ActiveRecord
13
13
  # * add_reference
14
14
  # * add_timestamps
15
15
  # * change_column
16
- # * change_column_default (must supply a :from and :to option)
16
+ # * change_column_default (must supply a +:from+ and +:to+ option)
17
17
  # * change_column_null
18
- # * change_column_comment (must supply a :from and :to option)
19
- # * change_table_comment (must supply a :from and :to option)
18
+ # * change_column_comment (must supply a +:from+ and +:to+ option)
19
+ # * change_table_comment (must supply a +:from+ and +:to+ option)
20
20
  # * create_join_table
21
21
  # * create_table
22
22
  # * disable_extension
@@ -92,27 +92,10 @@ module ActiveRecord
92
92
  end
93
93
  end
94
94
 
95
- module SQLite3
96
- module TableDefinition
97
- def references(*args, **options)
98
- args.each do |ref_name|
99
- ReferenceDefinition.new(ref_name, type: :integer, **options).add_to(self)
100
- end
101
- end
102
- alias :belongs_to :references
103
-
104
- def column(name, type, index: nil, **options)
105
- options[:precision] ||= nil
106
- super
107
- end
108
- end
109
- end
110
-
111
95
  module TableDefinition
112
96
  def references(*args, **options)
113
- args.each do |ref_name|
114
- ReferenceDefinition.new(ref_name, **options).add_to(self)
115
- end
97
+ options[:_uses_legacy_reference_index_name] = true
98
+ super
116
99
  end
117
100
  alias :belongs_to :references
118
101
 
@@ -148,12 +131,11 @@ module ActiveRecord
148
131
 
149
132
  def add_reference(table_name, ref_name, **options)
150
133
  if connection.adapter_name == "SQLite"
151
- reference_definition = ReferenceDefinition.new(ref_name, type: :integer, **options)
152
- else
153
- reference_definition = ReferenceDefinition.new(ref_name, **options)
134
+ options[:type] = :integer
154
135
  end
155
136
 
156
- reference_definition.add_to(connection.update_table_definition(table_name, self))
137
+ options[:_uses_legacy_reference_index_name] = true
138
+ super
157
139
  end
158
140
  alias :add_belongs_to :add_reference
159
141
 
@@ -161,9 +143,8 @@ module ActiveRecord
161
143
  def compatible_table_definition(t)
162
144
  class << t
163
145
  prepend TableDefinition
164
- prepend SQLite3::TableDefinition
165
146
  end
166
- t
147
+ super
167
148
  end
168
149
  end
169
150
 
@@ -228,7 +209,7 @@ module ActiveRecord
228
209
  class << t
229
210
  prepend TableDefinition
230
211
  end
231
- t
212
+ super
232
213
  end
233
214
 
234
215
  def command_recorder
@@ -326,7 +326,7 @@ module ActiveRecord
326
326
  # details.
327
327
  # * <tt>change_table(name, options)</tt>: Allows to make column alterations to
328
328
  # the table called +name+. It makes the table object available to a block that
329
- # can then add/remove columns, indexes or foreign keys to it.
329
+ # can then add/remove columns, indexes, or foreign keys to it.
330
330
  # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
331
331
  # a column but keeps the type and content.
332
332
  # * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
@@ -576,7 +576,7 @@ module ActiveRecord
576
576
  MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
577
577
 
578
578
  # This class is used to verify that all migrations have been run before
579
- # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
579
+ # loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
580
580
  class CheckPending
581
581
  def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
582
582
  @app = app
@@ -810,8 +810,9 @@ module ActiveRecord
810
810
 
811
811
  # Runs the given migration classes.
812
812
  # Last argument can specify options:
813
- # - :direction (default is :up)
814
- # - :revert (default is false)
813
+ #
814
+ # - +:direction+ - Default is +:up+.
815
+ # - +:revert+ - Default is +false+.
815
816
  def run(*migration_classes)
816
817
  opts = migration_classes.extract_options!
817
818
  dir = opts[:direction] || :up
@@ -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=
@@ -617,7 +629,7 @@ module ActiveRecord
617
629
 
618
630
  "#{full_table_name_prefix}#{contained}#{undecorated_table_name(model_name)}#{full_table_name_suffix}"
619
631
  else
620
- # STI subclasses always use their superclass' table.
632
+ # STI subclasses always use their superclass's table.
621
633
  base_class.table_name
622
634
  end
623
635
  end
@@ -62,7 +62,7 @@ module ActiveRecord
62
62
  # Active Record callbacks or validations. Though passed values
63
63
  # go through Active Record's type casting and serialization.
64
64
  #
65
- # See <tt>ActiveRecord::Persistence#insert_all</tt> for documentation.
65
+ # See #insert_all for documentation.
66
66
  def insert(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
67
67
  insert_all([ attributes ], returning: returning, unique_by: unique_by, record_timestamps: record_timestamps)
68
68
  end
@@ -79,7 +79,7 @@ module ActiveRecord
79
79
  # duplicate rows are skipped.
80
80
  # Override with <tt>:unique_by</tt> (see below).
81
81
  #
82
- # Returns an <tt>ActiveRecord::Result</tt> with its contents based on
82
+ # Returns an ActiveRecord::Result with its contents based on
83
83
  # <tt>:returning</tt> (see below).
84
84
  #
85
85
  # ==== Options
@@ -151,7 +151,7 @@ module ActiveRecord
151
151
  # Active Record callbacks or validations. Though passed values
152
152
  # go through Active Record's type casting and serialization.
153
153
  #
154
- # See <tt>ActiveRecord::Persistence#insert_all!</tt> for more.
154
+ # See #insert_all! for more.
155
155
  def insert!(attributes, returning: nil, record_timestamps: nil)
156
156
  insert_all!([ attributes ], returning: returning, record_timestamps: record_timestamps)
157
157
  end
@@ -167,10 +167,9 @@ module ActiveRecord
167
167
  # Raises <tt>ActiveRecord::RecordNotUnique</tt> if any rows violate a
168
168
  # unique index on the table. In that case, no rows are inserted.
169
169
  #
170
- # To skip duplicate rows, see <tt>ActiveRecord::Persistence#insert_all</tt>.
171
- # To replace them, see <tt>ActiveRecord::Persistence#upsert_all</tt>.
170
+ # To skip duplicate rows, see #insert_all. To replace them, see #upsert_all.
172
171
  #
173
- # Returns an <tt>ActiveRecord::Result</tt> with its contents based on
172
+ # Returns an ActiveRecord::Result with its contents based on
174
173
  # <tt>:returning</tt> (see below).
175
174
  #
176
175
  # ==== Options
@@ -219,7 +218,7 @@ module ActiveRecord
219
218
  # it trigger Active Record callbacks or validations. Though passed values
220
219
  # go through Active Record's type casting and serialization.
221
220
  #
222
- # See <tt>ActiveRecord::Persistence#upsert_all</tt> for documentation.
221
+ # See #upsert_all for documentation.
223
222
  def upsert(attributes, on_duplicate: :update, returning: nil, unique_by: nil, record_timestamps: nil)
224
223
  upsert_all([ attributes ], on_duplicate: on_duplicate, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps)
225
224
  end
@@ -232,7 +231,7 @@ module ActiveRecord
232
231
  # The +attributes+ parameter is an Array of Hashes. Every Hash determines
233
232
  # the attributes for a single row and must have the same keys.
234
233
  #
235
- # Returns an <tt>ActiveRecord::Result</tt> with its contents based on
234
+ # Returns an ActiveRecord::Result with its contents based on
236
235
  # <tt>:returning</tt> (see below).
237
236
  #
238
237
  # By default, +upsert_all+ will update all the columns that can be updated when
@@ -806,6 +805,7 @@ module ActiveRecord
806
805
  def update_columns(attributes)
807
806
  raise ActiveRecordError, "cannot update a new record" if new_record?
808
807
  raise ActiveRecordError, "cannot update a destroyed record" if destroyed?
808
+ _raise_readonly_record_error if readonly?
809
809
 
810
810
  attributes = attributes.transform_keys do |key|
811
811
  name = key.to_s
@@ -992,6 +992,7 @@ module ActiveRecord
992
992
  #
993
993
  def touch(*names, time: nil)
994
994
  _raise_record_not_touched_error unless persisted?
995
+ _raise_readonly_record_error if readonly?
995
996
 
996
997
  attribute_names = timestamp_attributes_for_update_in_model
997
998
  attribute_names |= names.map! do |name|
@@ -39,7 +39,7 @@ module ActiveRecord
39
39
  # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
40
40
  # # => [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "author"=>"Quentin"}>, ...]
41
41
  #
42
- # You can use the same string replacement techniques as you can with <tt>ActiveRecord::QueryMethods#where</tt>:
42
+ # You can use the same string replacement techniques as you can with ActiveRecord::QueryMethods#where :
43
43
  #
44
44
  # Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
45
45
  # Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
@@ -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
@@ -389,5 +379,19 @@ To keep using the current cache store, you can turn off cache versioning entirel
389
379
  end
390
380
  end
391
381
  end
382
+
383
+ initializer "active_record.unregister_current_scopes_on_unload" do |app|
384
+ config.after_initialize do
385
+ unless app.config.cache_classes
386
+ Rails.autoloaders.main.on_unload do |_cpath, value, _abspath|
387
+ # Conditions are written this way to be robust against custom
388
+ # implementations of value#is_a? or value#<.
389
+ if Class === value && ActiveRecord::Base > value
390
+ value.current_scope = nil
391
+ end
392
+ end
393
+ end
394
+ end
395
+ end
392
396
  end
393
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::Tasks::DatabaseTasks.dump_schema(db_config)
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::Tasks::DatabaseTasks.dump_schema(db_config)
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"
487
- task name => :load_config do
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"
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::Tasks::DatabaseTasks.load_schema(db_config)
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::Tasks::DatabaseTasks.load_schema(db_config)
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::Tasks::DatabaseTasks.load_schema(db_config)
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)
@@ -297,6 +297,12 @@ module ActiveRecord
297
297
  options[:strict_loading]
298
298
  end
299
299
 
300
+ def strict_loading_violation_message(owner)
301
+ message = +"`#{owner}` is marked for strict_loading."
302
+ message << " The #{polymorphic? ? "polymorphic association" : "#{klass} association"}"
303
+ message << " named `:#{name}` cannot be lazily loaded."
304
+ end
305
+
300
306
  protected
301
307
  def actual_source_reflection # FIXME: this is a horrible name
302
308
  self
@@ -37,7 +37,7 @@ module ActiveRecord
37
37
  # * <tt>:finish</tt> - Specifies the primary key value to end at, inclusive of the value.
38
38
  # * <tt>:error_on_ignore</tt> - Overrides the application config to specify if an error should be raised when
39
39
  # an order is present in the relation.
40
- # * <tt>:order</tt> - Specifies the primary key order (can be :asc or :desc). Defaults to :asc.
40
+ # * <tt>:order</tt> - Specifies the primary key order (can be +:asc+ or +:desc+). Defaults to +:asc+.
41
41
  #
42
42
  # Limits are honored, and if present there is no requirement for the batch
43
43
  # size: it can be less than, equal to, or greater than the limit.
@@ -102,7 +102,7 @@ module ActiveRecord
102
102
  # * <tt>:finish</tt> - Specifies the primary key value to end at, inclusive of the value.
103
103
  # * <tt>:error_on_ignore</tt> - Overrides the application config to specify if an error should be raised when
104
104
  # an order is present in the relation.
105
- # * <tt>:order</tt> - Specifies the primary key order (can be :asc or :desc). Defaults to :asc.
105
+ # * <tt>:order</tt> - Specifies the primary key order (can be +:asc+ or +:desc+). Defaults to +:asc+.
106
106
  #
107
107
  # Limits are honored, and if present there is no requirement for the batch
108
108
  # size: it can be less than, equal to, or greater than the limit.
@@ -167,7 +167,7 @@ module ActiveRecord
167
167
  # * <tt>:finish</tt> - Specifies the primary key value to end at, inclusive of the value.
168
168
  # * <tt>:error_on_ignore</tt> - Overrides the application config to specify if an error should be raised when
169
169
  # an order is present in the relation.
170
- # * <tt>:order</tt> - Specifies the primary key order (can be :asc or :desc). Defaults to :asc.
170
+ # * <tt>:order</tt> - Specifies the primary key order (can be +:asc+ or +:desc+). Defaults to +:asc+.
171
171
  #
172
172
  # Limits are honored, and if present there is no requirement for the batch
173
173
  # size, it can be less than, equal, or greater than the limit.
@@ -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 #where does not have any parameter.
14
- # In this case, #where must be chained with #not to return a new relation.
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
 
@@ -40,6 +40,13 @@ module ActiveRecord
40
40
  #
41
41
  # User.where.not(name: "Jon", role: "admin")
42
42
  # # SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
43
+ #
44
+ # If there is a non-nil condition on a nullable column in the hash condition, the records that have
45
+ # nil values on the nullable column won't be returned.
46
+ # User.create!(nullable_country: nil)
47
+ # User.where.not(nullable_country: "UK")
48
+ # # SELECT * FROM users WHERE NOT (nullable_country = 'UK')
49
+ # # => []
43
50
  def not(opts, *rest)
44
51
  where_clause = @scope.send(:build_where_clause, opts, rest)
45
52
 
@@ -162,7 +169,7 @@ module ActiveRecord
162
169
  #
163
170
  # users = User.includes(:address, friends: [:address, :followers])
164
171
  #
165
- # === conditions
172
+ # === Conditions
166
173
  #
167
174
  # If you want to add string conditions to your included models, you'll have
168
175
  # to explicitly reference them. For example:
@@ -710,12 +717,26 @@ module ActiveRecord
710
717
  # === no argument
711
718
  #
712
719
  # If no argument is passed, #where returns a new instance of WhereChain, that
713
- # can be chained with #not to return a new relation that negates the where clause.
720
+ # can be chained with WhereChain#not, WhereChain#missing, or WhereChain#associated.
721
+ #
722
+ # Chaining with WhereChain#not:
714
723
  #
715
724
  # User.where.not(name: "Jon")
716
725
  # # SELECT * FROM users WHERE name != 'Jon'
717
726
  #
718
- # See WhereChain for more details on #not.
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
719
740
  #
720
741
  # === blank condition
721
742
  #
@@ -429,10 +429,10 @@ module ActiveRecord
429
429
  end
430
430
  end
431
431
 
432
- def _exec_scope(*args, &block) # :nodoc:
432
+ def _exec_scope(...) # :nodoc:
433
433
  @delegate_to_klass = true
434
434
  registry = klass.scope_registry
435
- _scoping(nil, registry) { instance_exec(*args, &block) || self }
435
+ _scoping(nil, registry) { instance_exec(...) || self }
436
436
  ensure
437
437
  @delegate_to_klass = false
438
438
  end
@@ -654,7 +654,7 @@ module ActiveRecord
654
654
  # for queries to actually be executed concurrently. Otherwise it defaults to
655
655
  # executing them in the foreground.
656
656
  #
657
- # +load_async+ will also fallback to executing in the foreground in the test environment when transactional
657
+ # +load_async+ will also fall back to executing in the foreground in the test environment when transactional
658
658
  # fixtures are enabled.
659
659
  #
660
660
  # If the query was actually executed in the background, the Active Record logs will show
@@ -712,6 +712,7 @@ module ActiveRecord
712
712
  @to_sql = @arel = @loaded = @should_eager_load = nil
713
713
  @offsets = @take = nil
714
714
  @cache_keys = nil
715
+ @cache_versions = nil
715
716
  @records = nil
716
717
  self
717
718
  end
@@ -736,7 +737,7 @@ module ActiveRecord
736
737
  #
737
738
  # User.where(name: 'Oscar').where_values_hash
738
739
  # # => {name: "Oscar"}
739
- def where_values_hash(relation_table_name = klass.table_name)
740
+ def where_values_hash(relation_table_name = klass.table_name) # :nodoc:
740
741
  where_clause.to_h(relation_table_name)
741
742
  end
742
743
 
@@ -756,7 +757,7 @@ module ActiveRecord
756
757
  # Joins that are also marked for preloading. In which case we should just eager load them.
757
758
  # Note that this is a naive implementation because we could have strings and symbols which
758
759
  # represent the same association, but that aren't matched by this. Also, we could have
759
- # nested hashes which partially match, e.g. { a: :b } & { a: [:b, :c] }
760
+ # nested hashes which partially match, e.g. <tt>{ a: :b } & { a: [:b, :c] }</tt>
760
761
  def joined_includes_values
761
762
  includes_values & joins_values
762
763
  end
@@ -917,7 +918,7 @@ module ActiveRecord
917
918
  preload_associations(records) unless skip_preloading_value
918
919
 
919
920
  records.each(&:readonly!) if readonly_value
920
- records.each(&:strict_loading!) if strict_loading_value
921
+ records.each { |record| record.strict_loading!(strict_loading_value) } unless strict_loading_value.nil?
921
922
 
922
923
  records
923
924
  end
@@ -92,16 +92,17 @@ module ActiveRecord
92
92
  end
93
93
 
94
94
  # Sanitizes a +string+ so that it is safe to use within an SQL
95
- # LIKE statement. This method uses +escape_character+ to escape all occurrences of "\", "_" and "%".
95
+ # LIKE statement. This method uses +escape_character+ to escape all
96
+ # occurrences of itself, "_" and "%".
96
97
  #
97
- # sanitize_sql_like("100%")
98
- # # => "100\\%"
98
+ # sanitize_sql_like("100% true!")
99
+ # # => "100\\% true!"
99
100
  #
100
101
  # sanitize_sql_like("snake_cased_string")
101
102
  # # => "snake\\_cased\\_string"
102
103
  #
103
- # sanitize_sql_like("100%", "!")
104
- # # => "100!%"
104
+ # sanitize_sql_like("100% true!", "!")
105
+ # # => "100!% true!!"
105
106
  #
106
107
  # sanitize_sql_like("snake_cased_string", "!")
107
108
  # # => "snake!_cased!_string"
@@ -48,10 +48,6 @@ module ActiveRecord
48
48
  super || default_scopes.any? || respond_to?(:default_scope)
49
49
  end
50
50
 
51
- def before_remove_const # :nodoc:
52
- self.current_scope = nil
53
- end
54
-
55
51
  # Checks if the model has any default scopes. If all_queries
56
52
  # is set to true, the method will check if there are any
57
53
  # default_scopes for the model where +all_queries+ is true.
@@ -83,7 +79,7 @@ module ActiveRecord
83
79
  # <tt>all_queries: true</tt>:
84
80
  #
85
81
  # class Article < ActiveRecord::Base
86
- # default_scope { where(blog_id: 1) }, all_queries: true
82
+ # default_scope -> { where(blog_id: 1) }, all_queries: true
87
83
  # end
88
84
  #
89
85
  # Applying a default scope to all queries will ensure that records
@@ -150,11 +146,13 @@ module ActiveRecord
150
146
  end
151
147
  elsif default_scopes.any?
152
148
  evaluate_default_scope do
153
- default_scopes.inject(relation) do |default_scope, scope_obj|
149
+ default_scopes.inject(relation) do |combined_scope, scope_obj|
154
150
  if execute_scope?(all_queries, scope_obj)
155
151
  scope = scope_obj.scope.respond_to?(:to_proc) ? scope_obj.scope : scope_obj.scope.method(:call)
156
152
 
157
- default_scope.instance_exec(&scope) || default_scope
153
+ combined_scope.instance_exec(&scope) || combined_scope
154
+ else
155
+ combined_scope
158
156
  end
159
157
  end
160
158
  end
@@ -20,5 +20,10 @@ module ActiveRecord # :nodoc:
20
20
 
21
21
  super(options)
22
22
  end
23
+
24
+ private
25
+ def attribute_names_for_serialization
26
+ attribute_names
27
+ end
23
28
  end
24
29
  end
@@ -47,7 +47,7 @@ module ActiveRecord
47
47
  end
48
48
  end
49
49
 
50
- # Works like +find_signed+, but will raise an +ActiveSupport::MessageVerifier::InvalidSignature+
50
+ # Works like find_signed, but will raise an +ActiveSupport::MessageVerifier::InvalidSignature+
51
51
  # exception if the +signed_id+ has either expired, has a purpose mismatch, is for another record,
52
52
  # or has been tampered with. It will also raise an +ActiveRecord::RecordNotFound+ exception if
53
53
  # the valid signed id can't find a record.
@@ -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 further more be set to expire (the default is not to expire), and scoped down with a specific purpose.
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
  #