From 675d3794229e873efff536bcf3a66dedf6d53999 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sat, 2 May 2020 21:01:43 +0100 Subject: [PATCH 001/244] Fix "global use of must_equal" deprecation warning Followup to e01bf7f88f7dcf61264b0189d674bfce464e4d9b, fixing two new occurrences introduced in 1c3a6e8f539adfab45d40b53a6aa0bfeaa2f497f. --- activerecord/test/cases/arel/attributes/attribute_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/test/cases/arel/attributes/attribute_test.rb b/activerecord/test/cases/arel/attributes/attribute_test.rb index 0e8cf13b7abbf..05dbb258578e4 100644 --- a/activerecord/test/cases/arel/attributes/attribute_test.rb +++ b/activerecord/test/cases/arel/attributes/attribute_test.rb @@ -643,7 +643,7 @@ class AttributeTest < Arel::Spec attribute = Attribute.new nil, nil node = attribute.between(eval("..0")) # eval for backwards compatibility - node.must_equal Nodes::LessThanOrEqual.new( + _(node).must_equal Nodes::LessThanOrEqual.new( attribute, Nodes::Casted.new(0, attribute) ) @@ -856,7 +856,7 @@ class AttributeTest < Arel::Spec attribute = Attribute.new nil, nil node = attribute.not_between(eval("..0")) # eval for backwards compatibility - node.must_equal Nodes::GreaterThan.new( + _(node).must_equal Nodes::GreaterThan.new( attribute, Nodes::Casted.new(0, attribute) ) From e063befb14ae33f93cc05dbe59253e3c0fc9a13c Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sun, 3 May 2020 11:51:12 +0100 Subject: [PATCH 002/244] Merge pull request #39124 from eugeneius/autosave_multiple_times Allow associations to be autosaved multiple times --- .../lib/active_record/autosave_association.rb | 4 +--- .../test/cases/autosave_association_test.rb | 9 +++++++++ activerecord/test/cases/transactions_test.rb | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index d6c7c298735a7..bb0d75656b18a 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -361,9 +361,7 @@ def normalize_reflection_attribute(indexed_attribute, reflection, index, attribu # Is used as a before_save callback to check while saving a collection # association whether or not the parent was a new record before saving. def before_save_collection_association - unless defined?(@new_record_before_save) - @new_record_before_save = new_record? - end + @new_record_before_save ||= new_record? end def after_save_collection_association diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 4f988e20509a7..1b423b6df81ac 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -739,6 +739,15 @@ def test_replace_on_new_object assert_equal 2, firm.clients.length assert_includes firm.clients, Client.find_by_name("New Client") end + + def test_replace_on_duplicated_object + firm = Firm.create!("name" => "New Firm").dup + firm.clients = [companies(:second_client), Client.new("name" => "New Client")] + assert firm.save + firm.reload + assert_equal 2, firm.clients.length + assert_includes firm.clients, Client.find_by_name("New Client") + end end class TestDefaultAutosaveAssociationOnNewRecord < ActiveRecord::TestCase diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index b5c1cac3d9e1e..956d10653f651 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -77,6 +77,20 @@ def test_rollback_dirty_changes_then_retry_save_on_new_record assert_equal topic.title, topic.reload.title end + def test_rollback_dirty_changes_then_retry_save_on_new_record_with_autosave_association + author = Author.new(name: "DHH") + book = Book.create! + author.books << book + + author.transaction do + author.save! + raise ActiveRecord::Rollback + end + + author.save! + assert_equal author, book.reload.author + end + def test_persisted_in_a_model_with_custom_primary_key_after_failed_save movie = Movie.create assert_not_predicate movie, :persisted? From d089687c5a99381d7564be4a0a7dea081585409b Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 11 Feb 2020 08:46:14 +0900 Subject: [PATCH 003/244] Fix "instance variable @same_site not initialized" warnings Ref https://github.com/rack/rack/pull/1587. --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5ca6ea4edad51..f67909559c8a3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -362,7 +362,7 @@ GEM thor raabro (1.1.6) racc (1.4.16) - rack (2.2.1) + rack (2.2.2) rack-cache (1.10.0) rack (>= 0.4) rack-protection (2.0.7) From a4b20e4ffcdc9726f210c4e828927768497d7392 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 6 May 2020 02:48:48 +0900 Subject: [PATCH 004/244] Merge pull request #39156 from bogdan/preloader-duplicate-object-ids Ensure array passed to preloader has no duplicate records by object_id --- .../lib/active_record/associations/preloader/association.rb | 2 +- .../associations/has_many_through_associations_test.rb | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 4c7b0e6f07418..78ba6324a1d9a 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -6,7 +6,7 @@ class Preloader class Association #:nodoc: def initialize(klass, owners, reflection, preload_scope) @klass = klass - @owners = owners + @owners = owners.uniq(&:__id__) @reflection = reflection @preload_scope = preload_scope @model = owners.first && owners.first.class diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 0c78f81365b6c..ed90cc4c8ef35 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -41,7 +41,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :posts, :readers, :people, :comments, :authors, :categories, :taggings, :tags, :owners, :pets, :toys, :jobs, :references, :companies, :members, :author_addresses, :subscribers, :books, :subscriptions, :developers, :categorizations, :essays, - :categories_posts, :clubs, :memberships, :organizations + :categories_posts, :clubs, :memberships, :organizations, :author_favorites # Dummies to force column loads so query counts are clean. def setup @@ -67,11 +67,13 @@ def test_through_association_with_left_joins end def test_preload_with_nested_association - posts = Post.preload(:author, :author_favorites_with_scope).to_a + posts = Post.where(id: [authors(:david).id, authors(:mary).id]). + preload(:author, :author_favorites_with_scope).order(:id).to_a assert_no_queries do posts.each(&:author) posts.each(&:author_favorites_with_scope) + assert_equal 1, posts[0].author_favorites_with_scope.length end end From a6c554157a601e569a7a2c8993e65448c63adb7a Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sat, 2 May 2020 07:03:06 +0900 Subject: [PATCH 005/244] Merge pull request #39108 from kamipo/lock_benchmarck-ips_version Lock benchmark-ips version < 2.8 --- Gemfile | 2 +- Gemfile.lock | 2 +- guides/bug_report_templates/benchmark.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 60766bd39126a..d764a0abdd3de 100644 --- a/Gemfile +++ b/Gemfile @@ -112,7 +112,7 @@ group :test do gem "byebug" end - gem "benchmark-ips" + gem "benchmark-ips", "< 2.8" end platforms :ruby, :mswin, :mswin64, :mingw, :x64_mingw do diff --git a/Gemfile.lock b/Gemfile.lock index f67909559c8a3..0197aab83a41b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -542,7 +542,7 @@ DEPENDENCIES azure-storage backburner bcrypt (~> 3.1.11) - benchmark-ips + benchmark-ips (< 2.8) blade blade-sauce_labs_plugin bootsnap (>= 1.4.2) diff --git a/guides/bug_report_templates/benchmark.rb b/guides/bug_report_templates/benchmark.rb index c4dc6b3bc3ec4..76fa7f3e5c971 100644 --- a/guides/bug_report_templates/benchmark.rb +++ b/guides/bug_report_templates/benchmark.rb @@ -8,7 +8,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } gem "rails", github: "rails/rails", branch: "6-0-stable" - gem "benchmark-ips" + gem "benchmark-ips", "< 2.8" end require "active_support" From 246be6488a608a84f3cf5576733ca8fc21fd84b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Dubois?= Date: Tue, 5 May 2020 17:49:35 +0200 Subject: [PATCH 006/244] Demonstrate connecting Active Storage to S3-compatible APIs [ci skip] --- guides/source/active_storage_overview.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/guides/source/active_storage_overview.md b/guides/source/active_storage_overview.md index 37fc6d6cfa027..d7755615c3322 100644 --- a/guides/source/active_storage_overview.md +++ b/guides/source/active_storage_overview.md @@ -76,7 +76,7 @@ development environment, you would add the following to config.active_storage.service = :local ``` -To use the Amazon S3 service in production, you add the following to +To use the S3 service in production, you add the following to `config/environments/production.rb`: ```ruby @@ -105,9 +105,9 @@ local: root: <%= Rails.root.join("storage") %> ``` -### Amazon S3 Service +### S3 Service (Amazon S3 and S3-compatible APIs) -Declare an S3 service in `config/storage.yml`: +To connect to Amazon S3, declare an S3 service in `config/storage.yml`: ```yaml amazon: @@ -128,10 +128,20 @@ NOTE: The core features of Active Storage require the following permissions: `s3 NOTE: If you want to use environment variables, standard SDK configuration files, profiles, IAM instance profiles or task roles, you can omit the `access_key_id`, `secret_access_key`, -and `region` keys in the example above. The Amazon S3 Service supports all of the +and `region` keys in the example above. The S3 Service supports all of the authentication options described in the [AWS SDK documentation] (https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html). +To connect to an S3-compatible object storage API such as Digital Ocean Spaces, provide the `endpoint`: + +```yaml +digitalocean: + service: S3 + endpoint: https://nyc3.digitaloceanspaces.com + access_key_id: ... + secret_access_key: ... + # ...and other options +``` ### Microsoft Azure Storage Service From 72c660641ad6ea63167133fdce2462b5bb4e2b86 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 7 May 2020 12:33:15 +0900 Subject: [PATCH 007/244] Merge pull request #39174 from kamipo/fix_group_by_result Fix the result of aggregations to maintain duplicated "group by" fields --- .../active_record/relation/query_methods.rb | 7 +++- activerecord/test/cases/calculations_test.rb | 37 +++++++++++++++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 1c0e14175b9ec..ba4280ea9777f 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -331,7 +331,7 @@ def group(*args) def group!(*args) # :nodoc: args.flatten! - self.group_values |= args + self.group_values += args self end @@ -1361,7 +1361,10 @@ def structurally_incompatible_values_for_or(other) values = other.values STRUCTURAL_OR_METHODS.reject do |method| default = DEFAULT_VALUES[method] - @values.fetch(method, default) == values.fetch(method, default) + v1, v2 = @values.fetch(method, default), values.fetch(method, default) + v1 = v1.uniq if v1.is_a?(Array) + v2 = v2.uniq if v2.is_a?(Array) + v1 == v2 end end diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 2ee1ef8471609..963bd2327a61f 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -114,10 +114,39 @@ def test_should_group_by_multiple_fields_having_functions end def test_should_group_by_summed_field - c = Account.group(:firm_id).sum(:credit_limit) - assert_equal 50, c[1] - assert_equal 105, c[6] - assert_equal 60, c[2] + expected = { nil => 50, 1 => 50, 2 => 60, 6 => 105, 9 => 53 } + assert_equal expected, Account.group(:firm_id).sum(:credit_limit) + end + + def test_group_by_multiple_same_field + accounts = Account.group(:firm_id) + + expected = { + nil => 50, + 1 => 50, + 2 => 60, + 6 => 105, + 9 => 53 + } + assert_equal expected, accounts.sum(:credit_limit) + + expected = { + [nil, nil] => 50, + [1, 1] => 50, + [2, 2] => 60, + [6, 6] => 55, + [9, 9] => 53 + } + assert_equal expected, accounts.merge!(accounts).maximum(:credit_limit) + + expected = { + [nil, nil, nil, nil] => 50, + [1, 1, 1, 1] => 50, + [2, 2, 2, 2] => 60, + [6, 6, 6, 6] => 50, + [9, 9, 9, 9] => 53 + } + assert_equal expected, accounts.merge!(accounts).minimum(:credit_limit) end def test_should_generate_valid_sql_with_joins_and_group From 8fb96ce90c0af467074eeead5a2714583a04f1a9 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 8 May 2020 21:14:39 +0900 Subject: [PATCH 008/244] Merge pull request #39192 from kamipo/fix_remove_foreign_key_validate `remove_foreign_key` doesn't care `:validate` option if database has no feature --- .../abstract/schema_definitions.rb | 3 ++- .../sqlite3/schema_statements.rb | 2 +- .../test/cases/migration/foreign_key_test.rb | 16 +++------------- .../migration/references_foreign_key_test.rb | 7 +------ 4 files changed, 7 insertions(+), 21 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 6a051db181812..2ada383ba4b58 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -105,8 +105,9 @@ def export_name_on_schema_dump? !ActiveRecord::SchemaDumper.fk_ignore_pattern.match?(name) if name end - def defined_for?(to_table: nil, **options) + def defined_for?(to_table: nil, validate: nil, **options) (to_table.nil? || to_table.to_s == self.to_table) && + (validate.nil? || validate == options.fetch(:validate, validate)) && options.all? { |k, v| self.options[k].to_s == v.to_s } end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb index 8eff6e8b6f8e8..3ab7ced7886ae 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb @@ -61,7 +61,7 @@ def add_foreign_key(from_table, to_table, **options) def remove_foreign_key(from_table, to_table = nil, **options) to_table ||= options[:to_table] - options = options.except(:name, :to_table) + options = options.except(:name, :to_table, :validate) foreign_keys = foreign_keys(from_table) fkey = foreign_keys.detect do |fk| diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index 50afb9d3da2a6..8b1b54c4ab5a6 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -32,7 +32,7 @@ class Astronaut < ActiveRecord::Base end class CreateRocketsMigration < ActiveRecord::Migration::Current - def up + def change create_table :rockets do |t| t.string :name end @@ -42,11 +42,6 @@ def up t.references :rocket, foreign_key: true end end - - def down - drop_table :astronauts, if_exists: true - drop_table :rockets, if_exists: true - end end def setup @@ -533,18 +528,13 @@ def test_foreign_key_constraint_is_not_cached_incorrectly end class CreateSchoolsAndClassesMigration < ActiveRecord::Migration::Current - def up + def change create_table(:schools) create_table(:classes) do |t| t.references :school end - add_foreign_key :classes, :schools - end - - def down - drop_table :classes, if_exists: true - drop_table :schools, if_exists: true + add_foreign_key :classes, :schools, validate: true end end diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb index 90a50a5651c51..43bb63389eef9 100644 --- a/activerecord/test/cases/migration/references_foreign_key_test.rb +++ b/activerecord/test/cases/migration/references_foreign_key_test.rb @@ -170,18 +170,13 @@ class ReferencesForeignKeyTest < ActiveRecord::TestCase end class CreateDogsMigration < ActiveRecord::Migration::Current - def up + def change create_table :dog_owners create_table :dogs do |t| t.references :dog_owner, foreign_key: true end end - - def down - drop_table :dogs, if_exists: true - drop_table :dog_owners, if_exists: true - end end def test_references_foreign_key_with_prefix From cb683cb18daa69f74bbedf677cd66a05a9349454 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sat, 9 May 2020 16:03:45 +0900 Subject: [PATCH 009/244] Fix index creation to preserve comment in bulk change table on MySQL I've found the bug when I'm refactoring index creation code in #39203. --- activerecord/CHANGELOG.md | 5 +++++ .../connection_adapters/abstract_mysql_adapter.rb | 5 +++-- activerecord/test/cases/migration_test.rb | 5 +++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 1054e941a45a2..815f325e7e873 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +* Fix index creation to preserve index comment in bulk change table on MySQL. + + *Ryuta Kamizono* + + ## Rails 6.0.3 (May 06, 2020) ## * Recommend applications don't use the `database` kwarg in `connected_to` diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 011d55700bb83..53e525dacd453 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -675,9 +675,10 @@ def rename_column_for_alter(table_name, column_name, new_column_name) end def add_index_for_alter(table_name, column_name, options = {}) - index_name, index_type, index_columns, _, index_algorithm, index_using = add_index_options(table_name, column_name, **options) + index_name, index_type, index_columns, _, index_algorithm, index_using, comment = add_index_options(table_name, column_name, **options) index_algorithm[0, 0] = ", " if index_algorithm.present? - "ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}" + sql = +"ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}" + add_sql_comment!(sql, comment) end def remove_index_for_alter(table_name, options = {}) diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 83fe85baecbb9..ea4dc68764d89 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -867,7 +867,7 @@ def test_adding_indexes classname = ActiveRecord::Base.connection.class.name[/[^:]*$/] expected_query_count = { "Mysql2Adapter" => 3, # Adding an index fires a query every time to check if an index already exists or not - "PostgreSQLAdapter" => 2, + "PostgreSQLAdapter" => 3, }.fetch(classname) { raise "need an expected query count for #{classname}" } @@ -875,7 +875,7 @@ def test_adding_indexes assert_queries(expected_query_count) do with_bulk_change_table do |t| t.index :username, unique: true, name: :awesome_username_index - t.index [:name, :age] + t.index [:name, :age], comment: "This is a comment" end end @@ -883,6 +883,7 @@ def test_adding_indexes name_age_index = index(:index_delete_me_on_name_and_age) assert_equal ["name", "age"].sort, name_age_index.columns.sort + assert_equal "This is a comment", name_age_index.comment assert_not name_age_index.unique assert index(:awesome_username_index).unique From a95da6a6aea89c44144865d8dd87e56f3c049d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Tue, 3 Mar 2020 14:52:59 -0500 Subject: [PATCH 010/244] Merge pull request #38620 from bogdanvlviv/add-activerecord-db-folder-to-gitignore Add activerecord/db/ to gitignore Without this, easily add test db accidentally when changed branch from master. --- activerecord/.gitignore | 1 + .../connection_handler_test.rb | 48 +++++++++---------- .../connection_handlers_multi_db_test.rb | 42 ++++++++-------- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/activerecord/.gitignore b/activerecord/.gitignore index 884ee009eb2c5..8d747034f6517 100644 --- a/activerecord/.gitignore +++ b/activerecord/.gitignore @@ -1,3 +1,4 @@ /sqlnet.log /test/config.yml +/test/db/ /test/fixtures/*.sqlite* diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb index f2fa6f12cf208..1de440237bfcd 100644 --- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb +++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb @@ -46,14 +46,14 @@ def test_establish_connection_using_3_levels_config config = { "default_env" => { - "readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" }, - "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } + "readonly" => { "adapter" => "sqlite3", "database" => "test/db/readonly.sqlite3" }, + "primary" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" } }, "another_env" => { - "readonly" => { "adapter" => "sqlite3", "database" => "db/bad-readonly.sqlite3" }, - "primary" => { "adapter" => "sqlite3", "database" => "db/bad-primary.sqlite3" } + "readonly" => { "adapter" => "sqlite3", "database" => "test/db/bad-readonly.sqlite3" }, + "primary" => { "adapter" => "sqlite3", "database" => "test/db/bad-primary.sqlite3" } }, - "common" => { "adapter" => "sqlite3", "database" => "db/common.sqlite3" } + "common" => { "adapter" => "sqlite3", "database" => "test/db/common.sqlite3" } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @@ -62,13 +62,13 @@ def test_establish_connection_using_3_levels_config @handler.establish_connection(:readonly) assert_not_nil pool = @handler.retrieve_connection_pool("readonly") - assert_equal "db/readonly.sqlite3", pool.spec.config[:database] + assert_equal "test/db/readonly.sqlite3", pool.spec.config[:database] assert_not_nil pool = @handler.retrieve_connection_pool("primary") - assert_equal "db/primary.sqlite3", pool.spec.config[:database] + assert_equal "test/db/primary.sqlite3", pool.spec.config[:database] assert_not_nil pool = @handler.retrieve_connection_pool("common") - assert_equal "db/common.sqlite3", pool.spec.config[:database] + assert_equal "test/db/common.sqlite3", pool.spec.config[:database] ensure ActiveRecord::Base.configurations = @prev_configs ENV["RAILS_ENV"] = previous_env @@ -80,24 +80,23 @@ def test_establish_connection_using_3_level_config_defaults_to_default_env_prima config = { "default_env" => { - "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" }, - "readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" } + "primary" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" }, + "readonly" => { "adapter" => "sqlite3", "database" => "test/db/readonly.sqlite3" } }, "another_env" => { - "primary" => { "adapter" => "sqlite3", "database" => "db/another-primary.sqlite3" }, - "readonly" => { "adapter" => "sqlite3", "database" => "db/another-readonly.sqlite3" } + "primary" => { "adapter" => "sqlite3", "database" => "test/db/another-primary.sqlite3" }, + "readonly" => { "adapter" => "sqlite3", "database" => "test/db/another-readonly.sqlite3" } } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config ActiveRecord::Base.establish_connection - assert_match "db/primary.sqlite3", ActiveRecord::Base.connection.pool.spec.config[:database] + assert_match "test/db/primary.sqlite3", ActiveRecord::Base.connection.pool.spec.config[:database] ensure ActiveRecord::Base.configurations = @prev_configs ENV["RAILS_ENV"] = previous_env ActiveRecord::Base.establish_connection(:arunit) - FileUtils.rm_rf "db" end def test_establish_connection_using_2_level_config_defaults_to_default_env_primary_db @@ -105,48 +104,47 @@ def test_establish_connection_using_2_level_config_defaults_to_default_env_prima config = { "default_env" => { - "adapter" => "sqlite3", "database" => "db/primary.sqlite3" + "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" }, "another_env" => { - "adapter" => "sqlite3", "database" => "db/bad-primary.sqlite3" + "adapter" => "sqlite3", "database" => "test/db/bad-primary.sqlite3" } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config ActiveRecord::Base.establish_connection - assert_match "db/primary.sqlite3", ActiveRecord::Base.connection.pool.spec.config[:database] + assert_match "test/db/primary.sqlite3", ActiveRecord::Base.connection.pool.spec.config[:database] ensure ActiveRecord::Base.configurations = @prev_configs ENV["RAILS_ENV"] = previous_env ActiveRecord::Base.establish_connection(:arunit) - FileUtils.rm_rf "db" end end def test_establish_connection_using_two_level_configurations - config = { "development" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } } + config = { "development" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @handler.establish_connection(:development) assert_not_nil pool = @handler.retrieve_connection_pool("development") - assert_equal "db/primary.sqlite3", pool.spec.config[:database] + assert_equal "test/db/primary.sqlite3", pool.spec.config[:database] ensure ActiveRecord::Base.configurations = @prev_configs end def test_establish_connection_using_top_level_key_in_two_level_config config = { - "development" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" }, - "development_readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" } + "development" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" }, + "development_readonly" => { "adapter" => "sqlite3", "database" => "test/db/readonly.sqlite3" } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @handler.establish_connection(:development_readonly) assert_not_nil pool = @handler.retrieve_connection_pool("development_readonly") - assert_equal "db/readonly.sqlite3", pool.spec.config[:database] + assert_equal "test/db/readonly.sqlite3", pool.spec.config[:database] ensure ActiveRecord::Base.configurations = @prev_configs end @@ -157,13 +155,13 @@ def test_symbolized_configurations_assignment development: { primary: { adapter: "sqlite3", - database: "db/development.sqlite3", + database: "test/db/development.sqlite3", }, }, test: { primary: { adapter: "sqlite3", - database: "db/test.sqlite3", + database: "test/db/test.sqlite3", }, }, } diff --git a/activerecord/test/cases/connection_adapters/connection_handlers_multi_db_test.rb b/activerecord/test/cases/connection_adapters/connection_handlers_multi_db_test.rb index bebbc58ecb393..a81de8a1124d6 100644 --- a/activerecord/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +++ b/activerecord/test/cases/connection_adapters/connection_handlers_multi_db_test.rb @@ -89,8 +89,8 @@ def test_establish_connection_using_3_levels_config config = { "default_env" => { - "readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" }, - "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } + "readonly" => { "adapter" => "sqlite3", "database" => "test/db/readonly.sqlite3" }, + "primary" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" } } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @@ -98,10 +98,10 @@ def test_establish_connection_using_3_levels_config ActiveRecord::Base.connects_to(database: { writing: :primary, reading: :readonly }) assert_not_nil pool = ActiveRecord::Base.connection_handlers[:writing].retrieve_connection_pool("primary") - assert_equal "db/primary.sqlite3", pool.spec.config[:database] + assert_equal "test/db/primary.sqlite3", pool.spec.config[:database] assert_not_nil pool = ActiveRecord::Base.connection_handlers[:reading].retrieve_connection_pool("primary") - assert_equal "db/readonly.sqlite3", pool.spec.config[:database] + assert_equal "test/db/readonly.sqlite3", pool.spec.config[:database] ensure ActiveRecord::Base.configurations = @prev_configs ActiveRecord::Base.establish_connection(:arunit) @@ -113,8 +113,8 @@ def test_switching_connections_via_handler config = { "default_env" => { - "readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" }, - "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } + "readonly" => { "adapter" => "sqlite3", "database" => "test/db/readonly.sqlite3" }, + "primary" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" } } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @@ -149,8 +149,8 @@ def test_establish_connection_using_3_levels_config_with_non_default_handlers config = { "default_env" => { - "readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" }, - "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } + "readonly" => { "adapter" => "sqlite3", "database" => "test/db/readonly.sqlite3" }, + "primary" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" } } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @@ -158,10 +158,10 @@ def test_establish_connection_using_3_levels_config_with_non_default_handlers ActiveRecord::Base.connects_to(database: { default: :primary, readonly: :readonly }) assert_not_nil pool = ActiveRecord::Base.connection_handlers[:default].retrieve_connection_pool("primary") - assert_equal "db/primary.sqlite3", pool.spec.config[:database] + assert_equal "test/db/primary.sqlite3", pool.spec.config[:database] assert_not_nil pool = ActiveRecord::Base.connection_handlers[:readonly].retrieve_connection_pool("primary") - assert_equal "db/readonly.sqlite3", pool.spec.config[:database] + assert_equal "test/db/readonly.sqlite3", pool.spec.config[:database] ensure ActiveRecord::Base.configurations = @prev_configs ActiveRecord::Base.establish_connection(:arunit) @@ -190,7 +190,7 @@ def test_switching_connections_with_database_url def test_switching_connections_with_database_config_hash previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "default_env" - config = { adapter: "sqlite3", database: "db/readonly.sqlite3" } + config = { adapter: "sqlite3", database: "test/db/readonly.sqlite3" } ActiveRecord::Base.connected_to(database: { writing: config }) do assert_equal :writing, ActiveRecord::Base.current_role @@ -226,8 +226,8 @@ def test_switching_connections_with_database_symbol_uses_default_role config = { "default_env" => { - "animals" => { adapter: "sqlite3", database: "db/animals.sqlite3" }, - "primary" => { adapter: "sqlite3", database: "db/primary.sqlite3" } + "animals" => { adapter: "sqlite3", database: "test/db/animals.sqlite3" }, + "primary" => { adapter: "sqlite3", database: "test/db/primary.sqlite3" } } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @@ -253,8 +253,8 @@ def test_switching_connections_with_database_hash_uses_passed_role_and_database config = { "default_env" => { - "animals" => { adapter: "sqlite3", database: "db/animals.sqlite3" }, - "primary" => { adapter: "sqlite3", database: "db/primary.sqlite3" } + "animals" => { adapter: "sqlite3", database: "test/db/animals.sqlite3" }, + "primary" => { adapter: "sqlite3", database: "test/db/primary.sqlite3" } } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @@ -277,7 +277,7 @@ def test_switching_connections_with_database_hash_uses_passed_role_and_database def test_connects_to_with_single_configuration config = { - "development" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" }, + "development" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" }, } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config @@ -294,15 +294,15 @@ def test_connects_to_with_single_configuration def test_connects_to_using_top_level_key_in_two_level_config config = { - "development" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" }, - "development_readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" } + "development" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" }, + "development_readonly" => { "adapter" => "sqlite3", "database" => "test/db/readonly.sqlite3" } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config ActiveRecord::Base.connects_to database: { writing: :development, reading: :development_readonly } assert_not_nil pool = ActiveRecord::Base.connection_handlers[:reading].retrieve_connection_pool("primary") - assert_equal "db/readonly.sqlite3", pool.spec.config[:database] + assert_equal "test/db/readonly.sqlite3", pool.spec.config[:database] ensure ActiveRecord::Base.configurations = @prev_configs ActiveRecord::Base.establish_connection(:arunit) @@ -310,8 +310,8 @@ def test_connects_to_using_top_level_key_in_two_level_config def test_connects_to_returns_array_of_established_connections config = { - "development" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" }, - "development_readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" } + "development" => { "adapter" => "sqlite3", "database" => "test/db/primary.sqlite3" }, + "development_readonly" => { "adapter" => "sqlite3", "database" => "test/db/readonly.sqlite3" } } @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config From 28cff96cffb9ef0efad5026906be30503129c452 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Tue, 5 May 2020 01:51:09 +0100 Subject: [PATCH 011/244] Merge pull request #39138 from jonathanhefner/flakey-destroyed_by_association-tests Fix flakey destroyed_by_association tests --- .../test/cases/associations/has_one_associations_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 3ef25c70274db..3f2b8ad1625ea 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -21,7 +21,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase self.use_transactional_tests = false unless supports_savepoints? fixtures :accounts, :companies, :developers, :projects, :developers_projects, - :ships, :pirates, :authors, :author_addresses, :memberships, :clubs + :ships, :pirates, :authors, :author_addresses, :books, :memberships, :clubs def setup Account.destroyed_account_ids.clear From bb15351e18bcf9b87df2e890c1e0d5bd5ec3e56c Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sun, 10 May 2020 06:52:44 +0900 Subject: [PATCH 012/244] Merge pull request #39210 from kamipo/fix_kernel_open Eager generate relation methods if a method is on `Kernel` --- activerecord/lib/active_record/scoping/named.rb | 4 ++++ activerecord/test/cases/relations_test.rb | 2 ++ activerecord/test/models/reply.rb | 4 ++++ activerecord/test/models/topic.rb | 1 + 4 files changed, 11 insertions(+) diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index c9e900eca0f43..f884e0422d644 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -205,6 +205,10 @@ def scope(name, body, &block) end private + def singleton_method_added(name) + generate_relation_method(name) if Kernel.respond_to?(name) + end + def valid_scope_name?(name) if respond_to?(name, true) && logger logger.warn "Creating scope :#{name}. " \ diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index d27b5059b1e6b..6f5a354eeade3 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -2053,6 +2053,8 @@ def test_relation_with_private_kernel_method sub_accounts = SubAccount.all assert_equal [accounts(:signals37)], sub_accounts.open assert_equal [accounts(:signals37)], sub_accounts.available + + assert_equal [topics(:second)], topics(:first).open_replies end def test_where_with_take_memoization diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb index b35623a344b28..f692ff31cddb4 100644 --- a/activerecord/test/models/reply.rb +++ b/activerecord/test/models/reply.rb @@ -9,6 +9,10 @@ class Reply < Topic has_many :silly_unique_replies, dependent: :destroy, foreign_key: "parent_id" scope :ordered, -> { Reply.order(:id) } + + def self.open + approved + end end class SillyReply < Topic diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 7a864c728c475..24e464677b572 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -36,6 +36,7 @@ def two has_many :replies, dependent: :destroy, foreign_key: "parent_id", autosave: true has_many :approved_replies, -> { approved }, class_name: "Reply", foreign_key: "parent_id", counter_cache: "replies_count" + has_many :open_replies, -> { open }, class_name: "Reply", foreign_key: "parent_id" has_many :unique_replies, dependent: :destroy, foreign_key: "parent_id" has_many :silly_unique_replies, dependent: :destroy, foreign_key: "parent_id" From fa704909061301dc3ff67cc21083bffe773e519b Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Mon, 11 May 2020 00:50:09 +0100 Subject: [PATCH 013/244] Merge pull request #39224 from yahonda/diag_build_68962 Address `InnerJoinAssociationTest#test_eager_load_with_string_joins` failure with mysql2 --- activerecord/test/cases/dirty_test.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index a2a501a794026..5566b372cc3e3 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -16,6 +16,10 @@ def setup Person.create first_name: "foo" end + def teardown + Person.delete_by(first_name: "foo") + end + def test_attribute_changes # New record - no changes. pirate = Pirate.new From ec830e0cf3b6995f2bca1a90d4cbfe7160f30e42 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Fri, 8 May 2020 14:50:21 -0700 Subject: [PATCH 014/244] Merge pull request #39199 from kamipo/scope_kwargs Support kwargs for named scopes --- activerecord/lib/active_record/scoping/named.rb | 1 + .../test/cases/scoping/named_scoping_test.rb | 12 ++++++++++++ activerecord/test/models/topic.rb | 2 ++ 3 files changed, 15 insertions(+) diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index f884e0422d644..590d2b76d5053 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -200,6 +200,7 @@ def scope(name, body, &block) scope end end + singleton_class.send(:ruby2_keywords, name) if respond_to?(:ruby2_keywords, true) generate_relation_method(name) end diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb index 3488442cabdc7..2c2e86eb66138 100644 --- a/activerecord/test/cases/scoping/named_scoping_test.rb +++ b/activerecord/test/cases/scoping/named_scoping_test.rb @@ -113,6 +113,18 @@ def test_scope_with_object assert objects.all?(&:approved?), "all objects should be approved" end + def test_scope_with_kwargs + # Explicit true + topics = Topic.with_kwargs(approved: true) + assert_operator topics.length, :>, 0 + assert topics.all?(&:approved?), "all objects should be approved" + + # No arguments + topics = Topic.with_kwargs() + assert_operator topics.length, :>, 0 + assert topics.none?(&:approved?), "all objects should not be approved" + end + def test_has_many_associations_have_access_to_scopes assert_not_equal Post.containing_the_letter_a, authors(:david).posts assert_not_empty Post.containing_the_letter_a diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 24e464677b572..4da28cb1489ec 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -28,6 +28,8 @@ def call end }.new(self) + scope :with_kwargs, ->(approved: false) { where(approved: approved) } + module NamedExtension def two 2 From c0fd8f4bb2d4dd9abfbef9cc658ca0c88b8b0842 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Thu, 5 Sep 2019 19:01:12 +0900 Subject: [PATCH 015/244] These `options` are not defined as keyword arguments Fixes Ruby 2.6 warnings --- activesupport/lib/active_support/cache.rb | 4 ++-- .../lib/active_support/cache/strategy/local_cache.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index d58d10c6ad334..3cb1c59ab9e77 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -327,7 +327,7 @@ def fetch(name, options = nil) end if entry - get_entry_value(entry, name, **options) + get_entry_value(entry, name, options) else save_block_result_to_cache(name, **options) { |_name| yield _name } end @@ -448,7 +448,7 @@ def fetch_multi(*names) payload[:hits] = reads.keys payload[:super_operation] = :fetch_multi - write_multi(writes, **options) + write_multi(writes, options) ordered end diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb index 49709939024db..9da2a6217b389 100644 --- a/activesupport/lib/active_support/cache/strategy/local_cache.rb +++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb @@ -160,7 +160,7 @@ def write_cache_value(name, value, **options) cache = local_cache cache.mute do if value - cache.write(name, value, **options) + cache.write(name, value, options) else cache.delete(name, **options) end From 2255b68b50c755ca1d15d3f07e911631d10bcdff Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 5 May 2020 18:16:48 +0900 Subject: [PATCH 016/244] Follow up to 3f27aa8cdf8c3c7f36d630f0241854f712e4c937 3cfd6d1 added lots of `**` and then 3f27aa8 has reverted unnecessary changes. `save_block_result_to_cache` is also unnecessary to take keyword arguments. --- activesupport/lib/active_support/cache.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 3cb1c59ab9e77..fbe9fe9a2f9ee 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -312,7 +312,7 @@ def mute # :bar # end # cache.fetch('foo') # => "bar" - def fetch(name, options = nil) + def fetch(name, options = nil, &block) if block_given? options = merged_options(options) key = normalize_key(name, options) @@ -329,7 +329,7 @@ def fetch(name, options = nil) if entry get_entry_value(entry, name, options) else - save_block_result_to_cache(name, **options) { |_name| yield _name } + save_block_result_to_cache(name, options, &block) end elsif options && options[:force] raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block." @@ -712,7 +712,7 @@ def get_entry_value(entry, name, options) entry.value end - def save_block_result_to_cache(name, **options) + def save_block_result_to_cache(name, options) result = instrument(:generate, name, options) do yield(name) end From 04d0fa7e5f210ca49b758f4678d0fe3d3da4d7b5 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 12 May 2020 05:47:38 +0900 Subject: [PATCH 017/244] Merge pull request #39241 from jonathanhefner/kwargs-warning-39227 Fix Ruby 2.7 keyword arguments warning --- actionpack/lib/action_dispatch/routing/url_for.rb | 1 + actionpack/test/dispatch/prefix_generation_test.rb | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index e02a6541c159c..3160fb117cacd 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -107,6 +107,7 @@ def initialize(*) @_routes = nil super end + ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true) # Hook overridden in controller to add request information # with +default_url_options+. Application logic should not diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index f20043b9ac671..e6106766ee118 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -126,12 +126,19 @@ def ivar_usage end end + module KwObject + def initialize(kw:) + end + end + class EngineObject + include KwObject include ActionDispatch::Routing::UrlFor include BlogEngine.routes.url_helpers end class AppObject + include KwObject include ActionDispatch::Routing::UrlFor include RailsApplication.routes.url_helpers end @@ -144,8 +151,8 @@ def app def setup RailsApplication.routes.default_url_options = {} - @engine_object = EngineObject.new - @app_object = AppObject.new + @engine_object = EngineObject.new(kw: 1) + @app_object = AppObject.new(kw: 2) end include BlogEngine.routes.mounted_helpers From 4e47ce407400035d19fcf8f8ada51745af29a1eb Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Tue, 12 May 2020 12:03:34 -0700 Subject: [PATCH 018/244] Merge pull request #39256 from jhawthorn/methods_on_kernel_and_relation Avoid confliting Kernel-named scopes on Relation --- activerecord/lib/active_record/scoping/named.rb | 2 +- activerecord/test/models/reply.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index 590d2b76d5053..f635295261313 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -207,7 +207,7 @@ def scope(name, body, &block) private def singleton_method_added(name) - generate_relation_method(name) if Kernel.respond_to?(name) + generate_relation_method(name) if Kernel.respond_to?(name) && !ActiveRecord::Relation.method_defined?(name) end def valid_scope_name?(name) diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb index f692ff31cddb4..4dbceb6b9a949 100644 --- a/activerecord/test/models/reply.rb +++ b/activerecord/test/models/reply.rb @@ -10,9 +10,14 @@ class Reply < Topic scope :ordered, -> { Reply.order(:id) } + # Method on Kernel def self.open approved end + + # Methods both on Kernel and Relation + def self.load(data:); end + def self.select(data:); end end class SillyReply < Topic From f53f24e3a8e08d94eab6bf7e2c6c111f827a5681 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Tue, 12 May 2020 23:33:47 +0100 Subject: [PATCH 019/244] Merge pull request #39234 from aidanharan/binary-fixture-windows Test failing on Windows because binary file being read inconsistently --- activerecord/lib/active_record/fixture_set/render_context.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/fixture_set/render_context.rb b/activerecord/lib/active_record/fixture_set/render_context.rb index c90b5343dc2bf..4f4f542fe7db8 100644 --- a/activerecord/lib/active_record/fixture_set/render_context.rb +++ b/activerecord/lib/active_record/fixture_set/render_context.rb @@ -10,7 +10,7 @@ def get_binding end def binary(path) - %(!!binary "#{Base64.strict_encode64(File.read(path))}") + %(!!binary "#{Base64.strict_encode64(File.read(path, mode: 'rb'))}") end end end From 17d56621ff88d8d5a2a4577572a1d0d98a1fabb1 Mon Sep 17 00:00:00 2001 From: Santiago Bartesaghi Date: Wed, 13 May 2020 00:40:27 -0300 Subject: [PATCH 020/244] Fix #39205 ReadOnlyError when on writing connection --- .../lib/active_record/test_fixtures.rb | 2 +- activerecord/test/cases/fixtures_test.rb | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/test_fixtures.rb b/activerecord/lib/active_record/test_fixtures.rb index 53ef5f1a35591..c374368662512 100644 --- a/activerecord/lib/active_record/test_fixtures.rb +++ b/activerecord/lib/active_record/test_fixtures.rb @@ -187,7 +187,7 @@ def enlist_fixture_connections # need to share a connection pool so that the reading connection # can see data in the open transaction on the writing connection. def setup_shared_connection_pool - writing_handler = ActiveRecord::Base.connection_handler + writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord::Base.writing_role] ActiveRecord::Base.connection_handlers.values.each do |handler| if handler != writing_handler diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 9102fadff3bf4..8df7eefa82920 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -1377,3 +1377,52 @@ def with_temporary_connection_pool ActiveRecord::Base.connection_handler.send(:owner_to_pool)["primary"] = old_pool end end + +class UsesWritingConnectionForFixtures < ActiveRecord::TestCase + include ActiveRecord::TestFixtures + self.use_transactional_tests = true + + fixtures :dogs + + def setup + @old_handler = ActiveRecord::Base.connection_handler + @old_handlers = ActiveRecord::Base.connection_handlers + @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config + db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(ENV["RAILS_ENV"], "readonly", readonly_config) + + handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new + handler.establish_connection(db_config) + ActiveRecord::Base.connection_handlers = {} + ActiveRecord::Base.connection_handler = handler + ActiveRecord::Base.connects_to(database: { writing: :default, reading: :readonly }) + end + + def teardown + ActiveRecord::Base.configurations = @prev_configs + ActiveRecord::Base.connection_handler = @old_handler + ActiveRecord::Base.connection_handlers = @old_handlers + end + + def test_uses_writing_connection_for_fixtures + ActiveRecord::Base.connected_to(role: :reading) do + Dog.first + + assert_nothing_raised do + ActiveRecord::Base.connected_to(role: :writing) { Dog.create! alias: "Doggo" } + end + end + end + + private + def config + { "default" => default_config, "readonly" => readonly_config } + end + + def default_config + { "adapter" => "sqlite3", "database" => "test/fixtures/fixture_database.sqlite3" } + end + + def readonly_config + default_config.merge("replica" => true) + end +end From 685584c0874963ed7f24f6a61fa9d452678455e4 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 13 May 2020 11:31:19 -0400 Subject: [PATCH 021/244] Move and update enlist_fixture_connections test This moves the previous test into the old test and reuses the connection that that test establishes rather than requiring we muck with temporary connection pool. The change here is more correct than the previous code since we're establishing new connections we should be checking the newly established reading and writing connections are the same, not checking against the existing ActiveRecord::Base.connection. The test here also most closely emulates a real application using multiple databases. Note: manual backport from master due to conflicts. Co-authored-by: John Crepezzi --- activerecord/test/cases/fixtures_test.rb | 38 ++++++------------------ 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 8df7eefa82920..846c2a42bff5a 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -1352,35 +1352,8 @@ class NilFixturePathTest < ActiveRecord::TestCase end end -class MultipleDatabaseFixturesTest < ActiveRecord::TestCase - test "enlist_fixture_connections ensures multiple databases share a connection pool" do - with_temporary_connection_pool do - ActiveRecord::Base.connects_to database: { writing: :arunit, reading: :arunit2 } - - rw_conn = ActiveRecord::Base.connection - ro_conn = ActiveRecord::Base.connection_handlers[:reading].connection_pool_list.first.connection - - assert_equal rw_conn, ro_conn - end - ensure - ActiveRecord::Base.connection_handlers = { writing: ActiveRecord::Base.connection_handler } - end - - private - def with_temporary_connection_pool - old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name) - new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new ActiveRecord::Base.connection_pool.spec - ActiveRecord::Base.connection_handler.send(:owner_to_pool)["primary"] = new_pool - - yield - ensure - ActiveRecord::Base.connection_handler.send(:owner_to_pool)["primary"] = old_pool - end -end - -class UsesWritingConnectionForFixtures < ActiveRecord::TestCase +class MultipleFixtureConnectionsTest < ActiveRecord::TestCase include ActiveRecord::TestFixtures - self.use_transactional_tests = true fixtures :dogs @@ -1391,7 +1364,7 @@ def setup db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(ENV["RAILS_ENV"], "readonly", readonly_config) handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new - handler.establish_connection(db_config) + handler.establish_connection(db_config.config) ActiveRecord::Base.connection_handlers = {} ActiveRecord::Base.connection_handler = handler ActiveRecord::Base.connects_to(database: { writing: :default, reading: :readonly }) @@ -1413,6 +1386,13 @@ def test_uses_writing_connection_for_fixtures end end + def test_writing_and_reading_connections_are_the_same + rw_conn = ActiveRecord::Base.connection_handlers[:writing].connection_pool_list.first.connection + ro_conn = ActiveRecord::Base.connection_handlers[:reading].connection_pool_list.first.connection + + assert_equal rw_conn, ro_conn + end + private def config { "default" => default_config, "readonly" => readonly_config } From 6a755d887aafd9ef566308196a81545117a2011f Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 13 May 2020 16:14:09 -0400 Subject: [PATCH 022/244] Only run on SQlite3 I can't for the life of me reproduce the failures occurring on buildkite but I beleive this is the fix. We need to only run this on sqlite3 because we are using a sqlite3 database. --- activerecord/test/cases/fixtures_test.rb | 84 ++++++++++++------------ 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 846c2a42bff5a..bf3a1e76af728 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -1352,57 +1352,59 @@ class NilFixturePathTest < ActiveRecord::TestCase end end -class MultipleFixtureConnectionsTest < ActiveRecord::TestCase - include ActiveRecord::TestFixtures +if current_adapter?(:SQLite3Adapter) && !in_memory_db? + class MultipleFixtureConnectionsTest < ActiveRecord::TestCase + include ActiveRecord::TestFixtures - fixtures :dogs + fixtures :dogs - def setup - @old_handler = ActiveRecord::Base.connection_handler - @old_handlers = ActiveRecord::Base.connection_handlers - @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config - db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(ENV["RAILS_ENV"], "readonly", readonly_config) - - handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new - handler.establish_connection(db_config.config) - ActiveRecord::Base.connection_handlers = {} - ActiveRecord::Base.connection_handler = handler - ActiveRecord::Base.connects_to(database: { writing: :default, reading: :readonly }) - end + def setup + @old_handler = ActiveRecord::Base.connection_handler + @old_handlers = ActiveRecord::Base.connection_handlers + @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config + db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(ENV["RAILS_ENV"], "readonly", readonly_config) + + handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new + handler.establish_connection(db_config.config) + ActiveRecord::Base.connection_handlers = {} + ActiveRecord::Base.connection_handler = handler + ActiveRecord::Base.connects_to(database: { writing: :default, reading: :readonly }) + end - def teardown - ActiveRecord::Base.configurations = @prev_configs - ActiveRecord::Base.connection_handler = @old_handler - ActiveRecord::Base.connection_handlers = @old_handlers - end + def teardown + ActiveRecord::Base.configurations = @prev_configs + ActiveRecord::Base.connection_handler = @old_handler + ActiveRecord::Base.connection_handlers = @old_handlers + end - def test_uses_writing_connection_for_fixtures - ActiveRecord::Base.connected_to(role: :reading) do - Dog.first + def test_uses_writing_connection_for_fixtures + ActiveRecord::Base.connected_to(role: :reading) do + Dog.first - assert_nothing_raised do - ActiveRecord::Base.connected_to(role: :writing) { Dog.create! alias: "Doggo" } + assert_nothing_raised do + ActiveRecord::Base.connected_to(role: :writing) { Dog.create! alias: "Doggo" } + end end end - end - def test_writing_and_reading_connections_are_the_same - rw_conn = ActiveRecord::Base.connection_handlers[:writing].connection_pool_list.first.connection - ro_conn = ActiveRecord::Base.connection_handlers[:reading].connection_pool_list.first.connection + def test_writing_and_reading_connections_are_the_same + rw_conn = ActiveRecord::Base.connection_handlers[:writing].connection_pool_list.first.connection + ro_conn = ActiveRecord::Base.connection_handlers[:reading].connection_pool_list.first.connection - assert_equal rw_conn, ro_conn - end - - private - def config - { "default" => default_config, "readonly" => readonly_config } + assert_equal rw_conn, ro_conn end - def default_config - { "adapter" => "sqlite3", "database" => "test/fixtures/fixture_database.sqlite3" } - end + private + def config + { "default" => default_config, "readonly" => readonly_config } + end - def readonly_config - default_config.merge("replica" => true) - end + def default_config + { "adapter" => "sqlite3", "database" => "test/fixtures/fixture_database.sqlite3" } + end + + def readonly_config + default_config.merge("replica" => true) + end + end end From f9ba52477ca288e7effa5f6794ae3df3f4e982bc Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 14 May 2020 06:22:50 +0900 Subject: [PATCH 023/244] Merge pull request #39268 from kamipo/fix_merging_multiple_left_joins Fix left joins order when merging multiple left joins from different associations --- .../lib/active_record/relation/merger.rb | 9 ++++++-- .../active_record/relation/query_methods.rb | 22 ++++++++++++------- .../left_outer_join_association_test.rb | 11 +++++++++- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb index e1735c0522824..27ecd4b25eab6 100644 --- a/activerecord/lib/active_record/relation/merger.rb +++ b/activerecord/lib/active_record/relation/merger.rb @@ -135,11 +135,16 @@ def merge_outer_joins if other.klass == relation.klass relation.left_outer_joins!(*other.left_outer_joins_values) else - associations = other.left_outer_joins_values + associations, others = other.left_outer_joins_values.partition do |join| + case join + when Hash, Symbol, Array; true + end + end + join_dependency = other.construct_join_dependency( associations, Arel::Nodes::OuterJoin ) - relation.joins!(join_dependency) + relation.left_outer_joins!(join_dependency, *others) end end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index ba4280ea9777f..c7ff9a0cbce1a 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1094,12 +1094,14 @@ def build_from end end - def select_association_list(associations) + def select_association_list(associations, stashed_joins = nil) result = [] associations.each do |association| case association when Hash, Symbol, Array result << association + when ActiveRecord::Associations::JoinDependency + stashed_joins&.<< association else yield if block_given? end @@ -1107,15 +1109,15 @@ def select_association_list(associations) result end - def valid_association_list(associations) - select_association_list(associations) do + def valid_association_list(associations, stashed_joins) + select_association_list(associations, stashed_joins) do raise ArgumentError, "only Hash, Symbol and Array are allowed" end end def build_left_outer_joins(manager, outer_joins, aliases) buckets = Hash.new { |h, k| h[k] = [] } - buckets[:association_join] = valid_association_list(outer_joins) + buckets[:association_join] = valid_association_list(outer_joins, buckets[:stashed_join]) build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases) end @@ -1123,12 +1125,13 @@ def build_joins(manager, joins, aliases) buckets = Hash.new { |h, k| h[k] = [] } unless left_outer_joins_values.empty? - left_joins = valid_association_list(left_outer_joins_values.flatten) - buckets[:stashed_join] << construct_join_dependency(left_joins, Arel::Nodes::OuterJoin) + stashed_left_joins = [] + left_joins = valid_association_list(left_outer_joins_values.flatten, stashed_left_joins) + stashed_left_joins.unshift construct_join_dependency(left_joins, Arel::Nodes::OuterJoin) end if joins.last.is_a?(ActiveRecord::Associations::JoinDependency) - buckets[:stashed_join] << joins.pop if joins.last.base_klass == klass + stashed_eager_load = joins.pop if joins.last.base_klass == klass end joins.map! do |join| @@ -1141,7 +1144,7 @@ def build_joins(manager, joins, aliases) while joins.first.is_a?(Arel::Nodes::Join) join_node = joins.shift - if join_node.is_a?(Arel::Nodes::StringJoin) && !buckets[:stashed_join].empty? + if join_node.is_a?(Arel::Nodes::StringJoin) && (stashed_eager_load || stashed_left_joins) buckets[:join_node] << join_node else buckets[:leading_join] << join_node @@ -1161,6 +1164,9 @@ def build_joins(manager, joins, aliases) end end + buckets[:stashed_join].concat stashed_left_joins if stashed_left_joins + buckets[:stashed_join] << stashed_eager_load if stashed_eager_load + build_join_query(manager, buckets, Arel::Nodes::InnerJoin, aliases) end diff --git a/activerecord/test/cases/associations/left_outer_join_association_test.rb b/activerecord/test/cases/associations/left_outer_join_association_test.rb index d44c6407f51dd..01daea7a0026d 100644 --- a/activerecord/test/cases/associations/left_outer_join_association_test.rb +++ b/activerecord/test/cases/associations/left_outer_join_association_test.rb @@ -3,6 +3,7 @@ require "cases/helper" require "models/post" require "models/comment" +require "models/rating" require "models/author" require "models/essay" require "models/category" @@ -10,7 +11,15 @@ require "models/person" class LeftOuterJoinAssociationTest < ActiveRecord::TestCase - fixtures :authors, :author_addresses, :essays, :posts, :comments, :categorizations, :people + fixtures :authors, :author_addresses, :essays, :posts, :comments, :ratings, :categorizations, :people + + def test_merging_multiple_left_joins_from_different_associations + count = Author.joins(:posts).merge(Post.left_joins(:comments).merge(Comment.left_joins(:ratings))).count + assert_equal 16, count + + count = Author.left_joins(:posts).merge(Post.left_joins(:comments).merge(Comment.left_joins(:ratings))).count + assert_equal 16, count + end def test_construct_finder_sql_applies_aliases_tables_on_association_conditions result = Author.left_outer_joins(:thinking_posts, :welcome_posts).to_a From 9981f5225f03c6f2c33b20def6f8cb45d3fe36c6 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 15 May 2020 05:39:31 +0900 Subject: [PATCH 024/244] Merge pull request #39280 from kamipo/bypass_argument_forwording_issue Allow define scope for Ruby reserved keywords --- activerecord/lib/active_record/relation/delegation.rb | 3 ++- activerecord/test/cases/scoping/named_scoping_test.rb | 5 +++++ activerecord/test/models/topic.rb | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index 4c2b413a81b17..1c5fb3cdf33a4 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "mutex_m" +require "active_support/core_ext/module/delegation" module ActiveRecord module Delegation # :nodoc: @@ -59,7 +60,7 @@ def generate_method(method) synchronize do return if method_defined?(method) - if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method) + if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method) && !DELEGATION_RESERVED_METHOD_NAMES.include?(method.to_s) definition = RUBY_VERSION >= "2.7" ? "..." : "*args, &block" module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{method}(#{definition}) diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb index 2c2e86eb66138..e41cc46cced45 100644 --- a/activerecord/test/cases/scoping/named_scoping_test.rb +++ b/activerecord/test/cases/scoping/named_scoping_test.rb @@ -64,6 +64,11 @@ def test_method_missing_priority_when_delegating assert_equal klazz.to.since.to_a, klazz.since.to.to_a end + def test_define_scope_for_reserved_words + assert Topic.true.all?(&:approved?), "all objects should be approved" + assert Topic.false.none?(&:approved?), "all objects should not be approved" + end + def test_scope_should_respond_to_own_methods_and_methods_of_the_proxy assert_respond_to Topic.approved, :limit assert_respond_to Topic.approved, :count diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 4da28cb1489ec..49ebe65a7fbf1 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -10,6 +10,9 @@ class Topic < ActiveRecord::Base scope :approved, -> { where(approved: true) } scope :rejected, -> { where(approved: false) } + scope :true, -> { where(approved: true) } + scope :false, -> { where(approved: false) } + scope :scope_with_lambda, lambda { all } scope :by_lifo, -> { where(author_name: "lifo") } From f7fbd31e82f688da479382f95fe3ca10ec730d64 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sat, 16 May 2020 18:42:26 +0900 Subject: [PATCH 025/244] Merge pull request #39297 from kamipo/fix_group_by_order_and_limit_offset Fix group by count with eager loading + order + limit/offset --- .../lib/active_record/relation/calculations.rb | 2 +- activerecord/test/cases/calculations_test.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 114ac4c9ef467..ab74e5917c1a7 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -134,7 +134,7 @@ def calculate(operation, column_name) relation.select_values = [ klass.primary_key || table[Arel.star] ] end # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT - relation.order_values = [] + relation.order_values = [] if group_values.empty? end relation.calculate(operation, column_name) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 963bd2327a61f..825e23ec2337f 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -817,20 +817,20 @@ def test_group_by_with_order_by_virtual_count_attribute end if current_adapter?(:PostgreSQLAdapter) def test_group_by_with_limit - expected = { "Post" => 8, "SpecialPost" => 1 } - actual = Post.includes(:comments).group(:type).order(:type).limit(2).count("comments.id") + expected = { "StiPost" => 2, "SpecialPost" => 1 } + actual = Post.includes(:comments).group(:type).order(type: :desc).limit(2).count("comments.id") assert_equal expected, actual end def test_group_by_with_offset - expected = { "SpecialPost" => 1, "StiPost" => 2 } - actual = Post.includes(:comments).group(:type).order(:type).offset(1).count("comments.id") + expected = { "SpecialPost" => 1, "Post" => 8 } + actual = Post.includes(:comments).group(:type).order(type: :desc).offset(1).count("comments.id") assert_equal expected, actual end def test_group_by_with_limit_and_offset expected = { "SpecialPost" => 1 } - actual = Post.includes(:comments).group(:type).order(:type).offset(1).limit(1).count("comments.id") + actual = Post.includes(:comments).group(:type).order(type: :desc).offset(1).limit(1).count("comments.id") assert_equal expected, actual end From 734bb308ed198bdf279113fbc1900e75713989ae Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sat, 16 May 2020 18:42:54 +0900 Subject: [PATCH 026/244] Merge pull request #39305 from kamipo/fix_eager_load_with_arel_joins Fix eager load with Arel joins to maintain the original joins order --- .../lib/active_record/associations/association_scope.rb | 2 +- activerecord/lib/active_record/relation/query_methods.rb | 5 ++++- .../cases/associations/inner_join_association_test.rb | 9 +++++++++ .../associations/left_outer_join_association_test.rb | 9 +++++++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index 9e38380611352..3f8d3c5f055ca 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -52,7 +52,7 @@ def self.get_bind_values(owner, chain) attr_reader :value_transformation def join(table, constraint) - table.create_join(table, table.create_on(constraint)) + table.create_join(table, table.create_on(constraint), Arel::Nodes::LeadingJoin) end def last_chain_scope(scope, reflection, owner) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index c7ff9a0cbce1a..18328dd17033f 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1121,6 +1121,9 @@ def build_left_outer_joins(manager, outer_joins, aliases) build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases) end + class ::Arel::Nodes::LeadingJoin < Arel::Nodes::InnerJoin # :nodoc: + end + def build_joins(manager, joins, aliases) buckets = Hash.new { |h, k| h[k] = [] } @@ -1144,7 +1147,7 @@ def build_joins(manager, joins, aliases) while joins.first.is_a?(Arel::Nodes::Join) join_node = joins.shift - if join_node.is_a?(Arel::Nodes::StringJoin) && (stashed_eager_load || stashed_left_joins) + if !join_node.is_a?(Arel::Nodes::LeadingJoin) && (stashed_eager_load || stashed_left_joins) buckets[:join_node] << join_node else buckets[:leading_join] << join_node diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index 1ec349aa73487..d2aa601ca88f4 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -87,6 +87,15 @@ def test_eager_load_with_string_joins assert_equal 3, Person.eager_load(:agents).joins(string_join).count end + def test_eager_load_with_arel_joins + agents = Person.arel_table.alias("agents_people") + agents_2 = Person.arel_table.alias("agents_people_2") + constraint = agents[:primary_contact_id].eq(agents_2[:id]).and(agents[:id].gt(agents_2[:id])) + arel_join = agents.create_join(agents, agents.create_on(constraint), Arel::Nodes::OuterJoin) + + assert_equal 3, Person.eager_load(:agents).joins(arel_join).count + end + def test_construct_finder_sql_ignores_empty_joins_hash sql = Author.joins({}).to_sql assert_no_match(/JOIN/i, sql) diff --git a/activerecord/test/cases/associations/left_outer_join_association_test.rb b/activerecord/test/cases/associations/left_outer_join_association_test.rb index 01daea7a0026d..4843cc9f8abcc 100644 --- a/activerecord/test/cases/associations/left_outer_join_association_test.rb +++ b/activerecord/test/cases/associations/left_outer_join_association_test.rb @@ -83,6 +83,15 @@ def test_left_outer_joins_with_string_join assert_equal 16, Author.left_outer_joins(:posts).joins("LEFT OUTER JOIN comments ON comments.post_id = posts.id").count end + def test_left_outer_joins_with_arel_join + comments = Comment.arel_table + posts = Post.arel_table + constraint = comments[:post_id].eq(posts[:id]) + arel_join = comments.create_join(comments, comments.create_on(constraint), Arel::Nodes::OuterJoin) + + assert_equal 16, Author.left_outer_joins(:posts).joins(arel_join).count + end + def test_join_conditions_added_to_join_clause queries = capture_sql { Author.left_outer_joins(:essays).to_a } assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1|\:a1)/i.match?(sql) } From 185f935b188606108a7b19817e58153fd81f424d Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 14 May 2020 20:48:17 +0900 Subject: [PATCH 027/244] Merge pull request #39281 from kamipo/fix_rename_index_on_fk Update `supports_rename_index?` version for MariaDB --- .../connection_adapters/abstract_mysql_adapter.rb | 6 +++++- activerecord/test/cases/migration/foreign_key_test.rb | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 53e525dacd453..e0bd8f2f176c6 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -687,7 +687,11 @@ def remove_index_for_alter(table_name, options = {}) end def supports_rename_index? - mariadb? ? false : database_version >= "5.7.6" + if mariadb? + database_version >= "10.5.2" + else + database_version >= "5.7.6" + end end def configure_connection diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index 8b1b54c4ab5a6..0bedb2f5efc94 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -93,6 +93,10 @@ def test_rename_column_of_child_table end def test_rename_reference_column_of_child_table + if current_adapter?(:Mysql2Adapter) && !@connection.send(:supports_rename_index?) + skip "Cannot drop index, needed in a foreign key constraint" + end + rocket = Rocket.create!(name: "myrocket") rocket.astronauts << Astronaut.create! From c24c4e49b79b727efdd0860b97f55d7edcf4cf01 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 19 May 2020 02:56:09 +0900 Subject: [PATCH 028/244] Fix `test_two_classes_autoloading` failure That test requires Marshal is prepended by `MarshalWithAutoloading`. --- activesupport/lib/active_support/cache/mem_cache_store.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index fc1c1c8aa8db3..bf81c4270d5b4 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -7,6 +7,7 @@ raise e end +require "active_support/core_ext/marshal" require "active_support/core_ext/array/extract_options" module ActiveSupport From 129f6aa5698e6860ff6b2f8e19c61ce8d5cae4c2 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Tue, 19 May 2020 20:47:14 +0100 Subject: [PATCH 029/244] Merge pull request #39355 from blaze182/patch-1 Update aws-sdk-s3 dependency --- activestorage/lib/active_storage/service/s3_service.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/activestorage/lib/active_storage/service/s3_service.rb b/activestorage/lib/active_storage/service/s3_service.rb index 5349302c1c732..816829054d54a 100644 --- a/activestorage/lib/active_storage/service/s3_service.rb +++ b/activestorage/lib/active_storage/service/s3_service.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +gem "aws-sdk-s3", "~> 1.48" + require "aws-sdk-s3" require "active_support/core_ext/numeric/bytes" From 06b9e98e4a1b6bcd6e2f0174cccfcc8f7b33a966 Mon Sep 17 00:00:00 2001 From: Kasper Timm Hansen Date: Fri, 7 Feb 2020 01:39:39 +0100 Subject: [PATCH 030/244] Merge pull request #37468 Closes #37468 --- activesupport/lib/active_support/deprecation/proxy_wrappers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb index b6b32e2025f56..913f8765cb53e 100644 --- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb @@ -147,7 +147,7 @@ def inspect # Don't give a deprecation warning on methods that IRB may invoke # during tab-completion. - delegate :hash, :instance_methods, :name, to: :target + delegate :hash, :instance_methods, :name, :respond_to?, to: :target # Returns the class of the new constant. # From 9366f528b2d7fc18e4836b670fddcc75ea450333 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Wed, 20 May 2020 02:12:41 +0100 Subject: [PATCH 031/244] Merge pull request #39316 from alipman88/resolve_counter_cache_lock_version_conflict Resolve conflict between counter cache and optimistic locking --- activerecord/CHANGELOG.md | 11 +++++++++++ activerecord/lib/active_record/locking/optimistic.rb | 9 +++++++++ activerecord/test/cases/locking_test.rb | 6 ++++++ 3 files changed, 26 insertions(+) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index dd1e9bdb6bca7..49b7a4e409494 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,14 @@ +* Resolve conflict between counter cache and optimistic locking. + + Bump an Active Record instance's lock version after updating its counter + cache. This avoids raising an unnecessary `ActiveRecord::StaleObjectError` + upon subsequent transactions by maintaining parity with the corresponding + database record's `lock_version` column. + + Fixes #16449. + + *Aaron Lipman* + * Fix index creation to preserve index comment in bulk change table on MySQL. *Ryuta Kamizono* diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index c2a083bf3b31d..5dcebedc1f7db 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -60,6 +60,15 @@ def locking_enabled? #:nodoc: self.class.locking_enabled? end + def increment!(*, **) #:nodoc: + super.tap do + if locking_enabled? + self[self.class.locking_column] += 1 + clear_attribute_change(self.class.locking_column) + end + end + end + private def _create_record(attribute_names = self.attribute_names) if locking_enabled? diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index b468da7c7663a..f2b1062eb8ceb 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -486,6 +486,12 @@ def test_counter_cache_with_touch_and_lock_version assert_equal 3, car.lock_version assert_operator previously_updated_at, :<, car.updated_at assert_operator previously_wheels_owned_at, :<, car.wheels_owned_at + + car.wheels << Wheel.create! + assert_equal 1, car.wheels_count + assert_equal 4, car.lock_version + assert_not car.lock_version_changed? + assert_nothing_raised { car.update(name: "herbie") } end def test_polymorphic_destroy_with_dependencies_and_lock_version From 39de1156970d52b441ff944862ebe16a47de784f Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 20 May 2020 22:12:02 +0900 Subject: [PATCH 032/244] `loaded` should be aliased to `loaded?` in collection proxy Fixes #39088. --- .../lib/active_record/associations/collection_proxy.rb | 1 + activerecord/test/cases/associations_test.rb | 2 ++ activerecord/test/cases/relations_test.rb | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 627c78545ef0e..0a8ca4368bed5 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -51,6 +51,7 @@ def load_target def loaded? @association.loaded? end + alias :loaded :loaded? ## # :method: select diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb index 84130ec208da4..cefb43a8b5ff2 100644 --- a/activerecord/test/cases/associations_test.rb +++ b/activerecord/test/cases/associations_test.rb @@ -269,8 +269,10 @@ def test_reset_unloads_target david.posts.reload assert_predicate david.posts, :loaded? + assert_predicate david.posts, :loaded david.posts.reset assert_not_predicate david.posts, :loaded? + assert_not_predicate david.posts, :loaded end end diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 6f5a354eeade3..c01dab5751275 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -93,11 +93,15 @@ def test_scoped_all def test_loaded_all topics = Topic.all + assert_not_predicate topics, :loaded? + assert_not_predicate topics, :loaded + assert_queries(1) do 2.times { assert_equal 5, topics.to_a.size } end assert_predicate topics, :loaded? + assert_predicate topics, :loaded end def test_scoped_first From 72c73c3ed84650f7a8585866d24c1ce909438ce6 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 1 May 2020 15:00:01 +0900 Subject: [PATCH 033/244] Fix random CI failure due to non-deterministic order https://buildkite.com/rails/rails/builds/68559#2decc846-c6b5-46f7-a805-426a8063d36c/1016-1027 --- .../nested_through_associations_test.rb | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index 8d74ae396165a..1205d5c741ef1 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -62,11 +62,11 @@ def test_has_many_through_has_many_with_has_many_through_source_reflection end def test_has_many_through_has_many_with_has_many_through_source_reflection_preload - authors = assert_queries(5) { Author.includes(:tags).to_a } + author = assert_queries(5) { Author.includes(:tags).first } general = tags(:general) assert_no_queries do - assert_equal [general, general], authors.first.tags + assert_equal [general, general], author.tags end end @@ -91,9 +91,9 @@ def test_has_many_through_has_many_through_with_has_many_source_reflection def test_has_many_through_has_many_through_with_has_many_source_reflection_preload luke, david = subscribers(:first), subscribers(:second) - authors = assert_queries(4) { Author.includes(:subscribers).to_a } + author = assert_queries(4) { Author.includes(:subscribers).first } assert_no_queries do - assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick) + assert_equal [luke, david, david], author.subscribers.sort_by(&:nick) end end @@ -113,10 +113,10 @@ def test_has_many_through_has_one_with_has_one_through_source_reflection end def test_has_many_through_has_one_with_has_one_through_source_reflection_preload - members = assert_queries(4) { Member.includes(:nested_member_types).to_a } + member = assert_queries(4) { Member.includes(:nested_member_types).first } founding = member_types(:founding) assert_no_queries do - assert_equal [founding], members.first.nested_member_types + assert_equal [founding], member.nested_member_types end end @@ -135,10 +135,10 @@ def test_has_many_through_has_one_through_with_has_one_source_reflection end def test_has_many_through_has_one_through_with_has_one_source_reflection_preload - members = assert_queries(4) { Member.includes(:nested_sponsors).to_a } + member = assert_queries(4) { Member.includes(:nested_sponsors).first } mustache = sponsors(:moustache_club_sponsor_for_groucho) assert_no_queries do - assert_equal [mustache], members.first.nested_sponsors + assert_equal [mustache], member.nested_sponsors end end @@ -161,11 +161,11 @@ def test_has_many_through_has_one_with_has_many_through_source_reflection def test_has_many_through_has_one_with_has_many_through_source_reflection_preload ActiveRecord::Base.connection.table_alias_length # preheat cache - members = assert_queries(4) { Member.includes(:organization_member_details).to_a.sort_by(&:id) } + member = assert_queries(4) { Member.includes(:organization_member_details).first } groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) assert_no_queries do - assert_equal [groucho_details, other_details], members.first.organization_member_details.sort_by(&:id) + assert_equal [groucho_details, other_details], member.organization_member_details.sort_by(&:id) end end @@ -175,8 +175,7 @@ def test_has_many_through_has_one_with_has_many_through_source_reflection_preloa [members(:groucho), members(:some_other_guy)], :organization_member_details ) - members = Member.joins(:organization_member_details). - where("member_details.id" => 9) + members = Member.joins(:organization_member_details).where("member_details.id" => 9) assert_empty members end @@ -191,13 +190,13 @@ def test_has_many_through_has_one_through_with_has_many_source_reflection end def test_has_many_through_has_one_through_with_has_many_source_reflection_preload - members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a.sort_by(&:id) } + member = assert_queries(4) { Member.includes(:organization_member_details_2).first } groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) # postgresql test if randomly executed then executes "SHOW max_identifier_length". Hence # the need to ignore certain predefined sqls that deal with system calls. assert_no_queries do - assert_equal [groucho_details, other_details], members.first.organization_member_details_2.sort_by(&:id) + assert_equal [groucho_details, other_details], member.organization_member_details_2.sort_by(&:id) end end @@ -207,8 +206,7 @@ def test_has_many_through_has_one_through_with_has_many_source_reflection_preloa [members(:groucho), members(:some_other_guy)], :organization_member_details_2 ) - members = Member.joins(:organization_member_details_2). - where("member_details.id" => 9) + members = Member.joins(:organization_member_details_2).where("member_details.id" => 9) assert_empty members end @@ -222,11 +220,11 @@ def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflectio end def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection_preload - authors = assert_queries(4) { Author.includes(:post_categories).to_a.sort_by(&:id) } + author = assert_queries(4) { Author.includes(:post_categories).third } general, cooking = categories(:general), categories(:cooking) assert_no_queries do - assert_equal [general, cooking], authors[2].post_categories.sort_by(&:id) + assert_equal [general, cooking], author.post_categories.sort_by(&:id) end end @@ -251,11 +249,11 @@ def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflectio def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload Category.includes(:post_comments).to_a # preheat cache - categories = assert_queries(4) { Category.includes(:post_comments).to_a.sort_by(&:id) } + category = assert_queries(4) { Category.includes(:post_comments).second } greetings, more = comments(:greetings), comments(:more_greetings) assert_no_queries do - assert_equal [greetings, more], categories[1].post_comments.sort_by(&:id) + assert_equal [greetings, more], category.post_comments.sort_by(&:id) end end @@ -279,11 +277,11 @@ def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection end def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload - authors = assert_queries(6) { Author.includes(:category_post_comments).to_a.sort_by(&:id) } + author = assert_queries(6) { Author.includes(:category_post_comments).third } greetings, more = comments(:greetings), comments(:more_greetings) assert_no_queries do - assert_equal [greetings, more], authors[2].category_post_comments.sort_by(&:id) + assert_equal [greetings, more], author.category_post_comments.sort_by(&:id) end end @@ -305,11 +303,11 @@ def test_has_many_through_has_many_through_with_belongs_to_source_reflection end def test_has_many_through_has_many_through_with_belongs_to_source_reflection_preload - authors = assert_queries(5) { Author.includes(:tagging_tags).to_a } + author = assert_queries(5) { Author.includes(:tagging_tags).first } general = tags(:general) assert_no_queries do - assert_equal [general, general], authors.first.tagging_tags + assert_equal [general, general], author.tagging_tags end end @@ -331,11 +329,11 @@ def test_has_many_through_belongs_to_with_has_many_through_source_reflection end def test_has_many_through_belongs_to_with_has_many_through_source_reflection_preload - categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a.sort_by(&:id) } + categorization = assert_queries(4) { Categorization.includes(:post_taggings).first } welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general) assert_no_queries do - assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings.sort_by(&:id) + assert_equal [welcome_general, thinking_general], categorization.post_taggings.sort_by(&:id) end end @@ -354,11 +352,11 @@ def test_has_one_through_has_one_with_has_one_through_source_reflection end def test_has_one_through_has_one_with_has_one_through_source_reflection_preload - members = assert_queries(4) { Member.includes(:nested_member_type).to_a.sort_by(&:id) } + member = assert_queries(4) { Member.includes(:nested_member_type).first } founding = member_types(:founding) assert_no_queries do - assert_equal founding, members.first.nested_member_type + assert_equal founding, member.nested_member_type end end @@ -388,11 +386,11 @@ def test_joins_and_includes_from_through_models_not_included_in_association end def test_has_one_through_has_one_through_with_belongs_to_source_reflection_preload - members = assert_queries(4) { Member.includes(:club_category).to_a.sort_by(&:id) } + member = assert_queries(4) { Member.includes(:club_category).first } general = categories(:general) assert_no_queries do - assert_equal general, members.first.club_category + assert_equal general, member.club_category end end @@ -519,11 +517,11 @@ def test_nested_has_many_through_with_conditions_on_through_associations def test_nested_has_many_through_with_conditions_on_through_associations_preload assert_empty Author.where("tags.id" => 100).joins(:misc_post_first_blue_tags) - authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a.sort_by(&:id) } + author = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).third } blue = tags(:blue) assert_no_queries do - assert_equal [blue], authors[2].misc_post_first_blue_tags + assert_equal [blue], author.misc_post_first_blue_tags end end @@ -540,20 +538,20 @@ def test_nested_has_many_through_with_conditions_on_source_associations end def test_nested_has_many_through_with_conditions_on_source_associations_preload - authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) } + author = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).third } blue = tags(:blue) assert_no_queries do - assert_equal [blue], authors[2].misc_post_first_blue_tags_2 + assert_equal [blue], author.misc_post_first_blue_tags_2 end end def test_through_association_preload_doesnt_reset_source_association_if_already_preloaded blue = tags(:blue) - authors = Author.preload(posts: :first_blue_tags_2, misc_post_first_blue_tags_2: {}).to_a.sort_by(&:id) + author = Author.preload(posts: :first_blue_tags_2, misc_post_first_blue_tags_2: {}).third assert_no_queries do - assert_equal [blue], authors[2].posts.first.first_blue_tags_2 + assert_equal [blue], author.posts.first.first_blue_tags_2 end end @@ -627,6 +625,8 @@ def test_has_many_through_reset_source_reflection_after_loading_is_complete private def assert_includes_and_joins_equal(query, expected, association) + query = query.order(:id) + actual = assert_queries(1) { query.joins(association).to_a.uniq } assert_equal expected, actual From a415e804279c21b4dfbeb877ec0e40c12c2c8886 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 21 May 2020 20:30:13 +0900 Subject: [PATCH 034/244] Merge pull request #39378 from kamipo/fix_has_many_through_with_source_scope Fix through association to respect source scope for `includes`/`preload` --- .../lib/active_record/associations/preloader/association.rb | 6 ++++-- .../associations/has_many_through_associations_test.rb | 6 ++++++ .../cases/associations/nested_through_associations_test.rb | 4 ++-- activerecord/test/models/author.rb | 2 ++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 78ba6324a1d9a..692d9cf37fc81 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -113,7 +113,9 @@ def scope end def reflection_scope - @reflection_scope ||= reflection.scope ? reflection.scope_for(klass.unscoped) : klass.unscoped + @reflection_scope ||= begin + reflection.join_scopes(klass.arel_table, klass.predicate_builder).inject(klass.unscoped, &:merge!) + end end def build_scope @@ -123,7 +125,7 @@ def build_scope scope.where!(reflection.type => model.polymorphic_name) end - scope.merge!(reflection_scope) if reflection.scope + scope.merge!(reflection_scope) unless reflection_scope.empty_scope? scope.merge!(preload_scope) if preload_scope scope end diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index ed90cc4c8ef35..1dc8afaa27f6d 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -1051,6 +1051,12 @@ def test_can_update_through_association end end + def test_has_many_through_with_source_scope + expected = [readers(:michael_welcome).becomes(LazyReader)] + assert_equal expected, Author.preload(:lazy_readers_skimmers_or_not).first.lazy_readers_skimmers_or_not + assert_equal expected, Author.eager_load(:lazy_readers_skimmers_or_not).first.lazy_readers_skimmers_or_not + end + def test_has_many_through_polymorphic_with_rewhere post = TaggedPost.create!(title: "Tagged", body: "Post") tag = post.tags.create!(name: "Tag") diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index 1205d5c741ef1..1f649ca0a214f 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -517,7 +517,7 @@ def test_nested_has_many_through_with_conditions_on_through_associations def test_nested_has_many_through_with_conditions_on_through_associations_preload assert_empty Author.where("tags.id" => 100).joins(:misc_post_first_blue_tags) - author = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).third } + author = assert_queries(2) { Author.includes(:misc_post_first_blue_tags).third } blue = tags(:blue) assert_no_queries do @@ -538,7 +538,7 @@ def test_nested_has_many_through_with_conditions_on_source_associations end def test_nested_has_many_through_with_conditions_on_source_associations_preload - author = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).third } + author = assert_queries(2) { Author.includes(:misc_post_first_blue_tags_2).third } blue = tags(:blue) assert_no_queries do diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index fef36712538ec..71806b681a4ec 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -171,6 +171,8 @@ def extension_method; end has_many :top_posts, -> { order(id: :asc) }, class_name: "Post" has_many :other_top_posts, -> { order(id: :asc) }, class_name: "Post" + has_many :lazy_readers_skimmers_or_not, through: :posts + attr_accessor :post_log after_initialize :set_post_log From ca5770463c4f27ee1526394987b7ed4087d31b32 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sun, 24 May 2020 02:20:00 +0900 Subject: [PATCH 035/244] Merge pull request #39390 from kamipo/fix_has_many_through_with_join_scope Fix through association with source/through scope which has joins --- .../lib/active_record/associations/association_scope.rb | 6 ++++++ .../associations/join_dependency/join_association.rb | 7 +++++++ .../lib/active_record/associations/through_association.rb | 2 +- activerecord/lib/active_record/relation/finder_methods.rb | 2 +- .../associations/has_many_through_associations_test.rb | 8 ++++++++ activerecord/test/fixtures/readers.yml | 6 ++++++ activerecord/test/models/author.rb | 1 + 7 files changed, 30 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index 3f8d3c5f055ca..f653068484e7e 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -134,6 +134,12 @@ def add_constraints(scope, owner, chain) if scope_chain_item == chain_head.scope scope.merge! item.except(:where, :includes, :unscope, :order) + elsif !item.references_values.empty? + join_dependency = item.construct_join_dependency( + item.eager_load_values | item.includes_values, Arel::Nodes::OuterJoin + ) + scope.joins!(*item.joins_values, join_dependency) + scope.left_outer_joins!(*item.left_outer_joins_values) end reflection.all_includes do diff --git a/activerecord/lib/active_record/associations/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/join_dependency/join_association.rb index 3615e0c6c3f17..be8bb0fda141f 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb @@ -33,6 +33,13 @@ def join_constraints(foreign_table, foreign_klass, join_type, alias_tracker) join_scope = reflection.join_scope(table, foreign_table, foreign_klass) + unless join_scope.references_values.empty? + join_dependency = join_scope.construct_join_dependency( + join_scope.eager_load_values | join_scope.includes_values, Arel::Nodes::OuterJoin + ) + join_scope.joins!(join_dependency) + end + arel = join_scope.arel(alias_tracker.aliases) nodes = arel.constraints.first diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index 15e6565e69889..3f5e9066eb925 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -32,7 +32,7 @@ def target_scope reflection.chain.drop(1).each do |reflection| relation = reflection.klass.scope_for_association scope.merge!( - relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load) + relation.except(:select, :create_with, :includes, :preload, :eager_load, :joins, :left_outer_joins) ) end scope diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index b356e9f391db0..433fc96a622b5 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -371,7 +371,7 @@ def construct_relation_for_exists(conditions) def apply_join_dependency(eager_loading: group_values.empty?) join_dependency = construct_join_dependency( - eager_load_values + includes_values, Arel::Nodes::OuterJoin + eager_load_values | includes_values, Arel::Nodes::OuterJoin ) relation = except(:includes, :eager_load, :preload).joins!(join_dependency) diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 1dc8afaa27f6d..f673e8a20abe6 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -1053,10 +1053,18 @@ def test_can_update_through_association def test_has_many_through_with_source_scope expected = [readers(:michael_welcome).becomes(LazyReader)] + assert_equal expected, Author.first.lazy_readers_skimmers_or_not assert_equal expected, Author.preload(:lazy_readers_skimmers_or_not).first.lazy_readers_skimmers_or_not assert_equal expected, Author.eager_load(:lazy_readers_skimmers_or_not).first.lazy_readers_skimmers_or_not end + def test_has_many_through_with_join_scope + expected = [readers(:bob_welcome).becomes(LazyReader)] + assert_equal expected, Author.last.lazy_readers_skimmers_or_not_2 + assert_equal expected, Author.preload(:lazy_readers_skimmers_or_not_2).last.lazy_readers_skimmers_or_not_2 + assert_equal expected, Author.eager_load(:lazy_readers_skimmers_or_not_2).last.lazy_readers_skimmers_or_not_2 + end + def test_has_many_through_polymorphic_with_rewhere post = TaggedPost.create!(title: "Tagged", body: "Post") tag = post.tags.create!(name: "Tag") diff --git a/activerecord/test/fixtures/readers.yml b/activerecord/test/fixtures/readers.yml index 14b883f041046..246d94ffaa220 100644 --- a/activerecord/test/fixtures/readers.yml +++ b/activerecord/test/fixtures/readers.yml @@ -9,3 +9,9 @@ michael_authorless: post_id: 3 person_id: 1 first_post_id: 3 + +bob_welcome: + id: 3 + post_id: 8 + person_id: 4 + first_post_id: 10 diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index 71806b681a4ec..6b7522eb179e8 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -172,6 +172,7 @@ def extension_method; end has_many :other_top_posts, -> { order(id: :asc) }, class_name: "Post" has_many :lazy_readers_skimmers_or_not, through: :posts + has_many :lazy_readers_skimmers_or_not_2, through: :posts_with_no_comments, source: :lazy_readers_skimmers_or_not attr_accessor :post_log after_initialize :set_post_log From d63c53606207116bc7ea5f6124377ae76e93d09b Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sun, 24 May 2020 00:20:44 +0100 Subject: [PATCH 036/244] Merge pull request #39407 from eugeneius/with_options_dup_options Copy options before delegating in with_options --- activesupport/CHANGELOG.md | 7 +++++++ activesupport/lib/active_support/option_merger.rb | 2 +- activesupport/test/option_merger_test.rb | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index d772ba68b78d8..8cc0df1333953 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,10 @@ +* `with_options` copies its options hash again to avoid leaking mutations. + + Fixes #39343. + + *Eugene Kenny* + + ## Rails 6.0.3.1 (May 18, 2020) ## * [CVE-2020-8165] Deprecate Marshal.load on raw cache read in RedisCacheStore diff --git a/activesupport/lib/active_support/option_merger.rb b/activesupport/lib/active_support/option_merger.rb index a4f40b02a4ff9..c3b45baea3408 100644 --- a/activesupport/lib/active_support/option_merger.rb +++ b/activesupport/lib/active_support/option_merger.rb @@ -37,7 +37,7 @@ def invoke_method(method, arguments, options, &block) end else def invoke_method(method, arguments, options, &block) - arguments << options if options + arguments << options.dup if options @context.__send__(method, *arguments, &block) end end diff --git a/activesupport/test/option_merger_test.rb b/activesupport/test/option_merger_test.rb index 77cf9972f539f..bf6a3a4af577f 100644 --- a/activesupport/test/option_merger_test.rb +++ b/activesupport/test/option_merger_test.rb @@ -37,6 +37,12 @@ def test_method_with_options_appends_options_when_options_are_missing end end + def test_method_with_options_copies_options_when_options_are_missing + with_options(@options) do |o| + assert_not_same @options, o.method_with_options + end + end + def test_method_with_options_allows_to_overwrite_options local_options = { hello: "moon" } assert_equal @options.keys, local_options.keys From c382efda9ddcd0ce183ab731d0c6f99f1bf5f7dd Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sun, 24 May 2020 23:27:38 +0900 Subject: [PATCH 037/244] Merge pull request #38172 from sinsoku/or_with_annotate Allow relations with different SQL comments in the `or` method --- .../active_record/relation/query_methods.rb | 2 +- .../adapters/mysql2/optimizer_hints_test.rb | 21 +++++++++++++++++++ .../postgresql/optimizer_hints_test.rb | 19 +++++++++++++++++ activerecord/test/cases/relation/or_test.rb | 8 +++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 18328dd17033f..7be8fcb69af9b 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1365,7 +1365,7 @@ def check_if_method_has_arguments!(method_name, args) end end - STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references] + STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references, :annotate, :optimizer_hints] def structurally_incompatible_values_for_or(other) values = other.values STRUCTURAL_OR_METHODS.reject do |method| diff --git a/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb b/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb index 628802b216d91..d043b3c72604f 100644 --- a/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb +++ b/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb @@ -44,5 +44,26 @@ def test_optimizer_hints_with_unscope posts.unscope(:optimizer_hints).load end end + + def test_optimizer_hints_with_or + assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do + Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)") + .or(Post.all).load + end + + queries = capture_sql do + Post.optimizer_hints("NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)") + .or(Post.optimizer_hints("NO_ICP(posts)")).load + end + assert_equal 1, queries.length + assert_includes queries.first, "NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id)" + assert_not_includes queries.first, "NO_ICP(posts)" + + queries = capture_sql do + Post.all.or(Post.optimizer_hints("NO_ICP(posts)")).load + end + assert_equal 1, queries.length + assert_not_includes queries.first, "NO_ICP(posts)" + end end end diff --git a/activerecord/test/cases/adapters/postgresql/optimizer_hints_test.rb b/activerecord/test/cases/adapters/postgresql/optimizer_hints_test.rb index 5b9f5e08324ce..1e27cf87e85f9 100644 --- a/activerecord/test/cases/adapters/postgresql/optimizer_hints_test.rb +++ b/activerecord/test/cases/adapters/postgresql/optimizer_hints_test.rb @@ -48,5 +48,24 @@ def test_optimizer_hints_with_unscope posts.unscope(:optimizer_hints).load end end + + def test_optimizer_hints_with_or + assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do + Post.optimizer_hints("SeqScan(posts)").or(Post.all).load + end + + queries = capture_sql do + Post.optimizer_hints("SeqScan(posts)").or(Post.optimizer_hints("IndexScan(posts)")).load + end + assert_equal 1, queries.length + assert_includes queries.first, "/*+ SeqScan(posts) */" + assert_not_includes queries.first, "/*+ IndexScan(posts) */" + + queries = capture_sql do + Post.all.or(Post.optimizer_hints("IndexScan(posts)")).load + end + assert_equal 1, queries.length + assert_not_includes queries.first, "/*+ IndexScan(posts) */" + end end end diff --git a/activerecord/test/cases/relation/or_test.rb b/activerecord/test/cases/relation/or_test.rb index 95375eb4eeba5..26fe7adf8f421 100644 --- a/activerecord/test/cases/relation/or_test.rb +++ b/activerecord/test/cases/relation/or_test.rb @@ -139,6 +139,14 @@ def test_or_with_scope_on_association end end + def test_or_with_annotate + quoted_posts = Regexp.escape(Post.quoted_table_name) + assert_match %r{#{quoted_posts} /\* foo \*/\z}, Post.annotate("foo").or(Post.all).to_sql + assert_match %r{#{quoted_posts} /\* foo \*/\z}, Post.annotate("foo").or(Post.annotate("foo")).to_sql + assert_match %r{#{quoted_posts} /\* foo \*/\z}, Post.annotate("foo").or(Post.annotate("bar")).to_sql + assert_match %r{#{quoted_posts} /\* foo \*/ /\* bar \*/\z}, Post.annotate("foo", "bar").or(Post.annotate("foo")).to_sql + end + def test_structurally_incompatible_values assert_nothing_raised do Post.includes(:author).includes(:author).or(Post.includes(:author)) From 6404a6618f07e1e732295c49bdb0da736b393ba8 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 26 May 2020 05:19:26 +0900 Subject: [PATCH 038/244] Merge pull request #39424 from kamipo/fix_preload_for_polymorphic_association Fix preloading for polymorphic association with custom scope --- .../associations/preloader/association.rb | 2 +- activerecord/lib/active_record/reflection.rb | 14 +++++++------- .../associations/belongs_to_associations_test.rb | 7 +++++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 692d9cf37fc81..c973e0c3afea1 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -114,7 +114,7 @@ def scope def reflection_scope @reflection_scope ||= begin - reflection.join_scopes(klass.arel_table, klass.predicate_builder).inject(klass.unscoped, &:merge!) + reflection.join_scopes(klass.arel_table, klass.predicate_builder, klass).inject(&:merge!) || klass.unscoped end end diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 4a5aa902b880d..b875f88637f58 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -201,9 +201,9 @@ def join_scope(table, foreign_table, foreign_klass) klass_scope end - def join_scopes(table, predicate_builder) # :nodoc: + def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc: if scope - [scope_for(build_scope(table, predicate_builder))] + [scope_for(build_scope(table, predicate_builder, klass))] else [] end @@ -292,7 +292,7 @@ def get_join_keys(association_klass) JoinKeys.new(join_primary_key(association_klass), join_foreign_key) end - def build_scope(table, predicate_builder = predicate_builder(table)) + def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass) Relation.create( klass, table: table, @@ -839,8 +839,8 @@ def scopes source_reflection.scopes + super end - def join_scopes(table, predicate_builder) # :nodoc: - source_reflection.join_scopes(table, predicate_builder) + super + def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc: + source_reflection.join_scopes(table, predicate_builder, klass) + super end def has_scope? @@ -1003,9 +1003,9 @@ def initialize(reflection, previous_reflection) @previous_reflection = previous_reflection end - def join_scopes(table, predicate_builder) # :nodoc: + def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc: scopes = @previous_reflection.join_scopes(table, predicate_builder) + super - scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope) + scopes << build_scope(table, predicate_builder, klass).instance_exec(nil, &source_type_scope) end def constraints diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index cbdd4dda624a9..97cb7b3d68f32 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -441,7 +441,14 @@ def test_polymorphic_association_class def test_with_polymorphic_and_condition sponsor = Sponsor.create member = Member.create name: "Bert" + sponsor.sponsorable = member + sponsor.save! + + assert_equal member, sponsor.sponsorable + assert_nil sponsor.sponsorable_with_conditions + + sponsor = Sponsor.preload(:sponsorable, :sponsorable_with_conditions).last assert_equal member, sponsor.sponsorable assert_nil sponsor.sponsorable_with_conditions From 33c87282493d6691d71b604fe58c10997ac50d66 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Mon, 25 May 2020 21:03:32 -0500 Subject: [PATCH 039/244] Fix Active Storage behavior on record dup Prior to this commit, a `dup`ed record and its originating record would share the same `Attached` proxy objects. Those proxy objects, in turn, would point to the same `Attachment` associations, causing changes made through the proxy interface to affect both records. --- activestorage/lib/active_storage/attached/model.rb | 12 ++++++++++-- activestorage/test/models/attached/many_test.rb | 14 ++++++++++++++ activestorage/test/models/attached/one_test.rb | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/activestorage/lib/active_storage/attached/model.rb b/activestorage/lib/active_storage/attached/model.rb index 479f7f072ed86..962cec60e2d15 100644 --- a/activestorage/lib/active_storage/attached/model.rb +++ b/activestorage/lib/active_storage/attached/model.rb @@ -33,7 +33,8 @@ module Attached::Model def has_one_attached(name, dependent: :purge_later) generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1 def #{name} - @active_storage_attached_#{name} ||= ActiveStorage::Attached::One.new("#{name}", self) + @active_storage_attached ||= {} + @active_storage_attached[:#{name}] ||= ActiveStorage::Attached::One.new("#{name}", self) end def #{name}=(attachable) @@ -89,7 +90,8 @@ def #{name}=(attachable) def has_many_attached(name, dependent: :purge_later) generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1 def #{name} - @active_storage_attached_#{name} ||= ActiveStorage::Attached::Many.new("#{name}", self) + @active_storage_attached ||= {} + @active_storage_attached[:#{name}] ||= ActiveStorage::Attached::Many.new("#{name}", self) end def #{name}=(attachables) @@ -144,6 +146,12 @@ def changed_for_autosave? #:nodoc: super || attachment_changes.any? end + def initialize_dup(*) #:nodoc: + super + @active_storage_attached = nil + @attachment_changes = nil + end + def reload(*) #:nodoc: super.tap { @attachment_changes = nil } end diff --git a/activestorage/test/models/attached/many_test.rb b/activestorage/test/models/attached/many_test.rb index 785835e57b267..21cfb26b4ffb7 100644 --- a/activestorage/test/models/attached/many_test.rb +++ b/activestorage/test/models/attached/many_test.rb @@ -608,6 +608,20 @@ class ActiveStorage::ManyAttachedTest < ActiveSupport::TestCase end end + test "duped record does not share attachments" do + @user.highlights.attach [ create_blob(filename: "funky.jpg") ] + + assert_not_equal @user.highlights.first, @user.dup.highlights.first + end + + test "duped record does not share attachment changes" do + @user.highlights.attach [ create_blob(filename: "funky.jpg") ] + assert_not_predicate @user, :changed_for_autosave? + + @user.dup.highlights.attach [ create_blob(filename: "town.mp4") ] + assert_not_predicate @user, :changed_for_autosave? + end + test "clearing change on reload" do @user.highlights = [ create_blob(filename: "funky.jpg"), create_blob(filename: "town.jpg") ] assert @user.highlights.attached? diff --git a/activestorage/test/models/attached/one_test.rb b/activestorage/test/models/attached/one_test.rb index a7c5e9b67cba1..7e810edf2c992 100644 --- a/activestorage/test/models/attached/one_test.rb +++ b/activestorage/test/models/attached/one_test.rb @@ -496,6 +496,20 @@ class ActiveStorage::OneAttachedTest < ActiveSupport::TestCase end end + test "duped record does not share attachments" do + @user.avatar.attach create_blob(filename: "funky.jpg") + + assert_not_equal @user.avatar.attachment, @user.dup.avatar.attachment + end + + test "duped record does not share attachment changes" do + @user.avatar.attach create_blob(filename: "funky.jpg") + assert_not_predicate @user, :changed_for_autosave? + + @user.dup.avatar.attach create_blob(filename: "town.jpg") + assert_not_predicate @user, :changed_for_autosave? + end + test "clearing change on reload" do @user.avatar = create_blob(filename: "funky.jpg") assert @user.avatar.attached? From cca17e59e94ca6f774a855034f7863b3850c1fbd Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 20 May 2020 15:54:28 -0700 Subject: [PATCH 040/244] Fixed up error output tests and added a missing failure output test. Errors *should* output their stack. Somehow these tests were passing before. This clarifies all states (skip/fail/error) and works against @tenderlove's patch. (cherry picked from commit c07bcd65733e8c15447c38363f558e79fd1ed944) --- railties/test/test_unit/reporter_test.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/railties/test/test_unit/reporter_test.rb b/railties/test/test_unit/reporter_test.rb index 81b7ab19a1a17..25b711cc998b5 100644 --- a/railties/test/test_unit/reporter_test.rb +++ b/railties/test/test_unit/reporter_test.rb @@ -72,7 +72,7 @@ def woot; end @reporter.record(errored_test) @reporter.report - expect = %r{\AE\n\nError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n \n\nrails test .*test/test_unit/reporter_test\.rb:\d+\n\n\z} + expect = %r{\AE\n\nError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n some_test.rb:4\n\nrails test .*test/test_unit/reporter_test\.rb:\d+\n\n\z} assert_match expect, @output.string end @@ -148,11 +148,21 @@ def woot; end end test "outputs colored failed results" do + @output.stub(:tty?, true) do + colored = Rails::TestUnitReporter.new @output, color: true, output_inline: true + colored.record(failed_test) + + expected = %r{\e\[31mF\e\[0m\n\n\e\[31mFailure:\nTestUnitReporterTest::ExampleTest#woot \[test/test_unit/reporter_test.rb:\d+\]:\nboo\n\e\[0m\n\nrails test .*test/test_unit/reporter_test.rb:\d+\n\n} + assert_match expected, @output.string + end + end + + test "outputs colored error results" do @output.stub(:tty?, true) do colored = Rails::TestUnitReporter.new @output, color: true, output_inline: true colored.record(errored_test) - expected = %r{\e\[31mE\e\[0m\n\n\e\[31mError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n \n\e\[0m} + expected = %r{\e\[31mE\e\[0m\n\n\e\[31mError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n some_test.rb:4\n\e\[0m} assert_match expected, @output.string end end From 3f3d767499d240c1bbe75af43a8ef73563167a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Mon, 9 Mar 2020 13:57:07 -0400 Subject: [PATCH 041/244] Merge pull request #38662 from olivierlacan/doc/update-windows-setup Stop recommending RailsInstaller in favor of RubyInstaller --- guides/source/getting_started.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md index 40da25354c36e..34abd8044275d 100644 --- a/guides/source/getting_started.md +++ b/guides/source/getting_started.md @@ -80,7 +80,7 @@ your prompt will look something like `c:\source_code>` Before you install Rails, you should check to make sure that your system has the proper prerequisites installed. These include: -* Ruby +* Ruby * SQLite3 * Node.js * Yarn @@ -100,21 +100,18 @@ ruby 2.5.0 Rails requires Ruby version 2.5.0 or later. If the version number returned is less than that number, you'll need to install a fresh copy of Ruby. -TIP: To quickly install Ruby and Ruby on Rails on your system in Windows, you can use -[Rails Installer](http://railsinstaller.org). For more installation methods for most -Operating Systems take a look at [ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/). +To install Rails on Windows, you'll first need to install [Ruby Installer](https://rubyinstaller.org/). -If you are working on Windows, you should also install the -[Ruby Installer Development Kit](https://rubyinstaller.org/downloads/). +For more installation methods for most Operating Systems take a look at +[ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/). #### Installing SQLite3 You will also need an installation of the SQLite3 database. Many popular UNIX-like OSes ship with an acceptable version of SQLite3. -On Windows, if you installed Rails through Rails Installer, you -already have SQLite installed. Others can find installation instructions -at the [SQLite3 website](https://www.sqlite.org). -Verify that it is correctly installed and in your PATH: +Others can find installation instructions at the [SQLite3 website](https://www.sqlite.org). + +Verify that it is correctly installed and in your load `PATH`: ```bash $ sqlite3 --version @@ -126,10 +123,10 @@ The program should report its version. Finally, you'll need Node.js and Yarn installed to manage your application's JavaScript. -Find the installation instructions at the [Node.js website](https://nodejs.org/en/download/) and +Find the installation instructions at the [Node.js website](https://nodejs.org/en/download/) and verify it's installed correctly with the following command: -```bash +```bash $ node --version ``` From 7ddf2b7c0c8ff97b0a50e963b24bf2b82950988d Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 7 May 2020 10:56:45 +0900 Subject: [PATCH 042/244] Update rails gem version in bug report templates to pass CI on Ruby master https://buildkite.com/rails/rails/builds/68834#f6a78cf3-6ae4-4148-b1c2-114ccce0731a/941-1012 --- guides/bug_report_templates/action_controller_gem.rb | 2 +- guides/bug_report_templates/active_job_gem.rb | 2 +- guides/bug_report_templates/active_record_gem.rb | 2 +- guides/bug_report_templates/active_record_migrations_gem.rb | 2 +- guides/bug_report_templates/generic_gem.rb | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/guides/bug_report_templates/action_controller_gem.rb b/guides/bug_report_templates/action_controller_gem.rb index 09cced43bea2b..3ee3f9d2886dd 100644 --- a/guides/bug_report_templates/action_controller_gem.rb +++ b/guides/bug_report_templates/action_controller_gem.rb @@ -8,7 +8,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Activate the gem you are reporting the issue against. - gem "rails", "6.0.0" + gem "rails", "6.0.3" end require "rack/test" diff --git a/guides/bug_report_templates/active_job_gem.rb b/guides/bug_report_templates/active_job_gem.rb index 92da7572b326c..0965daf9f5cf7 100644 --- a/guides/bug_report_templates/active_job_gem.rb +++ b/guides/bug_report_templates/active_job_gem.rb @@ -8,7 +8,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Activate the gem you are reporting the issue against. - gem "activejob", "6.0.0" + gem "activejob", "6.0.3" end require "minitest/autorun" diff --git a/guides/bug_report_templates/active_record_gem.rb b/guides/bug_report_templates/active_record_gem.rb index 57ee2f0d1ce89..6f11f8559cd86 100644 --- a/guides/bug_report_templates/active_record_gem.rb +++ b/guides/bug_report_templates/active_record_gem.rb @@ -8,7 +8,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Activate the gem you are reporting the issue against. - gem "activerecord", "6.0.0" + gem "activerecord", "6.0.3" gem "sqlite3" end diff --git a/guides/bug_report_templates/active_record_migrations_gem.rb b/guides/bug_report_templates/active_record_migrations_gem.rb index 2386ff8e9dc29..9ddad75a4caf9 100644 --- a/guides/bug_report_templates/active_record_migrations_gem.rb +++ b/guides/bug_report_templates/active_record_migrations_gem.rb @@ -8,7 +8,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Activate the gem you are reporting the issue against. - gem "activerecord", "6.0.0" + gem "activerecord", "6.0.3" gem "sqlite3" end diff --git a/guides/bug_report_templates/generic_gem.rb b/guides/bug_report_templates/generic_gem.rb index 9427d7982694f..3e9e81551c861 100644 --- a/guides/bug_report_templates/generic_gem.rb +++ b/guides/bug_report_templates/generic_gem.rb @@ -8,7 +8,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Activate the gem you are reporting the issue against. - gem "activesupport", "6.0.0" + gem "activesupport", "6.0.3" end require "active_support" From e7154f346ae88c45429c151a366eb34572479284 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Thu, 28 May 2020 08:49:45 +0100 Subject: [PATCH 043/244] Merge pull request #39452 from rolandasb/fix-nil-encrypted-cookie-value Fix nil encrypted/signed cookie value when value is stored as `false` --- actionpack/CHANGELOG.md | 6 ++++++ .../lib/action_dispatch/middleware/cookies.rb | 8 +++++++- actionpack/test/dispatch/cookies_test.rb | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index fe80fee82837e..cf60f50d49146 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,9 @@ +* Signed and encrypted cookies can now store `false` as their value when + `action_dispatch.use_cookies_with_metadata` is enabled. + + *Rolandas Barysas* + + ## Rails 6.0.3.1 (May 18, 2020) ## * [CVE-2020-8166] HMAC raw CSRF token before masking it, so it cannot be used to reconstruct a per-form token diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 41b913af67857..66ffb71abd649 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -458,7 +458,13 @@ def initialize(parent_jar) def [](name) if data = @parent_jar[name.to_s] - parse(name, data, purpose: "cookie.#{name}") || parse(name, data) + result = parse(name, data, purpose: "cookie.#{name}") + + if result.nil? + parse(name, data) + else + result + end end end diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index 446aa8e37dc78..16b21103b83ae 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -1185,6 +1185,20 @@ def test_vanilla_cookie_with_expires_set_relatively end end + def test_signed_cookie_with_false_value_and_metadata + request.env["action_dispatch.use_cookies_with_metadata"] = true + + cookies.signed[:foo] = false + assert_equal false, cookies.signed[:foo] + end + + def test_encrypted_cookie_with_false_value_and_metadata + request.env["action_dispatch.use_cookies_with_metadata"] = true + + cookies.encrypted[:foo] = false + assert_equal false, cookies.encrypted[:foo] + end + def test_purpose_metadata_for_encrypted_cookies get :encrypted_discount_and_user_id_cookie From 3335a0e79b308f5100e2b88536144307fd4db13f Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 1 Jun 2020 09:27:16 -0400 Subject: [PATCH 044/244] Backport a portion of #38684 In Rails 6.0 the connection specification name for the ActiveRecord::Base class is `primary`. In 6.1 we've changed it to be `ActiveRecord::Base` to match how other classes behave. Due to the way the schema migration table and connection to that table are handled in Active Record we need to generate classes on the connection so those connections are able to find the correct table. Applications don't create the table, Rails does, and the default schema migration class inherits directly from Active Record. Since the default connection in 6.0 is named `primary` we end up with a class name of `primary::SchemaMigration` which is not a valid constant name and causes problems with Zeitwerk. I realized however that I never backported #38684 to 6.0 which skips the creation of the class for `ActiveRecord::Base` since it can use the default. This should fix the issue for Zeitwrk since we're no longer creating a `primary::SchemaMigration` class. The other databases in a multi-db application won't have issues because they use their actual class name, therefore causing no issues for Zeitwerk since it follows the Active Model naming pattern. Ref: #36757 --- .../active_record/connection_adapters/abstract_adapter.rb | 2 ++ activerecord/test/cases/multi_db_migrator_test.rb | 5 +++++ railties/test/application/loading_test.rb | 4 ++-- railties/test/application/zeitwerk_integration_test.rb | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index cf1926f40ab2b..def1e625d438d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -168,6 +168,8 @@ def schema_migration # :nodoc: spec_name = conn.pool.spec.name name = "#{spec_name}::SchemaMigration" + return ActiveRecord::SchemaMigration if spec_name == "primary" + Class.new(ActiveRecord::SchemaMigration) do define_singleton_method(:name) { name } define_singleton_method(:to_s) { name } diff --git a/activerecord/test/cases/multi_db_migrator_test.rb b/activerecord/test/cases/multi_db_migrator_test.rb index 650b3af6f00ec..1cc3b08a5d954 100644 --- a/activerecord/test/cases/multi_db_migrator_test.rb +++ b/activerecord/test/cases/multi_db_migrator_test.rb @@ -67,6 +67,11 @@ def puts(*) end end + def test_schema_migration_class_names + assert_equal "ActiveRecord::SchemaMigration", @schema_migration_a.name + assert_equal "ARUnit2Model::SchemaMigration", @schema_migration_b.name + end + def test_finds_migrations @migrations_a_list.each_with_index do |pair, i| assert_equal @migrations_a[i].version, pair.first diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index 9ab400acfcbd9..d1bca825572c6 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -133,12 +133,12 @@ class Post < ApplicationRecord require "#{rails_root}/config/environment" setup_ar! - initial = [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord, "primary::SchemaMigration"].collect(&:to_s).sort + initial = [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord].collect(&:to_s).sort assert_equal initial, ActiveRecord::Base.descendants.collect(&:to_s).sort get "/load" assert_equal [Post].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort - initial get "/unload" - assert_equal ["ActiveRecord::InternalMetadata", "ActiveRecord::SchemaMigration", "primary::SchemaMigration"], ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq + assert_equal ["ActiveRecord::InternalMetadata", "ActiveRecord::SchemaMigration"], ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq end test "initialize cant be called twice" do diff --git a/railties/test/application/zeitwerk_integration_test.rb b/railties/test/application/zeitwerk_integration_test.rb index 57004d3e13f1d..268a7467eb44e 100644 --- a/railties/test/application/zeitwerk_integration_test.rb +++ b/railties/test/application/zeitwerk_integration_test.rb @@ -101,7 +101,7 @@ class RESTfulController < ApplicationController test "autoloaded? and overridden class names" do invalid_constant_name = Module.new do def self.name - "primary::SchemaMigration" + "MyModule::SchemaMigration" end end assert_not deps.autoloaded?(invalid_constant_name) From f7c618e7b897a5fc6a22b5bc368079db5615f9a9 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Wed, 3 Jun 2020 15:40:04 +0100 Subject: [PATCH 045/244] Merge pull request #39517 from austenmadden/allow-insert-all-unique-by-index-expressions Fix issue with expression index in insert_all --- activerecord/CHANGELOG.md | 21 ++++++++++++++++++++ activerecord/lib/active_record/insert_all.rb | 2 +- activerecord/test/cases/helper.rb | 1 + activerecord/test/cases/insert_all_test.rb | 14 +++++++++++++ activerecord/test/schema/schema.rb | 2 ++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 49b7a4e409494..88064c1fd3b65 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,24 @@ +* Resolve issue with insert_all unique_by option when used with expression index. + + When the `:unique_by` option of `ActiveRecord::Persistence.insert_all` and + `ActiveRecord::Persistence.upsert_all` was used with the name of an expression index, an error + was raised. Adding a guard around the formatting behavior for the `:unique_by` corrects this. + + Usage: + + ```ruby + create_table :books, id: :integer, force: true do |t| + t.column :name, :string + t.index "lower(name)", unique: true + end + + Book.insert_all [{ name: "MyTest" }], unique_by: :index_books_on_lower_name + ``` + + Fixes #39516. + + *Austen Madden* + * Resolve conflict between counter cache and optimistic locking. Bump an Active Record instance's lock version after updating its counter diff --git a/activerecord/lib/active_record/insert_all.rb b/activerecord/lib/active_record/insert_all.rb index 46e32056bae82..51dd5cd7c9588 100644 --- a/activerecord/lib/active_record/insert_all.rb +++ b/activerecord/lib/active_record/insert_all.rb @@ -168,7 +168,7 @@ def extract_types_from_columns_on(table_name, keys:) end def format_columns(columns) - quote_columns(columns).join(",") + columns.respond_to?(:map) ? quote_columns(columns).join(",") : columns end def quote_columns(columns) diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 891641575b0c7..ddf5c35a3fde0 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -61,6 +61,7 @@ def supports_default_expression? supports_savepoints? supports_partial_index? supports_partitioned_indexes? + supports_expression_index? supports_insert_returning? supports_insert_on_duplicate_skip? supports_insert_on_duplicate_update? diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb index 50a58610ac440..523bdd727dea4 100644 --- a/activerecord/test/cases/insert_all_test.rb +++ b/activerecord/test/cases/insert_all_test.rb @@ -173,6 +173,20 @@ def test_insert_all_and_upsert_all_with_index_finding_options end end + def test_insert_all_and_upsert_all_with_expression_index + skip unless supports_expression_index? && supports_insert_conflict_target? + + book = Book.create!(external_id: "abc") + + assert_no_difference "Book.count" do + Book.insert_all [{ external_id: "ABC" }], unique_by: :index_books_on_lower_external_id + end + + Book.upsert_all [{ external_id: "Abc" }], unique_by: :index_books_on_lower_external_id + + assert_equal "Abc", book.reload.external_id + end + def test_insert_all_and_upsert_all_raises_when_index_is_missing skip unless supports_insert_conflict_target? diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 1e387cf6f2b98..be2277dbe841d 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -116,9 +116,11 @@ t.column :difficulty, :integer, **default_zero t.column :cover, :string, default: "hard" t.string :isbn, **case_sensitive_options + t.string :external_id t.datetime :published_on t.index [:author_id, :name], unique: true t.index :isbn, where: "published_on IS NOT NULL", unique: true + t.index "(lower(external_id))", unique: true if supports_expression_index? end create_table :booleans, force: true do |t| From 87818dde9d76392432a096eb5dcde61c469bb018 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Tue, 2 Jun 2020 00:25:55 +0100 Subject: [PATCH 046/244] Merge pull request #39488 from eugeneius/recommend_null_session Don't recommend disabling CSRF protection [ci skip] --- .../metal/request_forgery_protection.rb | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index c9ec3c051f014..8123170533346 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -32,29 +32,21 @@ class InvalidCrossOriginRequest < ActionControllerError #:nodoc: # response may be extracted. To prevent this, only XmlHttpRequest (known as XHR or # Ajax) requests are allowed to make requests for JavaScript responses. # - # It's important to remember that XML or JSON requests are also checked by default. If - # you're building an API or an SPA you could change forgery protection method in - # ApplicationController (by default: :exception): + # Subclasses of ActionController::Base are protected by default with the + # :exception strategy, which raises an + # ActionController::InvalidAuthenticityToken error on unverified requests. + # + # APIs may want to disable this behavior since they are typically designed to be + # state-less: that is, the request API client handles the session instead of Rails. + # One way to achieve this is to use the :null_session strategy instead, + # which allows unverified requests to be handled, but with an empty session: # # class ApplicationController < ActionController::Base - # protect_from_forgery unless: -> { request.format.json? } + # protect_from_forgery with: :null_session # end # - # It is generally safe to exclude XHR requests from CSRF protection - # (like the code snippet above does), because XHR requests can only be made from - # the same origin. Note however that any cross-origin third party domain - # allowed via {CORS}[https://en.wikipedia.org/wiki/Cross-origin_resource_sharing] - # will also be able to create XHR requests. Be sure to check your - # CORS configuration before disabling forgery protection for XHR. - # - # CSRF protection is turned on with the protect_from_forgery method. - # By default protect_from_forgery protects your session with - # :null_session method, which provides an empty session - # during request. - # - # We may want to disable CSRF protection for APIs since they are typically - # designed to be state-less. That is, the request API client will handle - # the session for you instead of Rails. + # Note that API only applications don't include this module or a session middleware + # by default, and so don't require CSRF protection to be configured. # # The token parameter is named authenticity_token by default. The name and # value of this token must be added to every layout that renders forms by including From 82f861855c23e6f0005a3222e1238efb2baa270a Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 4 Jun 2020 02:17:18 +0900 Subject: [PATCH 047/244] Don't call `ruby2_keywords` for user supplied block --- activemodel/lib/active_model/type/registry.rb | 6 ++++-- activemodel/test/cases/type/registry_test.rb | 18 +++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/activemodel/lib/active_model/type/registry.rb b/activemodel/lib/active_model/type/registry.rb index f227f74b5ee67..4bd76363cfae2 100644 --- a/activemodel/lib/active_model/type/registry.rb +++ b/activemodel/lib/active_model/type/registry.rb @@ -9,8 +9,10 @@ def initialize end def register(type_name, klass = nil, **options, &block) - block ||= proc { |_, *args| klass.new(*args) } - block.ruby2_keywords if block.respond_to?(:ruby2_keywords) + unless block_given? + block = proc { |_, *args| klass.new(*args) } + block.ruby2_keywords if block.respond_to?(:ruby2_keywords) + end registrations << registration_klass.new(type_name, block, **options) end diff --git a/activemodel/test/cases/type/registry_test.rb b/activemodel/test/cases/type/registry_test.rb index 0633ea2538fad..c6ded52f39e03 100644 --- a/activemodel/test/cases/type/registry_test.rb +++ b/activemodel/test/cases/type/registry_test.rb @@ -16,16 +16,20 @@ class RegistryTest < ActiveModel::TestCase test "a block can be registered" do registry = Type::Registry.new - registry.register(:foo) do |*args| - [*args, "block for foo"] + registry.register(:foo) do |type, *args| + [type, args, "block for foo"] end - registry.register(:bar) do |*args| - [*args, "block for bar"] + registry.register(:bar) do |type, *args| + [type, args, "block for bar"] + end + registry.register(:baz) do |type, **kwargs| + [type, kwargs, "block for baz"] end - assert_equal [:foo, 1, "block for foo"], registry.lookup(:foo, 1) - assert_equal [:foo, 2, "block for foo"], registry.lookup(:foo, 2) - assert_equal [:bar, 1, 2, 3, "block for bar"], registry.lookup(:bar, 1, 2, 3) + assert_equal [:foo, [1], "block for foo"], registry.lookup(:foo, 1) + assert_equal [:foo, [2], "block for foo"], registry.lookup(:foo, 2) + assert_equal [:bar, [1, 2, 3], "block for bar"], registry.lookup(:bar, 1, 2, 3) + assert_equal [:baz, { kw: 1 }, "block for baz"], registry.lookup(:baz, kw: 1) end test "a reasonable error is given when no type is found" do From 4c57f94764dc964bdfdae4d9fefc7cbaf0e267c0 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 5 Jun 2020 10:17:51 +0900 Subject: [PATCH 048/244] Revert "Lock benchmark-ips version "< 2.8"" This reverts commit c1b8833edbc55cdbea34b572e8759a92ed9a4660. Revert "Lock benchmark-ips version < 2.8" This reverts commit 62bfa50ff2db093508575b442ac50b125dd0850b. LoadError is fixed in benchmark-ips 2.8.2. https://github.com/evanphx/benchmark-ips/pull/101 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- guides/bug_report_templates/benchmark.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index d764a0abdd3de..60766bd39126a 100644 --- a/Gemfile +++ b/Gemfile @@ -112,7 +112,7 @@ group :test do gem "byebug" end - gem "benchmark-ips", "< 2.8" + gem "benchmark-ips" end platforms :ruby, :mswin, :mswin64, :mingw, :x64_mingw do diff --git a/Gemfile.lock b/Gemfile.lock index e93252f2e4980..3cfd6f19935b6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -148,7 +148,7 @@ GEM bcrypt (3.1.13) bcrypt (3.1.13-java) beaneater (1.0.0) - benchmark-ips (2.7.2) + benchmark-ips (2.8.2) blade (0.7.1) activesupport (>= 3.0.0) blade-qunit_adapter (~> 2.0.1) @@ -540,7 +540,7 @@ DEPENDENCIES azure-storage backburner bcrypt (~> 3.1.11) - benchmark-ips (< 2.8) + benchmark-ips blade blade-sauce_labs_plugin bootsnap (>= 1.4.2) diff --git a/guides/bug_report_templates/benchmark.rb b/guides/bug_report_templates/benchmark.rb index 76fa7f3e5c971..c4dc6b3bc3ec4 100644 --- a/guides/bug_report_templates/benchmark.rb +++ b/guides/bug_report_templates/benchmark.rb @@ -8,7 +8,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } gem "rails", github: "rails/rails", branch: "6-0-stable" - gem "benchmark-ips", "< 2.8" + gem "benchmark-ips" end require "active_support" From b3a0be0f560b558ca121905d7882ef790df67bcc Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 10 Jun 2020 09:25:03 +0900 Subject: [PATCH 049/244] Fix Active Support failure for redis 4.2.0 with Ruby 2.8.0-dev --- Gemfile.lock | 2 +- activesupport/lib/active_support/cache/redis_cache_store.rb | 2 +- activesupport/test/cache/stores/redis_cache_store_test.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3cfd6f19935b6..f6c5922a4131a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -383,7 +383,7 @@ GEM ffi (~> 1.0) rdoc (6.2.1) redcarpet (3.2.3) - redis (4.1.3) + redis (4.2.0) redis-namespace (1.7.0) redis (>= 3.0.4) regexp_parser (1.6.0) diff --git a/activesupport/lib/active_support/cache/redis_cache_store.rb b/activesupport/lib/active_support/cache/redis_cache_store.rb index cf41ef3803c93..37499ee4eb2d2 100644 --- a/activesupport/lib/active_support/cache/redis_cache_store.rb +++ b/activesupport/lib/active_support/cache/redis_cache_store.rb @@ -394,7 +394,7 @@ def write_entry(key, entry, unless_exist: false, raw: false, expires_in: nil, ra modifiers[:nx] = unless_exist modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in - redis.with { |c| c.set key, serialized_entry, modifiers } + redis.with { |c| c.set key, serialized_entry, **modifiers } else redis.with { |c| c.set key, serialized_entry } end diff --git a/activesupport/test/cache/stores/redis_cache_store_test.rb b/activesupport/test/cache/stores/redis_cache_store_test.rb index 2fa997079b2ef..a7685e6f8f82b 100644 --- a/activesupport/test/cache/stores/redis_cache_store_test.rb +++ b/activesupport/test/cache/stores/redis_cache_store_test.rb @@ -300,7 +300,7 @@ class ClearTest < StoreTest @cache.redis.set("fu", "baz") @cache.clear assert_not @cache.exist?("foo") - assert @cache.redis.exists("fu") + assert @cache.redis.exists?("fu") end end end From 319de3e9d5b3cd0b98f63a74a2501e2b0b1c8530 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 17 Oct 2019 11:40:48 +0900 Subject: [PATCH 050/244] Merge pull request #37489 from giraffate/fix_random_ci_failure_due_to_non-deterministic_sorting_order Fix random CI failure due to non-deterministic sorting order --- activerecord/test/cases/relations_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index c01dab5751275..a3cca5972b380 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -2046,7 +2046,7 @@ def test_locked_should_not_build_arel end def test_relation_join_method - assert_equal "Thank you for the welcome,Thank you again for the welcome", Post.first.comments.join(",") + assert_equal "Thank you for the welcome,Thank you again for the welcome", Post.first.comments.order(:id).join(",") end def test_relation_with_private_kernel_method From 133920647065205b4cd5bf2e8e15313152ab1fb2 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sat, 13 Jun 2020 10:59:29 +0900 Subject: [PATCH 051/244] Merge pull request #37648 from chrisandreae/postgresql-quoted-ranges ActiveRecord PostgreSQL adapter: parse quoted values in range output --- .../postgresql/oid/range.rb | 29 +++++++++++++++---- .../cases/adapters/postgresql/range_test.rb | 27 +++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb index d19f1f9cf8e07..64dafbd89fefd 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb @@ -67,15 +67,34 @@ def type_cast_single_for_database(value) end def extract_bounds(value) - from, to = value[1..-2].split(",") + from, to = value[1..-2].split(",", 2) { - from: (value[1] == "," || from == "-infinity") ? infinity(negative: true) : from, - to: (value[-2] == "," || to == "infinity") ? infinity : to, - exclude_start: (value[0] == "("), - exclude_end: (value[-1] == ")") + from: (from == "" || from == "-infinity") ? infinity(negative: true) : unquote(from), + to: (to == "" || to == "infinity") ? infinity : unquote(to), + exclude_start: value.start_with?("("), + exclude_end: value.end_with?(")") } end + # When formatting the bound values of range types, PostgreSQL quotes + # the bound value using double-quotes in certain conditions. Within + # a double-quoted string, literal " and \ characters are themselves + # escaped. In input, PostgreSQL accepts multiple escape styles for " + # (either \" or "") but in output always uses "". + # See: + # * https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO + # * https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-IO-SYNTAX + def unquote(value) + if value.start_with?('"') && value.end_with?('"') + unquoted_value = value[1..-2] + unquoted_value.gsub!('""', '"') + unquoted_value.gsub!('\\\\', '\\') + unquoted_value + else + value + end + end + def infinity(negative: false) if subtype.respond_to?(:infinity) subtype.infinity(negative: negative) diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb index 068f1e8beac15..395fbebbdf9fe 100644 --- a/activerecord/test/cases/adapters/postgresql/range_test.rb +++ b/activerecord/test/cases/adapters/postgresql/range_test.rb @@ -22,6 +22,10 @@ def setup subtype = float8, subtype_diff = float8mi ); + + CREATE TYPE stringrange AS RANGE ( + subtype = varchar + ); SQL @connection.create_table("postgresql_ranges") do |t| @@ -34,6 +38,7 @@ def setup end @connection.add_column "postgresql_ranges", "float_range", "floatrange" + @connection.add_column "postgresql_ranges", "string_range", "stringrange" end PostgresqlRange.reset_column_information rescue ActiveRecord::StatementInvalid @@ -96,6 +101,7 @@ def setup teardown do @connection.drop_table "postgresql_ranges", if_exists: true @connection.execute "DROP TYPE IF EXISTS floatrange" + @connection.execute "DROP TYPE IF EXISTS stringrange" reset_connection end @@ -197,6 +203,11 @@ def test_update_tstzrange Time.parse("2010-01-01 14:30:00 +0100")...Time.parse("2010-01-01 13:30:00 +0000")) end + def test_escaped_tstzrange + assert_equal_round_trip(@first_range, :tstz_range, + Time.parse("-1000-01-01 14:30:00 CDT")...Time.parse("2020-02-02 14:30:00 CET")) + end + def test_create_tsrange tz = ::ActiveRecord::Base.default_timezone assert_equal_round_trip(@new_range, :ts_range, @@ -211,6 +222,12 @@ def test_update_tsrange Time.send(tz, 2010, 1, 1, 14, 30, 0)...Time.send(tz, 2010, 1, 1, 14, 30, 0)) end + def test_escaped_tsrange + tz = ::ActiveRecord::Base.default_timezone + assert_equal_round_trip(@first_range, :ts_range, + Time.send(tz, -1000, 1, 1, 14, 30, 0)...Time.send(tz, 2020, 2, 2, 14, 30, 0)) + end + def test_timezone_awareness_tsrange tz = "Pacific Time (US & Canada)" @@ -363,6 +380,16 @@ def test_ranges_correctly_escape_input end end + def test_ranges_correctly_unescape_output + @connection.execute(<<~SQL) + INSERT INTO postgresql_ranges (id, string_range) + VALUES (106, '["ca""t","do\\\\g")') + SQL + + escaped_range = PostgresqlRange.find(106) + assert_equal('ca"t'...'do\\g', escaped_range.string_range) + end + def test_infinity_values PostgresqlRange.create!(int4_range: 1..Float::INFINITY, int8_range: -Float::INFINITY..0, From 2478300525043a889fcb5d216b16128f657f5463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Mon, 15 Jun 2020 11:51:20 -0400 Subject: [PATCH 052/244] Merge pull request #39633 from gmcgibbon/document_javascript_path Document config.javascript_path --- guides/source/configuring.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 2f679e74498a8..bb42e3048dd36 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -112,6 +112,8 @@ numbers. It also filters out sensitive values of database columns when call `#in * `config.force_ssl` forces all requests to be served over HTTPS by using the `ActionDispatch::SSL` middleware, and sets `config.action_mailer.default_url_options` to be `{ protocol: 'https' }`. This can be configured by setting `config.ssl_options` - see the [ActionDispatch::SSL documentation](https://api.rubyonrails.org/classes/ActionDispatch/SSL.html) for details. +* `config.javascript_path` sets the path where your app's JavaScript lives relative to the `app` directory. The default is `javascript`, used by [webpacker](https://github.com/rails/webpacker). An app's configured `javascript_path` will be excluded from `autoload_paths`. + * `config.log_formatter` defines the formatter of the Rails logger. This option defaults to an instance of `ActiveSupport::Logger::SimpleFormatter` for all modes. If you are setting a value for `config.logger` you must manually pass the value of your formatter to your logger before it is wrapped in an `ActiveSupport::TaggedLogging` instance, Rails will not do it for you. * `config.log_level` defines the verbosity of the Rails logger. This option From a1608d2e7a1a6ab86d99283956b7112de6ea6924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 15 Jun 2020 22:59:28 -0400 Subject: [PATCH 053/244] Fix CHANGELOG --- actionpack/CHANGELOG.md | 1 + actionview/CHANGELOG.md | 1 + activerecord/CHANGELOG.md | 1 + activestorage/CHANGELOG.md | 1 + activesupport/CHANGELOG.md | 1 + 5 files changed, 5 insertions(+) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index cf60f50d49146..a903e1eae8f67 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -10,6 +10,7 @@ * [CVE-2020-8164] Return self when calling #each, #each_pair, and #each_value instead of the raw @parameters hash + ## Rails 6.0.3 (May 06, 2020) ## * Include child session assertion count in ActionDispatch::IntegrationTest diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 854ec7f1dce46..ae23a602e2d4d 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -2,6 +2,7 @@ * [CVE-2020-8167] Check that request is same-origin prior to including CSRF token in XHRs + ## Rails 6.0.3 (May 06, 2020) ## * annotated_source_code returns an empty array so TemplateErrors without a diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 88064c1fd3b65..bb85b020bd4d9 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -39,6 +39,7 @@ * No changes. + ## Rails 6.0.3 (May 06, 2020) ## * Recommend applications don't use the `database` kwarg in `connected_to` diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 64473cbd7dbde..63983116502c6 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -2,6 +2,7 @@ * [CVE-2020-8162] Include Content-Length in signature for ActiveStorage direct upload + ## Rails 6.0.3 (May 06, 2020) ## * No changes. diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 8cc0df1333953..e08f2935adef5 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -11,6 +11,7 @@ * [CVE-2020-8165] Avoid Marshal.load on raw cache value in MemCacheStore + ## Rails 6.0.3 (May 06, 2020) ## * `Array#to_sentence` no longer returns a frozen string. From def6b627b834c6d66237d8a3886c49f5814d4c56 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Wed, 17 Jun 2020 13:45:18 -0500 Subject: [PATCH 054/244] Remove git merge artifact [ci skip] Follow-up to 5438067c81e983c134c6b948a5d4702f95936db4. --- activerecord/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 3413825a273a4..9cfb10cdb7de7 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -40,7 +40,6 @@ * No changes. ->>>>>>> 6-0-sec ## Rails 6.0.3.1 (May 18, 2020) ## * No changes. From 75f6539d0e94c76d93d61feef06c3b0974fe62c1 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 23 Jun 2020 00:01:18 +0900 Subject: [PATCH 055/244] Merge pull request #39697 from yahonda/another_ruby_16973 Use ActiveSupport::ToJsonWithActiveSupportEncoder#to_json for Ruby 2.8.0 --- activesupport/lib/active_support/core_ext/object/json.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/core_ext/object/json.rb b/activesupport/lib/active_support/core_ext/object/json.rb index 416059d17bc3a..02919c0985d33 100644 --- a/activesupport/lib/active_support/core_ext/object/json.rb +++ b/activesupport/lib/active_support/core_ext/object/json.rb @@ -45,7 +45,7 @@ def to_json(options = nil) end end -[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass, Enumerable].reverse_each do |klass| +[Enumerable, Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].reverse_each do |klass| klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder) end From 0793a144eca16b8c5828d2aee97fd4e2208fc8e9 Mon Sep 17 00:00:00 2001 From: "Eileen M. Uchitelle" Date: Thu, 25 Jun 2020 09:59:07 -0400 Subject: [PATCH 056/244] Merge pull request #39712 from arthurschreiber/arthur/use-subquery-for-information-schema Use a subquery when filtering `information_schema.tables` by `table_name`. --- .../connection_adapters/mysql/schema_statements.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb index 06572bb88ed20..b1b60846e60d6 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_statements.rb @@ -203,10 +203,14 @@ def add_options_for_index_columns(quoted_columns, **options) def data_source_sql(name = nil, type: nil) scope = quoted_scope(name, type: type) - sql = +"SELECT table_name FROM information_schema.tables" - sql << " WHERE table_schema = #{scope[:schema]}" - sql << " AND table_name = #{scope[:name]}" if scope[:name] - sql << " AND table_type = #{scope[:type]}" if scope[:type] + sql = +"SELECT table_name FROM (SELECT * FROM information_schema.tables " + sql << " WHERE table_schema = #{scope[:schema]}) _subquery" + if scope[:type] || scope[:name] + conditions = [] + conditions << "_subquery.table_type = #{scope[:type]}" if scope[:type] + conditions << "_subquery.table_name = #{scope[:name]}" if scope[:name] + sql << " WHERE #{conditions.join(" AND ")}" + end sql end From 457d9dc939f14ad810d05a8938b9e4d21cd619ea Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 26 Jun 2020 07:16:57 +0900 Subject: [PATCH 057/244] Merge pull request #39710 from colorbox/amend_cleanup_behavior_for_non_active_support_cache_files Fix an error for `FileStore.cleanup` when using Sprockets --- activesupport/lib/active_support/cache/file_store.rb | 3 ++- activesupport/test/cache/stores/file_store_test.rb | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index ff1d6793beb5c..cbce9d8915337 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -74,7 +74,8 @@ def delete_matched(matcher, options = nil) private def read_entry(key, **options) if File.exist?(key) - File.open(key) { |f| Marshal.load(f) } + entry = File.open(key) { |f| Marshal.load(f) } + entry if entry.is_a?(Cache::Entry) end rescue => e logger.error("FileStoreError (#{e}): #{e.message}") if logger diff --git a/activesupport/test/cache/stores/file_store_test.rb b/activesupport/test/cache/stores/file_store_test.rb index 2eb06cbe5e995..84feb6843ffb6 100644 --- a/activesupport/test/cache/stores/file_store_test.rb +++ b/activesupport/test/cache/stores/file_store_test.rb @@ -125,6 +125,14 @@ def test_cleanup_removes_all_expired_entries end end + def test_cleanup_when_non_active_support_cache_file_exists + cache_file_path = @cache.send(:normalize_key, "foo", nil) + FileUtils.makedirs(File.dirname(cache_file_path)) + File.atomic_write(cache_file_path, cache_dir) { |f| Marshal.dump({ "foo": "bar" }, f) } + assert_nothing_raised { @cache.cleanup } + assert_equal 1, Dir.glob(File.join(cache_dir, "**")).size + end + def test_write_with_unless_exist assert_equal true, @cache.write(1, "aaaaaaaaaa") assert_equal false, @cache.write(1, "aaaaaaaaaa", unless_exist: true) From af5cd95a4e7923ec0478ac0d7cdcff1c5b765a99 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Tue, 30 Jun 2020 17:56:31 +0100 Subject: [PATCH 058/244] Merge pull request #39694 from Shopify/routing-mapper-dedup Fix skip_parameter_encoding when controller and action params are frozen --- actionpack/lib/action_dispatch/http/parameters.rb | 2 +- actionpack/test/controller/parameter_encoding_test.rb | 2 +- actionpack/test/dispatch/routing_test.rb | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb index deb499a6a0de3..909132a05b01f 100644 --- a/actionpack/lib/action_dispatch/http/parameters.rb +++ b/actionpack/lib/action_dispatch/http/parameters.rb @@ -89,7 +89,7 @@ def set_binary_encoding(params, controller, action) return params unless controller && controller.valid_encoding? if binary_params_for?(controller, action) - ActionDispatch::Request::Utils.each_param_value(params) do |param| + ActionDispatch::Request::Utils.each_param_value(params.except(:controller, :action)) do |param| param.force_encoding ::Encoding::ASCII_8BIT end end diff --git a/actionpack/test/controller/parameter_encoding_test.rb b/actionpack/test/controller/parameter_encoding_test.rb index e2194e8974dbb..179c643922691 100644 --- a/actionpack/test/controller/parameter_encoding_test.rb +++ b/actionpack/test/controller/parameter_encoding_test.rb @@ -15,7 +15,7 @@ def test_bar end def test_all_values_encoding - render body: ::JSON.dump(params.values.map(&:encoding).map(&:name)) + render body: ::JSON.dump(params.except(:action, :controller).values.map(&:encoding).map(&:name)) end end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index d514c9316bb47..bb4c34ba6dc19 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -4538,10 +4538,14 @@ def show with_routing do |set| set.draw do get "/foo/show(/:id)", to: "test_invalid_urls/foo#show" + get "/bar/show(/:id)", controller: "test_invalid_urls/foo", action: "show" end get "/foo/show/%E2%EF%BF%BD%A6" assert_response :ok + + get "/bar/show/%E2%EF%BF%BD%A6" + assert_response :ok end end end From fecea8fe5d013941d7baf1a074651a61db1d75b2 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 17 Jun 2020 20:29:47 +0900 Subject: [PATCH 059/244] Merge pull request #39612 from kamipo/faster_attributes PERF: 45% faster attributes for readonly usage --- activemodel/lib/active_model/attribute.rb | 15 ++-- activemodel/lib/active_model/attribute_set.rb | 30 +++---- .../lib/active_model/attribute_set/builder.rb | 87 ++++++++++++++++--- activemodel/test/cases/attribute_set_test.rb | 6 ++ 4 files changed, 105 insertions(+), 33 deletions(-) diff --git a/activemodel/lib/active_model/attribute.rb b/activemodel/lib/active_model/attribute.rb index 75f60d205e953..7facc6cc75656 100644 --- a/activemodel/lib/active_model/attribute.rb +++ b/activemodel/lib/active_model/attribute.rb @@ -5,16 +5,16 @@ module ActiveModel class Attribute # :nodoc: class << self - def from_database(name, value, type) - FromDatabase.new(name, value, type) + def from_database(name, value_before_type_cast, type, value = nil) + FromDatabase.new(name, value_before_type_cast, type, nil, value) end - def from_user(name, value, type, original_attribute = nil) - FromUser.new(name, value, type, original_attribute) + def from_user(name, value_before_type_cast, type, original_attribute = nil) + FromUser.new(name, value_before_type_cast, type, original_attribute) end - def with_cast_value(name, value, type) - WithCastValue.new(name, value, type) + def with_cast_value(name, value_before_type_cast, type) + WithCastValue.new(name, value_before_type_cast, type) end def null(name) @@ -30,11 +30,12 @@ def uninitialized(name, type) # This method should not be called directly. # Use #from_database or #from_user - def initialize(name, value_before_type_cast, type, original_attribute = nil) + def initialize(name, value_before_type_cast, type, original_attribute = nil, value = nil) @name = name @value_before_type_cast = value_before_type_cast @type = type @original_attribute = original_attribute + @value = value unless value.nil? end def value diff --git a/activemodel/lib/active_model/attribute_set.rb b/activemodel/lib/active_model/attribute_set.rb index 2f5437ceda13e..138d74fd8d485 100644 --- a/activemodel/lib/active_model/attribute_set.rb +++ b/activemodel/lib/active_model/attribute_set.rb @@ -13,11 +13,11 @@ def initialize(attributes) end def [](name) - attributes[name] || Attribute.null(name) + @attributes[name] || default_attribute(name) end def []=(name, value) - attributes[name] = value + @attributes[name] = value end def values_before_type_cast @@ -25,9 +25,9 @@ def values_before_type_cast end def to_hash - initialized_attributes.transform_values(&:value) + keys.index_with { |name| self[name].value } end - alias_method :to_h, :to_hash + alias :to_h :to_hash def key?(name) attributes.key?(name) && self[name].initialized? @@ -42,35 +42,33 @@ def fetch_value(name, &block) end def write_from_database(name, value) - attributes[name] = self[name].with_value_from_database(value) + @attributes[name] = self[name].with_value_from_database(value) end def write_from_user(name, value) - attributes[name] = self[name].with_value_from_user(value) + @attributes[name] = self[name].with_value_from_user(value) end def write_cast_value(name, value) - attributes[name] = self[name].with_cast_value(value) + @attributes[name] = self[name].with_cast_value(value) end def freeze - @attributes.freeze + attributes.freeze super end def deep_dup - self.class.allocate.tap do |copy| - copy.instance_variable_set(:@attributes, attributes.deep_dup) - end + AttributeSet.new(attributes.deep_dup) end def initialize_dup(_) - @attributes = attributes.dup + @attributes = @attributes.dup super end def initialize_clone(_) - @attributes = attributes.clone + @attributes = @attributes.clone super end @@ -81,7 +79,7 @@ def reset(key) end def accessed - attributes.select { |_, attr| attr.has_been_read? }.keys + attributes.each_key.select { |name| self[name].has_been_read? } end def map(&block) @@ -97,8 +95,8 @@ def ==(other) attr_reader :attributes private - def initialized_attributes - attributes.select { |_, attr| attr.initialized? } + def default_attribute(name) + Attribute.null(name) end end end diff --git a/activemodel/lib/active_model/attribute_set/builder.rb b/activemodel/lib/active_model/attribute_set/builder.rb index 2b1c2206ecf01..86b0e64a68fb0 100644 --- a/activemodel/lib/active_model/attribute_set/builder.rb +++ b/activemodel/lib/active_model/attribute_set/builder.rb @@ -13,14 +13,86 @@ def initialize(types, default_attributes = {}) end def build_from_database(values = {}, additional_types = {}) - attributes = LazyAttributeHash.new(types, values, additional_types, default_attributes) - AttributeSet.new(attributes) + LazyAttributeSet.new(values, types, additional_types, default_attributes) end end end + class LazyAttributeSet < AttributeSet # :nodoc: + def initialize(values, types, additional_types, default_attributes, attributes = {}) + super(attributes) + @values = values + @types = types + @additional_types = additional_types + @default_attributes = default_attributes + @casted_values = {} + @materialized = false + end + + def key?(name) + (values.key?(name) || types.key?(name) || @attributes.key?(name)) && self[name].initialized? + end + + def keys + keys = values.keys | types.keys | @attributes.keys + keys.keep_if { |name| self[name].initialized? } + end + + def fetch_value(name, &block) + if attr = @attributes[name] + return attr.value(&block) + end + + @casted_values.fetch(name) do + value_present = true + value = values.fetch(name) { value_present = false } + + if value_present + type = additional_types.fetch(name, types[name]) + @casted_values[name] = type.deserialize(value) + else + attr = default_attribute(name, value_present, value) + attr.value(&block) + end + end + end + + protected + def attributes + unless @materialized + values.each_key { |key| self[key] } + types.each_key { |key| self[key] } + @materialized = true + end + @attributes + end + + private + attr_reader :values, :types, :additional_types, :default_attributes + + def default_attribute( + name, + value_present = true, + value = values.fetch(name) { value_present = false } + ) + type = additional_types.fetch(name, types[name]) + + if value_present + @attributes[name] = Attribute.from_database(name, value, type, @casted_values[name]) + elsif types.key?(name) + if attr = default_attributes[name] + @attributes[name] = attr.dup + else + @attributes[name] = Attribute.uninitialized(name, type) + end + else + Attribute.null(name) + end + end + end + class LazyAttributeHash # :nodoc: - delegate :transform_values, :each_key, :each_value, :fetch, :except, to: :materialize + delegate :transform_values, :each_value, :fetch, :except, to: :materialize def initialize(types, values, additional_types, default_attributes, delegate_hash = {}) @types = types @@ -57,14 +129,9 @@ def initialize_dup(_) super end - def select + def each_key(&block) keys = types.keys | values.keys | delegate_hash.keys - keys.each_with_object({}) do |key, hash| - attribute = self[key] - if yield(key, attribute) - hash[key] = attribute - end - end + keys.each(&block) end def ==(other) diff --git a/activemodel/test/cases/attribute_set_test.rb b/activemodel/test/cases/attribute_set_test.rb index 62feb9074e52c..b0b791b91fe85 100644 --- a/activemodel/test/cases/attribute_set_test.rb +++ b/activemodel/test/cases/attribute_set_test.rb @@ -219,6 +219,12 @@ def assert_valid_value(*) test "marshalling dump/load legacy materialized attribute hash" do builder = AttributeSet::Builder.new(foo: Type::String.new) + + def builder.build_from_database(values = {}, additional_types = {}) + attributes = LazyAttributeHash.new(types, values, additional_types, default_attributes) + AttributeSet.new(attributes) + end + attributes = builder.build_from_database(foo: "1") attributes.instance_variable_get(:@attributes).instance_eval do From ccbc2d055d6f70cd8ebe41d4fb81a230af796f8e Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 1 Jul 2020 20:56:29 +0900 Subject: [PATCH 060/244] Partly revert part of using new constant `LazyAttributeSet` The purpose of backporting #39612 is for `Marshal.load(record.dump)` forward compatibility. Actually we never said we would keep Mashal compatibility between two versions of Rails, so we sometimes directly added and removed the internal objects. Theoretically, removing objects will lose backward compatibility and adding objects will lose forward compatibility. Example: * Rails 4.2/4.1 lost forward/backward compatibility due to entirely changed object layout * Rails 5.0/4.2 lost backward compatibility due to removed `MysqlDateTime` * Rails 5.2/5.1 lost forward compatibility due to added `SQLite3Integer` * Rails 5.2/5.1 lost forward/backward compatibility due to added `Type::Json` and removed `MysqlJson`/`OID::Json` I'm not sure how much we should be aware of `Mashal.load` compatibility. Especially if we should keep perfectly forward compatibility, we almost have no chance to improve object layout (includes ivar usage). One possible idea to mitigate breaking forward compatibility is backporting new constant to the latest stable branch. --- activemodel/lib/active_model/attribute_set/builder.rb | 3 ++- activemodel/test/cases/attribute_set_test.rb | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/activemodel/lib/active_model/attribute_set/builder.rb b/activemodel/lib/active_model/attribute_set/builder.rb index 86b0e64a68fb0..a4933aa956d8e 100644 --- a/activemodel/lib/active_model/attribute_set/builder.rb +++ b/activemodel/lib/active_model/attribute_set/builder.rb @@ -13,7 +13,8 @@ def initialize(types, default_attributes = {}) end def build_from_database(values = {}, additional_types = {}) - LazyAttributeSet.new(values, types, additional_types, default_attributes) + attributes = LazyAttributeHash.new(types, values, additional_types, default_attributes) + AttributeSet.new(attributes) end end end diff --git a/activemodel/test/cases/attribute_set_test.rb b/activemodel/test/cases/attribute_set_test.rb index b0b791b91fe85..62feb9074e52c 100644 --- a/activemodel/test/cases/attribute_set_test.rb +++ b/activemodel/test/cases/attribute_set_test.rb @@ -219,12 +219,6 @@ def assert_valid_value(*) test "marshalling dump/load legacy materialized attribute hash" do builder = AttributeSet::Builder.new(foo: Type::String.new) - - def builder.build_from_database(values = {}, additional_types = {}) - attributes = LazyAttributeHash.new(types, values, additional_types, default_attributes) - AttributeSet.new(attributes) - end - attributes = builder.build_from_database(foo: "1") attributes.instance_variable_get(:@attributes).instance_eval do From b30da999c4a6d8ba76d5f02f67bfb0c9636e943e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Mon, 6 Jul 2020 17:40:17 -0400 Subject: [PATCH 061/244] Merge pull request #39793 from tiramizoo/forum Add link to forum --- guides/source/layout.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb index 72c676202e216..087be91344b40 100644 --- a/guides/source/layout.html.erb +++ b/guides/source/layout.html.erb @@ -38,7 +38,7 @@
  • Blog
  • Guides
  • API
  • -
  • Ask for help
  • +
  • Forum
  • Contribute on GitHub
  • From 84ce0763655febf0e81088c5546809d99ae8ab42 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 7 Jul 2020 17:34:46 +0900 Subject: [PATCH 062/244] Merge pull request #39795 from kamipo/type_casted_extra_select Type cast extra select for eager loading --- .../associations/join_dependency.rb | 20 +++++++++++++------ .../associations/join_dependency/join_part.rb | 4 ++-- .../test/cases/relation/select_test.rb | 20 ++++++++++++++++--- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index c92c6ad15dc57..30d6f99b0dd4d 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -106,8 +106,16 @@ def instantiate(result_set, &block) model_cache = Hash.new { |h, klass| h[klass] = {} } parents = model_cache[join_root] - column_aliases = aliases.column_aliases join_root - column_aliases += explicit_selections(column_aliases, result_set) + column_aliases = aliases.column_aliases(join_root) + column_names = explicit_selections(column_aliases, result_set) + + if column_names.empty? + column_types = {} + else + column_types = result_set.column_types + column_types = column_types.slice(*column_names) unless column_types.empty? + column_aliases += column_names.map! { |name| Aliases::Column.new(name, name) } + end message_bus = ActiveSupport::Notifications.instrumenter @@ -119,7 +127,7 @@ def instantiate(result_set, &block) message_bus.instrument("instantiation.active_record", payload) do result_set.each { |row_hash| parent_key = primary_key ? row_hash[primary_key] : row_hash - parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, &block) + parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, column_types, &block) construct(parent, join_root, row_hash, seen, model_cache) } end @@ -139,9 +147,9 @@ def apply_column_aliases(relation) def explicit_selections(root_column_aliases, result_set) root_names = root_column_aliases.map(&:name).to_set - result_set.columns - .reject { |n| root_names.include?(n) || n =~ /\At\d+_r\d+\z/ } - .map { |n| Aliases::Column.new(n, n) } + result_set.columns.each_with_object([]) do |name, result| + result << name unless /\At\d+_r\d+\z/.match?(name) || root_names.include?(name) + end end def aliases diff --git a/activerecord/lib/active_record/associations/join_dependency/join_part.rb b/activerecord/lib/active_record/associations/join_dependency/join_part.rb index 3ad72a3646bc9..cf551f78b0b5e 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_part.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_part.rb @@ -62,8 +62,8 @@ def extract_record(row, column_names_with_alias) hash end - def instantiate(row, aliases, &block) - base_klass.instantiate(extract_record(row, aliases), &block) + def instantiate(row, aliases, column_types = {}, &block) + base_klass.instantiate(extract_record(row, aliases), column_types, &block) end end end diff --git a/activerecord/test/cases/relation/select_test.rb b/activerecord/test/cases/relation/select_test.rb index 69a8d36b031b8..22ea45c72f476 100644 --- a/activerecord/test/cases/relation/select_test.rb +++ b/activerecord/test/cases/relation/select_test.rb @@ -25,19 +25,33 @@ def test_reselect_with_default_scope_select assert_equal expected, actual end + def test_type_casted_extra_select_with_eager_loading + posts = Post.select("posts.id * 1.1 AS foo").eager_load(:comments) + assert_equal 1.1, posts.first.foo + end + def test_aliased_select_using_as_with_joins_and_includes posts = Post.select("posts.id AS field_alias").joins(:comments).includes(:comments) - assert_includes posts.first.attributes, "field_alias" + assert_equal %w( + id author_id title body type comments_count taggings_with_delete_all_count taggings_with_destroy_count + tags_count indestructible_tags_count tags_with_destroy_count tags_with_nullify_count field_alias + ), posts.first.attributes.keys end def test_aliased_select_not_using_as_with_joins_and_includes posts = Post.select("posts.id field_alias").joins(:comments).includes(:comments) - assert_includes posts.first.attributes, "field_alias" + assert_equal %w( + id author_id title body type comments_count taggings_with_delete_all_count taggings_with_destroy_count + tags_count indestructible_tags_count tags_with_destroy_count tags_with_nullify_count field_alias + ), posts.first.attributes.keys end def test_star_select_with_joins_and_includes posts = Post.select("posts.*").joins(:comments).includes(:comments) - assert_not_includes posts.first.attributes, "posts.*" + assert_equal %w( + id author_id title body type comments_count taggings_with_delete_all_count taggings_with_destroy_count + tags_count indestructible_tags_count tags_with_destroy_count tags_with_nullify_count + ), posts.first.attributes.keys end end end From d5f958b9babb51b00aa611dd77363343fa63a5b9 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Wed, 8 Jul 2020 00:43:44 +0100 Subject: [PATCH 063/244] Merge pull request #39803 from jaredbeck/patch-6 Docs: config.hosts: details re: regexp anchors --- guides/source/configuring.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/guides/source/configuring.md b/guides/source/configuring.md index bb42e3048dd36..61da951ab8805 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -261,6 +261,10 @@ Every Rails application comes with a standard set of middleware which it uses in # `beta1.product.com`. Rails.application.config.hosts << /.*\.product\.com/ ``` + + The provided regexp will be wrapped with both anchors (`\A` and `\z`) so it + must match the entire hostname. `/product.com/`, for example, once anchored, + would fail to match `www.product.com`. A special case is supported that allows you to permit all sub-domains: From 83df9feb0ed5f3787c2e32b79a1d84b61c065c0e Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Sat, 20 Jun 2020 01:38:34 -0500 Subject: [PATCH 064/244] Merge pull request #39678 from santib/touch-all-documentation Documentation: Add touch_all to callbacks and validations guides [ci skip] --- activerecord/lib/active_record/relation.rb | 4 ++-- guides/source/active_record_callbacks.md | 1 + guides/source/active_record_validations.md | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 4794598d9a98f..b969fc5803002 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -497,8 +497,8 @@ def update_counters(counters) # :nodoc: update_all updates end - # Touches all records in the current relation without instantiating records first with the +updated_at+/+updated_on+ attributes - # set to the current time or the time specified. + # Touches all records in the current relation, setting the +updated_at+/+updated_on+ attributes to the current time or the time specified. + # It does not instantiate the involved models, and it does not trigger Active Record callbacks or validations. # This method can be passed attribute names and an optional time argument. # If attribute names are passed, they are updated along with +updated_at+/+updated_on+ attributes. # If no time argument is passed, the current time is used as default. diff --git a/guides/source/active_record_callbacks.md b/guides/source/active_record_callbacks.md index 31521bb90b305..8a83081206e40 100644 --- a/guides/source/active_record_callbacks.md +++ b/guides/source/active_record_callbacks.md @@ -247,6 +247,7 @@ Just as with validations, it is also possible to skip callbacks by using the fol * `delete_all` * `increment!` * `increment_counter` +* `touch_all` * `update_column` * `update_columns` * `update_all` diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md index e68f34dd5df66..234d97e9271d1 100644 --- a/guides/source/active_record_validations.md +++ b/guides/source/active_record_validations.md @@ -136,6 +136,7 @@ database regardless of its validity. They should be used with caution. * `increment_counter` * `toggle!` * `touch` +* `touch_all` * `update_all` * `update_attribute` * `update_column` From c9095561a12413ac9ea580a9446adba9475d230e Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Wed, 8 Jul 2020 12:17:43 +0100 Subject: [PATCH 065/244] Note that insert_all and friends skip callbacks and validations [ci skip] --- guides/source/active_record_callbacks.md | 6 ++++++ guides/source/active_record_validations.md | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/guides/source/active_record_callbacks.md b/guides/source/active_record_callbacks.md index 8a83081206e40..80e73faca2145 100644 --- a/guides/source/active_record_callbacks.md +++ b/guides/source/active_record_callbacks.md @@ -247,11 +247,17 @@ Just as with validations, it is also possible to skip callbacks by using the fol * `delete_all` * `increment!` * `increment_counter` +* `insert` +* `insert!` +* `insert_all` +* `insert_all!` * `touch_all` * `update_column` * `update_columns` * `update_all` * `update_counters` +* `upsert` +* `upsert_all` These methods should be used with caution, however, because important business rules and application logic may be kept in callbacks. Bypassing them without understanding the potential implications may lead to invalid data. diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md index 234d97e9271d1..7a04de98329ea 100644 --- a/guides/source/active_record_validations.md +++ b/guides/source/active_record_validations.md @@ -134,6 +134,10 @@ database regardless of its validity. They should be used with caution. * `decrement_counter` * `increment!` * `increment_counter` +* `insert` +* `insert!` +* `insert_all` +* `insert_all!` * `toggle!` * `touch` * `touch_all` @@ -142,6 +146,8 @@ database regardless of its validity. They should be used with caution. * `update_column` * `update_columns` * `update_counters` +* `upsert` +* `upsert_all` Note that `save` also has the ability to skip validations if passed `validate: false` as an argument. This technique should be used with caution. From af0181059afd92cb126f11a9c6704c007fc3636a Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Mon, 20 Jul 2020 17:05:23 +0100 Subject: [PATCH 066/244] Merge pull request #38979 from lorennorman/fix-invalid-mime-type Bugfix for Mime::Type::MimeTypeInvalid handling in ActionDispatch::DebugExceptions --- .../middleware/debug_exceptions.rb | 2 +- actionpack/test/dispatch/debug_exceptions_test.rb | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb index ac5131f7b999c..7f6d918446716 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb @@ -64,7 +64,7 @@ def render_exception(request, exception) begin content_type = request.formats.first rescue Mime::Type::InvalidMimeType - render_for_api_request(Mime[:text], wrapper) + content_type = Mime[:text] end if api_request?(content_type) diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb index 9911690f2bf35..64ceab56ef177 100644 --- a/actionpack/test/dispatch/debug_exceptions_test.rb +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -137,6 +137,7 @@ def call(env) DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp) InterceptedApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :default, [Interceptor]) BadInterceptedApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :default, [BadInterceptor]) + ApiApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api) test "skip diagnosis if not showing detailed exceptions" do @app = ProductionApp @@ -269,7 +270,7 @@ def call(env) end test "rescue with JSON error for JSON API request" do - @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api) + @app = ApiApp get "/", headers: { "action_dispatch.show_exceptions" => true }, as: :json assert_response 500 @@ -307,10 +308,16 @@ def call(env) assert_no_match(//, body) assert_equal "application/json", response.media_type assert_match(/ActionController::ParameterMissing/, body) + + get "/invalid_mimetype", headers: { "Accept" => "text/html,*", "action_dispatch.show_exceptions" => true }, as: :json + assert_response 406 + assert_no_match(//, body) + assert_equal "application/json", response.media_type + assert_match(/Mime::Type::InvalidMimeType/, body) end test "rescue with HTML format for HTML API request" do - @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api) + @app = ApiApp get "/index.html", headers: { "action_dispatch.show_exceptions" => true } assert_response 500 @@ -321,7 +328,7 @@ def call(env) end test "rescue with XML format for XML API requests" do - @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api) + @app = ApiApp get "/index.xml", headers: { "action_dispatch.show_exceptions" => true } assert_response 500 @@ -335,7 +342,7 @@ def call(env) ActionDispatch::IntegrationTest.register_encoder(:wibble, param_encoder: -> params { params }) - @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api) + @app = ApiApp get "/index", headers: { "action_dispatch.show_exceptions" => true }, as: :wibble assert_response 500 From 7d8cc2feb99b60cf0d2c76415b8b923246cca4a0 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Mon, 2 Dec 2019 11:52:54 +0100 Subject: [PATCH 067/244] Allow non-hash values in config files Fix: https://github.com/rails/rails/issues/37800 (cherry picked from commit 21c7199c0f0a0187298621631fbc3864c93ec8b9) --- railties/lib/rails/application.rb | 22 +++++++++---------- .../test/application/configuration_test.rb | 16 ++++++++++++++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 3a1794f42dbe7..9247fa827c970 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -220,27 +220,27 @@ def message_verifier(verifier_name) # config.middleware.use ExceptionNotifier, config_for(:exception_notification) # end def config_for(name, env: Rails.env) - if name.is_a?(Pathname) - yaml = name - else - yaml = Pathname.new("#{paths["config"].existent.first}/#{name}.yml") - end + yaml = name.is_a?(Pathname) ? name : Pathname.new("#{paths["config"].existent.first}/#{name}.yml") if yaml.exist? require "erb" - config = YAML.load(ERB.new(yaml.read).result) || {} - config = (config["shared"] || {}).merge(config[env] || {}) + all_configs = YAML.load(ERB.new(yaml.read).result) || {} + config, shared = all_configs[env], all_configs["shared"] - ActiveSupport::OrderedOptions.new.tap do |options| - options.update(NonSymbolAccessDeprecatedHash.new(config)) + config ||= {} if shared.nil? || shared.is_a?(Hash) + + if config.is_a?(Hash) + ActiveSupport::OrderedOptions.new.update(NonSymbolAccessDeprecatedHash.new(shared&.deep_merge(config) || config)) + else + config || shared end else raise "Could not load configuration. No such file - #{yaml}" end - rescue Psych::SyntaxError => e + rescue Psych::SyntaxError => error raise "YAML syntax error occurred while parsing #{yaml}. " \ "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \ - "Error: #{e.message}" + "Error: #{error.message}" end # Stores some of the Rails initial environment parameters which diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index e0bb51e7dc80d..8de87c0c700da 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -2055,6 +2055,22 @@ class D < C end end + test "config_for does not assume config is a hash" do + app_file "config/custom.yml", <<~RUBY + development: + - foo + - bar + RUBY + + add_to_config <<~RUBY + config.my_custom_config = config_for('custom') + RUBY + + app "development" + + assert_equal %w( foo bar ), Rails.application.config.my_custom_config + end + test "config_for uses the Pathname object if it is provided" do app_file "config/custom.yml", <<-RUBY development: From 22e5cacd788a9e8ec6221a0f4fb54312ffa88aa5 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 25 Dec 2019 17:57:14 +0900 Subject: [PATCH 068/244] `ruby2_keywords` for `method_missing` This fixes the following warnings: ``` /rails/railties/lib/rails/railtie.rb:190: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call /rails/railties/lib/rails/application.rb:222: warning: The called method `config_for' is defined here ``` --- railties/lib/rails/railtie.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb index 178c584f95fc0..7958018455f00 100644 --- a/railties/lib/rails/railtie.rb +++ b/railties/lib/rails/railtie.rb @@ -192,6 +192,7 @@ def method_missing(name, *args, &block) super end end + ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true) # receives an instance variable identifier, set the variable value if is # blank and append given block to value, which will be used later in From 54c507bcbcc259cb1304873dec72f3fa8d2d12aa Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Mon, 9 Sep 2019 22:25:05 +0900 Subject: [PATCH 069/244] Fix keyword arguments warnings --- railties/test/application/middleware/cache_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb index 3768d8ce2d67c..fa8590c41df49 100644 --- a/railties/test/application/middleware/cache_test.rb +++ b/railties/test/application/middleware/cache_test.rb @@ -38,7 +38,7 @@ def keeps_if_modified_since end private def render_conditionally(headers) - if stale?(headers.merge(public: !params[:private])) + if stale?(**headers.merge(public: !params[:private])) render plain: SecureRandom.hex(16) end end From dd6087c8f54d999678a8a94d94f2c90698ce5953 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sun, 26 Jul 2020 09:58:16 +0100 Subject: [PATCH 070/244] Merge pull request #39844 from deepredsky/redis-cache-bug Fix option not being passed with fetch_multi --- activesupport/CHANGELOG.md | 5 +++++ .../lib/active_support/cache/redis_cache_store.rb | 2 +- activesupport/test/cache/stores/redis_cache_store_test.rb | 8 ++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index ffaf40e8cce45..ea86018c1e050 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +* Fixed issue in `ActiveSupport::Cache::RedisCacheStore` not passing options + to `read_multi` causing `fetch_multi` to not work properly. + + *Rajesh Sharma* + * `with_options` copies its options hash again to avoid leaking mutations. Fixes #39343. diff --git a/activesupport/lib/active_support/cache/redis_cache_store.rb b/activesupport/lib/active_support/cache/redis_cache_store.rb index 37499ee4eb2d2..a2fd585355c21 100644 --- a/activesupport/lib/active_support/cache/redis_cache_store.rb +++ b/activesupport/lib/active_support/cache/redis_cache_store.rb @@ -347,7 +347,7 @@ def read_entry(key, **options) def read_multi_entries(names, **options) if mget_capable? - read_multi_mget(*names) + read_multi_mget(*names, **options) else super end diff --git a/activesupport/test/cache/stores/redis_cache_store_test.rb b/activesupport/test/cache/stores/redis_cache_store_test.rb index a7685e6f8f82b..22e3b829405e7 100644 --- a/activesupport/test/cache/stores/redis_cache_store_test.rb +++ b/activesupport/test/cache/stores/redis_cache_store_test.rb @@ -141,6 +141,14 @@ def test_fetch_multi_uses_redis_mget end end + def test_fetch_multi_with_namespace + assert_called_with(@cache.redis, :mget, ["custom-namespace:a", "custom-namespace:b", "custom-namespace:c"], returns: []) do + @cache.fetch_multi("a", "b", "c", namespace: "custom-namespace") do |key| + key * 2 + end + end + end + def test_fetch_multi_without_names assert_not_called(@cache.redis, :mget) do @cache.fetch_multi() { } From 99cd347a55fd9bddb458afd003e0f50c5b2ba29a Mon Sep 17 00:00:00 2001 From: "Eileen M. Uchitelle" Date: Fri, 20 Dec 2019 08:41:57 -0500 Subject: [PATCH 071/244] Merge pull request #38042 from eileencodes/update-read-query Refactor READ_QUERY and fix missing arguments --- .../connection_adapters/abstract_adapter.rb | 4 ++++ .../mysql/database_statements.rb | 2 +- .../postgresql/database_statements.rb | 2 +- .../sqlite3/database_statements.rb | 2 +- .../cases/adapters/mysql2/mysql2_adapter_test.rb | 7 +++++++ .../adapters/postgresql/postgresql_adapter_test.rb | 13 +++++++++++++ 6 files changed, 27 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index def1e625d438d..82cff5c70e8b8 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -103,7 +103,11 @@ def self.type_cast_config_to_boolean(config) end end + DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc: + private_constant :DEFAULT_READ_QUERY + def self.build_read_query_regexp(*parts) # :nodoc: + parts += DEFAULT_READ_QUERY parts = parts.map { |part| /#{part}/i } /\A(?:[\(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/ end diff --git a/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb index 4bfd36a13442d..32092b3142663 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb @@ -20,7 +20,7 @@ def query(sql, name = nil) # :nodoc: end READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp( - :begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :describe, :desc, :with + :desc, :describe, :set, :show, :use ) # :nodoc: private_constant :READ_QUERY diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb index 810f4757b4cc2..abe32472c0a35 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb @@ -68,7 +68,7 @@ def query(sql, name = nil) #:nodoc: end READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp( - :begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :with + :close, :declare, :fetch, :move, :set, :show ) # :nodoc: private_constant :READ_QUERY diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb index bffa499a84b98..fef8d1a693de1 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb @@ -5,7 +5,7 @@ module ConnectionAdapters module SQLite3 module DatabaseStatements READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp( - :begin, :commit, :explain, :select, :pragma, :release, :savepoint, :rollback, :with + :pragma ) # :nodoc: private_constant :READ_QUERY diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb index d27ca203d43b1..5f27976684561 100644 --- a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -257,6 +257,13 @@ def test_statement_timeout_error_codes end end + def test_doesnt_error_when_a_use_query_is_called_while_preventing_writes + @connection_handler.while_preventing_writes do + db_name = ActiveRecord::Base.configurations["arunit"][:database] + assert_nil @conn.execute("USE #{db_name}") + end + end + private def with_example_table(definition = "id int auto_increment primary key, number int, data varchar(255)", &block) super(@conn, "ex", definition, &block) diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index 2afd6820a8d4e..12cce48851ff1 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -458,6 +458,19 @@ def test_doesnt_error_when_a_read_query_with_leading_chars_is_called_while_preve end end + def test_doesnt_error_when_a_read_query_with_cursors_is_called_while_preventing_writes + with_example_table do + @connection_handler.while_preventing_writes do + @connection.transaction do + assert_equal [], @connection.execute("DECLARE cur_ex CURSOR FOR SELECT * FROM ex").entries + assert_equal [], @connection.execute("FETCH cur_ex").entries + assert_equal [], @connection.execute("MOVE cur_ex").entries + assert_equal [], @connection.execute("CLOSE cur_ex").entries + end + end + end + end + private def with_example_table(definition = "id serial primary key, number integer, data character varying(255)", &block) super(@connection, "ex", definition, &block) From e1a3aea1c796d4580c722cfe97030c041aa75ed2 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Mon, 27 Jul 2020 15:27:43 +0100 Subject: [PATCH 072/244] Fix MySQL USE statement preventing writes test This test broke when backported because the connection configuration only accepts symbol keys since ce9b197cc902ce8b72b7b3b5a3ec7e507fdba858. --- activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb index 5f27976684561..1e013e24a62f7 100644 --- a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -259,7 +259,7 @@ def test_statement_timeout_error_codes def test_doesnt_error_when_a_use_query_is_called_while_preventing_writes @connection_handler.while_preventing_writes do - db_name = ActiveRecord::Base.configurations["arunit"][:database] + db_name = ActiveRecord::Base.connection_config[:database] assert_nil @conn.execute("USE #{db_name}") end end From 74bea3666e544cbcf177263fd60d8a261bf62b00 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Tue, 28 Jul 2020 00:53:01 +0100 Subject: [PATCH 073/244] Skip foreign key rename table test on MariaDB This test first started to fail when MariaDB 10.4.13 was released. To fix the build, the `supports_rename_index?` guard was added in 185f935b188606108a7b19817e58153fd81f424d, which meant that the test was never run on MariaDB since the stable release was still 10.4. When MariaDB 10.5.4 was released and 10.5 became the stable release, the test was no longer skipped and started to fail again. It didn't fail on master because RENAME COLUMN is supported there, which doesn't trigger the problem. It looks like the failure is a consequence of fixing this issue: https://jira.mariadb.org/browse/MDEV-22465 --- activerecord/test/cases/migration/foreign_key_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index 0bedb2f5efc94..af574cd899918 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -93,7 +93,7 @@ def test_rename_column_of_child_table end def test_rename_reference_column_of_child_table - if current_adapter?(:Mysql2Adapter) && !@connection.send(:supports_rename_index?) + if current_adapter?(:Mysql2Adapter) && (!@connection.send(:supports_rename_index?) || @connection.mariadb?) skip "Cannot drop index, needed in a foreign key constraint" end From 2d6a726dcb3320ff021c05f3d908adbb2b2e335f Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Wed, 29 Jul 2020 21:21:13 +0100 Subject: [PATCH 074/244] Merge pull request #39771 from eugeneius/autosave_exactly_once Autosave collection associations exactly once --- activerecord/CHANGELOG.md | 6 ++++++ .../lib/active_record/autosave_association.rb | 18 +++++++++--------- .../test/cases/autosave_association_test.rb | 10 ++++++++++ activerecord/test/models/post.rb | 1 + 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 9cfb10cdb7de7..cc98601a5ba48 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* Prevent collection associations from being autosaved multiple times. + + Fixes #39173. + + *Eugene Kenny* + * Resolve issue with insert_all unique_by option when used with expression index. When the `:unique_by` option of `ActiveRecord::Persistence.insert_all` and diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index bb0d75656b18a..933a0557f05fa 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -29,7 +29,7 @@ module ActiveRecord # == Callbacks # # Association with autosave option defines several callbacks on your - # model (before_save, after_create, after_update). Please note that + # model (around_save, before_save, after_create, after_update). Please note that # callbacks are executed in the order they were defined in # model. You should avoid modifying the association content, before # autosave callbacks are executed. Placing your callbacks after @@ -180,8 +180,7 @@ def add_autosave_association_callbacks(reflection) save_method = :"autosave_associated_records_for_#{reflection.name}" if reflection.collection? - before_save :before_save_collection_association - after_save :after_save_collection_association + around_save :around_save_collection_association define_non_cyclic_method(save_method) { save_collection_association(reflection) } # Doesn't use after_save as that would save associations added in after_create/after_update twice @@ -358,14 +357,15 @@ def normalize_reflection_attribute(indexed_attribute, reflection, index, attribu end end - # Is used as a before_save callback to check while saving a collection + # Is used as an around_save callback to check while saving a collection # association whether or not the parent was a new record before saving. - def before_save_collection_association - @new_record_before_save ||= new_record? - end + def around_save_collection_association + previously_new_record_before_save = (@new_record_before_save ||= false) + @new_record_before_save = !previously_new_record_before_save && new_record? - def after_save_collection_association - @new_record_before_save = false + yield + ensure + @new_record_before_save = previously_new_record_before_save end # Saves any new associated records, or all loaded autosave associations if diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 1b423b6df81ac..05f2a3db36a01 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -6,6 +6,7 @@ require "models/bird" require "models/post" require "models/comment" +require "models/category" require "models/company" require "models/contract" require "models/customer" @@ -820,6 +821,15 @@ def test_autosave_new_record_with_after_create_callback assert_not_nil post.author_id end + + def test_autosave_new_record_with_after_create_callback_and_habtm_association + post = PostWithAfterCreateCallback.new(title: "Captain Murphy", body: "is back") + post.comments.build(body: "foo") + post.categories.build(name: "bar") + post.save! + + assert_equal 1, post.categories.reload.length + end end class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 50c0dddcf2ff8..3451eaf2e35d9 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -288,6 +288,7 @@ class PostWithAfterCreateCallback < ActiveRecord::Base self.inheritance_column = :disabled self.table_name = "posts" has_many :comments, foreign_key: :post_id + has_and_belongs_to_many :categories, foreign_key: :post_id after_create do |post| update_attribute(:author_id, comments.first.id) From b6f78f558eeb9d555b974dcb5b683f05fd57cf73 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 3 Aug 2020 19:14:36 +0900 Subject: [PATCH 075/244] Merge pull request #39967 from kamipo/fix_or_with_sti_relation Avoid implicit `create_with` for `StiClass.all` --- activerecord/lib/active_record/core.rb | 1 - activerecord/lib/active_record/relation.rb | 5 ++++- activerecord/test/cases/relation/or_test.rb | 5 +++++ activerecord/test/models/post.rb | 4 ++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index f2bf1780b8d0e..b011722fa4f03 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -296,7 +296,6 @@ def relation if finder_needs_type_condition? && !ignore_default_scope? relation.where!(type_condition) - relation.create_with!(inheritance_column.to_s => sti_name) else relation end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index b969fc5803002..065ace4cc8946 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -671,7 +671,10 @@ def where_values_hash(relation_table_name = klass.table_name) end def scope_for_create - where_values_hash.merge!(create_with_value.stringify_keys) + hash = where_values_hash + hash.delete(klass.inheritance_column) if klass.finder_needs_type_condition? + create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty? + hash end # Returns true if relation needs eager loading. diff --git a/activerecord/test/cases/relation/or_test.rb b/activerecord/test/cases/relation/or_test.rb index 26fe7adf8f421..cf9d59745f8b0 100644 --- a/activerecord/test/cases/relation/or_test.rb +++ b/activerecord/test/cases/relation/or_test.rb @@ -110,6 +110,11 @@ def test_or_inside_named_scope assert_equal expected, Post.order(id: :desc).typographically_interesting end + def test_or_with_sti_relation + expected = Post.where("id = 1 or id = 2").sort_by(&:id) + assert_equal expected, Post.where(id: 1).or(SpecialPost.all).sort_by(&:id) + end + def test_or_on_loaded_relation expected = Post.where("id = 1 or id = 2").to_a p = Post.where("id = 1") diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 3451eaf2e35d9..b6b0b7b3776a9 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -357,6 +357,10 @@ def predicate_builder Post.predicate_builder end + def finder_needs_type_condition? + false + end + def base_class? true end From 79af891f3e17091d6ee46712ad1fd58243b212a6 Mon Sep 17 00:00:00 2001 From: Lawrence Chou Date: Tue, 4 Aug 2020 12:26:27 +0800 Subject: [PATCH 076/244] Fix attaching blobs via nested attributes Closes #37411. --- .../lib/active_storage/attached/changes/create_one.rb | 2 +- activestorage/test/models/attached/one_test.rb | 7 +++++++ activestorage/test/test_helper.rb | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/activestorage/lib/active_storage/attached/changes/create_one.rb b/activestorage/lib/active_storage/attached/changes/create_one.rb index f242574b46eb5..753203dae8da6 100644 --- a/activestorage/lib/active_storage/attached/changes/create_one.rb +++ b/activestorage/lib/active_storage/attached/changes/create_one.rb @@ -58,7 +58,7 @@ def find_or_build_blob filename: attachable.original_filename, content_type: attachable.content_type when Hash - ActiveStorage::Blob.build_after_unfurling(**attachable) + ActiveStorage::Blob.build_after_unfurling(**attachable.symbolize_keys) when String ActiveStorage::Blob.find_signed(attachable) else diff --git a/activestorage/test/models/attached/one_test.rb b/activestorage/test/models/attached/one_test.rb index 7e810edf2c992..0034e9d6d9fda 100644 --- a/activestorage/test/models/attached/one_test.rb +++ b/activestorage/test/models/attached/one_test.rb @@ -286,6 +286,13 @@ class ActiveStorage::OneAttachedTest < ActiveSupport::TestCase assert_equal 2736, @user.avatar.metadata[:height] end + test "creating an attachment as part of an autosave association through nested attributes" do + group = Group.create!(users_attributes: [{ name: "John", avatar: { io: StringIO.new("STUFF"), filename: "town.jpg", content_type: "image/jpg" } }]) + group.save! + new_user = User.find_by(name: "John") + assert new_user.avatar.attached? + end + test "updating an attachment as part of an autosave association" do group = Group.create!(users: [@user]) @user.avatar = fixture_file_upload("racecar.jpg") diff --git a/activestorage/test/test_helper.rb b/activestorage/test/test_helper.rb index 150b8c10fc60b..6734f73ab1c53 100644 --- a/activestorage/test/test_helper.rb +++ b/activestorage/test/test_helper.rb @@ -101,6 +101,8 @@ class User < ActiveRecord::Base class Group < ActiveRecord::Base has_one_attached :avatar has_many :users, autosave: true + + accepts_nested_attributes_for :users end require_relative "../../tools/test_common" From 45081c989b3108a629a26d0dde5d21eb06dbd8fb Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 29 May 2020 15:07:11 +0900 Subject: [PATCH 077/244] Reset statement cache for association if table_name is changed Related to #27953. All statement caches should be owned by the klass, otherwise cannot be aware of table_name is changed. Fixes #36453. --- activerecord/CHANGELOG.md | 6 ++++++ .../lib/active_record/associations/association.rb | 5 ++--- activerecord/lib/active_record/core.rb | 10 +++++----- activerecord/lib/active_record/reflection.rb | 10 ++++------ activerecord/test/cases/statement_cache_test.rb | 13 +++++++++++++ 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index cc98601a5ba48..f8c6fda9b4530 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* Reset statement cache for association if `table_name` is changed. + + Fixes #36453. + + *Ryuta Kamizono* + * Prevent collection associations from being autosaved multiple times. Fixes #39173. diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index cac4b4c22c6b7..61962fbb0baea 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -204,14 +204,13 @@ def find_target scope = self.scope return scope.to_a if skip_statement_cache?(scope) - conn = klass.connection - sc = reflection.association_scope_cache(conn, owner) do |params| + sc = reflection.association_scope_cache(klass, owner) do |params| as = AssociationScope.create { params.bind } target_scope.merge!(as.scope(self)) end binds = AssociationScope.get_bind_values(owner, reflection.chain) - sc.execute(binds, conn) { |record| set_inverse_instance(record) } || [] + sc.execute(binds, klass.connection) { |record| set_inverse_instance(record) } || [] end # The scope for this association. diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index b011722fa4f03..d5a2dbc34f76d 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -285,12 +285,12 @@ def _internal? # :nodoc: false end - private - def cached_find_by_statement(key, &block) - cache = @find_by_statement_cache[connection.prepared_statements] - cache.compute_if_absent(key) { StatementCache.create(connection, &block) } - end + def cached_find_by_statement(key, &block) # :nodoc: + cache = @find_by_statement_cache[connection.prepared_statements] + cache.compute_if_absent(key) { StatementCache.create(connection, &block) } + end + private def relation relation = Relation.create(self) diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index b875f88637f58..0f5eca8769c2c 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "active_support/core_ext/string/filters" -require "concurrent/map" module ActiveRecord # = Active Record Reflection @@ -432,19 +431,18 @@ def initialize(name, scope, options, active_record) @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type") @foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type") @constructable = calculate_constructable(macro, options) - @association_scope_cache = Concurrent::Map.new if options[:class_name] && options[:class_name].class == Class raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string." end end - def association_scope_cache(conn, owner, &block) - key = conn.prepared_statements + def association_scope_cache(klass, owner, &block) + key = self if polymorphic? key = [key, owner._read_attribute(@foreign_type)] end - @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) } + klass.cached_find_by_statement(key, &block) end def constructable? # :nodoc: @@ -510,7 +508,7 @@ def collect_join_chain # This is for clearing cache on the reflection. Useful for tests that need to compare # SQL queries on associations. def clear_association_scope_cache # :nodoc: - @association_scope_cache.clear + klass.initialize_find_by_cache end def nested? diff --git a/activerecord/test/cases/statement_cache_test.rb b/activerecord/test/cases/statement_cache_test.rb index 6a6d73dc38f8c..0423e611733e2 100644 --- a/activerecord/test/cases/statement_cache_test.rb +++ b/activerecord/test/cases/statement_cache_test.rb @@ -136,5 +136,18 @@ def test_find_does_not_use_statement_cache_if_table_name_is_changed ensure Book.table_name = :books end + + def test_find_association_does_not_use_statement_cache_if_table_name_is_changed + salty = Liquid.create(name: "salty") + molecule = salty.molecules.create(name: "dioxane") + + assert_equal salty, molecule.liquid + + Liquid.table_name = :birds + + assert_nil molecule.reload_liquid + ensure + Liquid.table_name = :liquid + end end end From 34dc7c39f20882a81a510126ad96b90c2845dbb6 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 17 Aug 2020 12:35:34 +0900 Subject: [PATCH 078/244] Merge pull request #40056 from kamipo/fix_preloader_associate_by_default Fix preloader to associate preloaded records by default --- .../active_record/associations/preloader.rb | 8 ++++++-- .../associations/preloader/association.rb | 19 ++++++++----------- .../preloader/through_association.rb | 2 +- activerecord/test/cases/associations_test.rb | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb index e1f4049163d6e..17c664299276b 100644 --- a/activerecord/lib/active_record/associations/preloader.rb +++ b/activerecord/lib/active_record/associations/preloader.rb @@ -94,6 +94,10 @@ def preload(records, associations, preload_scope = nil) end end + def initialize(associate_by_default: true) + @associate_by_default = associate_by_default + end + private # Loads all the given data into +records+ for the +association+. def preloaders_on(association, records, scope, polymorphic_parent = false) @@ -142,7 +146,7 @@ def preloaders_for_one(association, records, scope, polymorphic_parent) def preloaders_for_reflection(reflection, records, scope) records.group_by { |record| record.association(reflection.name).klass }.map do |rhs_klass, rs| - preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope).run + preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope, @associate_by_default).run end end @@ -157,7 +161,7 @@ def grouped_records(association, records, polymorphic_parent) end class AlreadyLoaded # :nodoc: - def initialize(klass, owners, reflection, preload_scope) + def initialize(klass, owners, reflection, preload_scope, associate_by_default = true) @owners = owners @reflection = reflection end diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index c973e0c3afea1..4876c02a5993f 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -4,25 +4,22 @@ module ActiveRecord module Associations class Preloader class Association #:nodoc: - def initialize(klass, owners, reflection, preload_scope) + def initialize(klass, owners, reflection, preload_scope, associate_by_default = true) @klass = klass @owners = owners.uniq(&:__id__) @reflection = reflection @preload_scope = preload_scope + @associate = associate_by_default || !preload_scope || preload_scope.empty_scope? @model = owners.first && owners.first.class end def run - if !preload_scope || preload_scope.empty_scope? - owners.each do |owner| - associate_records_to_owner(owner, records_by_owner[owner] || []) - end - else - # Custom preload scope is used and - # the association can not be marked as loaded - # Loading into a Hash instead - records_by_owner - end + records = records_by_owner + + owners.each do |owner| + associate_records_to_owner(owner, records[owner] || []) + end if @associate + self end diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index bec1c4c94a473..8c01870c91132 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -4,7 +4,7 @@ module ActiveRecord module Associations class Preloader class ThroughAssociation < Association # :nodoc: - PRELOADER = ActiveRecord::Associations::Preloader.new + PRELOADER = ActiveRecord::Associations::Preloader.new(associate_by_default: false) def initialize(*) super diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb index cefb43a8b5ff2..47038feef01b4 100644 --- a/activerecord/test/cases/associations_test.rb +++ b/activerecord/test/cases/associations_test.rb @@ -347,8 +347,23 @@ def test_requires_symbol_argument end end +class PreloaderTest < ActiveRecord::TestCase + fixtures :posts, :comments + + def test_preload_with_scope + post = posts(:welcome) + + preloader = ActiveRecord::Associations::Preloader.new + preloader.preload([post], :comments, Comment.where(body: "Thank you for the welcome")) + + assert_predicate post.comments, :loaded? + assert_equal [comments(:greetings)], post.comments + end +end + class GeneratedMethodsTest < ActiveRecord::TestCase fixtures :developers, :computers, :posts, :comments + def test_association_methods_override_attribute_methods_of_same_name assert_equal(developers(:david), computers(:workstation).developer) # this next line will fail if the attribute methods module is generated lazily From c2a705d1477b580fa54b603ef145bb136cc4a909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Wed, 8 Jan 2020 11:45:53 -0300 Subject: [PATCH 079/244] Merge pull request #38118 from mkrfowler/reduce_preloaded_records Reduce the number of records loaded when preloading across a `has_one` --- .../associations/preloader/association.rb | 37 ++++++++++++---- .../cascaded_eager_loading_test.rb | 42 +++++++++++++++++++ activerecord/test/models/author.rb | 3 ++ 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 4876c02a5993f..63be11fc72431 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -24,23 +24,42 @@ def run end def records_by_owner - # owners can be duplicated when a relation has a collection association join - # #compare_by_identity makes such owners different hash keys - @records_by_owner ||= preloaded_records.each_with_object({}.compare_by_identity) do |record, result| - owners_by_key[convert_key(record[association_key_name])].each do |owner| - (result[owner] ||= []) << record - end - end + load_records unless defined?(@records_by_owner) + + @records_by_owner end def preloaded_records - return @preloaded_records if defined?(@preloaded_records) - @preloaded_records = owner_keys.empty? ? [] : records_for(owner_keys) + load_records unless defined?(@preloaded_records) + + @preloaded_records end private attr_reader :owners, :reflection, :preload_scope, :model, :klass + def load_records + # owners can be duplicated when a relation has a collection association join + # #compare_by_identity makes such owners different hash keys + @records_by_owner = {}.compare_by_identity + raw_records = owner_keys.empty? ? [] : records_for(owner_keys) + + @preloaded_records = raw_records.select do |record| + assignments = [] + + owners_by_key[convert_key(record[association_key_name])].each do |owner| + entries = (@records_by_owner[owner] ||= []) + + if reflection.collection? || entries.empty? + entries << record + assignments << record + end + end + + !assignments.empty? + end + end + # The name of the key on the associated records def association_key_name reflection.join_primary_key(klass) diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index 055a62b2bcaf6..002962c3f9243 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -200,4 +200,46 @@ def test_preloaded_records_are_not_duplicated assert_equal expected, actual end + + def test_preloading_across_has_one_constrains_loaded_records + author = authors(:david) + + old_post = author.posts.create!(title: "first post", body: "test") + old_post.comments.create!(author: authors(:mary), body: "a response") + + recent_post = author.posts.create!(title: "first post", body: "test") + last_comment = recent_post.comments.create!(author: authors(:bob), body: "a response") + + authors = Author.where(id: author.id) + retrieved_comments = [] + + reset_callbacks(Comment, :initialize) do + Comment.after_initialize { |record| retrieved_comments << record } + authors.preload(recent_post: :comments).load + end + + assert_equal 1, retrieved_comments.size + assert_equal [last_comment], retrieved_comments + end + + def test_preloading_across_has_one_through_constrains_loaded_records + author = authors(:david) + + old_post = author.posts.create!(title: "first post", body: "test") + old_post.comments.create!(author: authors(:mary), body: "a response") + + recent_post = author.posts.create!(title: "first post", body: "test") + recent_post.comments.create!(author: authors(:bob), body: "a response") + + authors = Author.where(id: author.id) + retrieved_authors = [] + + reset_callbacks(Author, :initialize) do + Author.after_initialize { |record| retrieved_authors << record } + authors.preload(recent_response: :author).load + end + + assert_equal 2, retrieved_authors.size + assert_equal [author, authors(:bob)], retrieved_authors + end end diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index 6b7522eb179e8..5b12505d86489 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -160,6 +160,9 @@ def ratings has_many :posts_with_signature, ->(record) { where("posts.title LIKE ?", "%by #{record.name.downcase}%") }, class_name: "Post" has_many :posts_mentioning_author, ->(record = nil) { where("posts.body LIKE ?", "%#{record&.name&.downcase}%") }, class_name: "Post" + has_one :recent_post, -> { order(id: :desc) }, class_name: "Post" + has_one :recent_response, through: :recent_post, source: :comments + has_many :posts_with_extension, -> { order(:title) }, class_name: "Post" do def extension_method; end end From 57a4eade265d45c7fb73d70ab9137086c7e41a36 Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Thu, 20 Aug 2020 18:00:44 -0300 Subject: [PATCH 080/244] Merge pull request #40047 from mehagar/plugins_docs Fix markdown syntax error in docs [ci skip] --- guides/source/plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/source/plugins.md b/guides/source/plugins.md index d008dc1d8d633..9db5af4e5c669 100644 --- a/guides/source/plugins.md +++ b/guides/source/plugins.md @@ -391,7 +391,7 @@ class ActsAsYaffleTest < ActiveSupport::TestCase end ``` -Run the test to make sure the last two tests fail with an error that contains "NoMethodError: undefined method `squawk'", +Run the test to make sure the last two tests fail with an error that contains "NoMethodError: undefined method \`squawk'", then update `acts_as_yaffle.rb` to look like this: ```ruby From 5bc24ed2b232454d74e94be97c75f289a09e8935 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sat, 22 Aug 2020 12:39:32 +0900 Subject: [PATCH 081/244] Fix keyword argument warning for Ruby 2.6 https://buildkite.com/rails/rails/builds/71112#a57253a9-6088-4f76-ad75-0df8cf3ba356/1006-1014 --- activerecord/lib/active_record/validations/associated.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/validations/associated.rb b/activerecord/lib/active_record/validations/associated.rb index 2112a6d7b6973..dc89df4be7539 100644 --- a/activerecord/lib/active_record/validations/associated.rb +++ b/activerecord/lib/active_record/validations/associated.rb @@ -5,7 +5,7 @@ module Validations class AssociatedValidator < ActiveModel::EachValidator #:nodoc: def validate_each(record, attribute, value) if Array(value).reject { |r| valid_object?(r) }.any? - record.errors.add(attribute, :invalid, **options.merge(value: value)) + record.errors.add(attribute, :invalid, options.merge(value: value)) end end From 3fed62cfb1f43d8df5a5ff31229a5ad03264186e Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Fri, 17 Jan 2020 11:12:32 -0800 Subject: [PATCH 082/244] Reduce FILENAME_MAX_SIZE to accomodate large PIDs The max size here is designed around Ruby's Dir::Tmpname.create which creates temporary filenames in the format $TIMESTAMP-$PID-$RANDOM I believe the previous value of this field was based on the assumption that PIDs are 1-65535, which isn't necessarily the case on 64 bit Linux systems, which can be up to 2**22. $ uname -a Linux zergling 5.4.11-arch1-1 #1 SMP PREEMPT Sun, 12 Jan 2020 12:15:27 +0000 x86_64 GNU/Linux $ cat /proc/sys/kernel/pid_max 4194304 I've chosen a new value based on what I believe the largest possible tempname is: 255 - "20200117-4194304-#{0x100000000.to_s(36)}.lock".length #=> 226 (cherry picked from commit a98f330fb138fe4a78c270788218309849440026) --- activesupport/lib/active_support/cache/file_store.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index cbce9d8915337..8b248efd14deb 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -16,7 +16,7 @@ class FileStore < Store attr_reader :cache_path DIR_FORMATTER = "%03X" - FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write) + FILENAME_MAX_SIZE = 226 # max filename size on file system is 255, minus room for timestamp, pid, and random characters appended by Tempfile (used by atomic write) FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room GITKEEP_FILES = [".gitkeep", ".keep"].freeze From c63b42f789bef01ea34ceaaacaf19388d1e0fde9 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sun, 23 Aug 2020 09:17:53 +0100 Subject: [PATCH 083/244] Add missing require for Enumerable#index_with Followup to fecea8fe5d013941d7baf1a074651a61db1d75b2. Fixes the Active Model isolated tests: https://buildkite.com/rails/rails/builds/71159#0fa6804a-8adc-4439-aa8f-466265712eba/944-972 --- activemodel/lib/active_model/attribute_set.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activemodel/lib/active_model/attribute_set.rb b/activemodel/lib/active_model/attribute_set.rb index 138d74fd8d485..ae0c02348c03b 100644 --- a/activemodel/lib/active_model/attribute_set.rb +++ b/activemodel/lib/active_model/attribute_set.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require "active_support/core_ext/enumerable" require "active_support/core_ext/object/deep_dup" require "active_model/attribute_set/builder" require "active_model/attribute_set/yaml_encoder" From 60776ef70242d354c449a56a6375fd1313e926c5 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 26 Aug 2020 11:20:21 +0900 Subject: [PATCH 084/244] Revert "Merge pull request #39769 from kamipo/backport_new_constant_for_forward_compatibility" This reverts commit 7376d2e1874708978ea7c388d1144e75c263cc37, reversing changes made to 6dd78c595ebb70342e7d0ec472d5cd03208230cb. --- activemodel/lib/active_model/attribute.rb | 15 ++-- activemodel/lib/active_model/attribute_set.rb | 31 +++---- .../lib/active_model/attribute_set/builder.rb | 84 ++----------------- 3 files changed, 31 insertions(+), 99 deletions(-) diff --git a/activemodel/lib/active_model/attribute.rb b/activemodel/lib/active_model/attribute.rb index 7facc6cc75656..75f60d205e953 100644 --- a/activemodel/lib/active_model/attribute.rb +++ b/activemodel/lib/active_model/attribute.rb @@ -5,16 +5,16 @@ module ActiveModel class Attribute # :nodoc: class << self - def from_database(name, value_before_type_cast, type, value = nil) - FromDatabase.new(name, value_before_type_cast, type, nil, value) + def from_database(name, value, type) + FromDatabase.new(name, value, type) end - def from_user(name, value_before_type_cast, type, original_attribute = nil) - FromUser.new(name, value_before_type_cast, type, original_attribute) + def from_user(name, value, type, original_attribute = nil) + FromUser.new(name, value, type, original_attribute) end - def with_cast_value(name, value_before_type_cast, type) - WithCastValue.new(name, value_before_type_cast, type) + def with_cast_value(name, value, type) + WithCastValue.new(name, value, type) end def null(name) @@ -30,12 +30,11 @@ def uninitialized(name, type) # This method should not be called directly. # Use #from_database or #from_user - def initialize(name, value_before_type_cast, type, original_attribute = nil, value = nil) + def initialize(name, value_before_type_cast, type, original_attribute = nil) @name = name @value_before_type_cast = value_before_type_cast @type = type @original_attribute = original_attribute - @value = value unless value.nil? end def value diff --git a/activemodel/lib/active_model/attribute_set.rb b/activemodel/lib/active_model/attribute_set.rb index ae0c02348c03b..2f5437ceda13e 100644 --- a/activemodel/lib/active_model/attribute_set.rb +++ b/activemodel/lib/active_model/attribute_set.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "active_support/core_ext/enumerable" require "active_support/core_ext/object/deep_dup" require "active_model/attribute_set/builder" require "active_model/attribute_set/yaml_encoder" @@ -14,11 +13,11 @@ def initialize(attributes) end def [](name) - @attributes[name] || default_attribute(name) + attributes[name] || Attribute.null(name) end def []=(name, value) - @attributes[name] = value + attributes[name] = value end def values_before_type_cast @@ -26,9 +25,9 @@ def values_before_type_cast end def to_hash - keys.index_with { |name| self[name].value } + initialized_attributes.transform_values(&:value) end - alias :to_h :to_hash + alias_method :to_h, :to_hash def key?(name) attributes.key?(name) && self[name].initialized? @@ -43,33 +42,35 @@ def fetch_value(name, &block) end def write_from_database(name, value) - @attributes[name] = self[name].with_value_from_database(value) + attributes[name] = self[name].with_value_from_database(value) end def write_from_user(name, value) - @attributes[name] = self[name].with_value_from_user(value) + attributes[name] = self[name].with_value_from_user(value) end def write_cast_value(name, value) - @attributes[name] = self[name].with_cast_value(value) + attributes[name] = self[name].with_cast_value(value) end def freeze - attributes.freeze + @attributes.freeze super end def deep_dup - AttributeSet.new(attributes.deep_dup) + self.class.allocate.tap do |copy| + copy.instance_variable_set(:@attributes, attributes.deep_dup) + end end def initialize_dup(_) - @attributes = @attributes.dup + @attributes = attributes.dup super end def initialize_clone(_) - @attributes = @attributes.clone + @attributes = attributes.clone super end @@ -80,7 +81,7 @@ def reset(key) end def accessed - attributes.each_key.select { |name| self[name].has_been_read? } + attributes.select { |_, attr| attr.has_been_read? }.keys end def map(&block) @@ -96,8 +97,8 @@ def ==(other) attr_reader :attributes private - def default_attribute(name) - Attribute.null(name) + def initialized_attributes + attributes.select { |_, attr| attr.initialized? } end end end diff --git a/activemodel/lib/active_model/attribute_set/builder.rb b/activemodel/lib/active_model/attribute_set/builder.rb index a4933aa956d8e..2b1c2206ecf01 100644 --- a/activemodel/lib/active_model/attribute_set/builder.rb +++ b/activemodel/lib/active_model/attribute_set/builder.rb @@ -19,81 +19,8 @@ def build_from_database(values = {}, additional_types = {}) end end - class LazyAttributeSet < AttributeSet # :nodoc: - def initialize(values, types, additional_types, default_attributes, attributes = {}) - super(attributes) - @values = values - @types = types - @additional_types = additional_types - @default_attributes = default_attributes - @casted_values = {} - @materialized = false - end - - def key?(name) - (values.key?(name) || types.key?(name) || @attributes.key?(name)) && self[name].initialized? - end - - def keys - keys = values.keys | types.keys | @attributes.keys - keys.keep_if { |name| self[name].initialized? } - end - - def fetch_value(name, &block) - if attr = @attributes[name] - return attr.value(&block) - end - - @casted_values.fetch(name) do - value_present = true - value = values.fetch(name) { value_present = false } - - if value_present - type = additional_types.fetch(name, types[name]) - @casted_values[name] = type.deserialize(value) - else - attr = default_attribute(name, value_present, value) - attr.value(&block) - end - end - end - - protected - def attributes - unless @materialized - values.each_key { |key| self[key] } - types.each_key { |key| self[key] } - @materialized = true - end - @attributes - end - - private - attr_reader :values, :types, :additional_types, :default_attributes - - def default_attribute( - name, - value_present = true, - value = values.fetch(name) { value_present = false } - ) - type = additional_types.fetch(name, types[name]) - - if value_present - @attributes[name] = Attribute.from_database(name, value, type, @casted_values[name]) - elsif types.key?(name) - if attr = default_attributes[name] - @attributes[name] = attr.dup - else - @attributes[name] = Attribute.uninitialized(name, type) - end - else - Attribute.null(name) - end - end - end - class LazyAttributeHash # :nodoc: - delegate :transform_values, :each_value, :fetch, :except, to: :materialize + delegate :transform_values, :each_key, :each_value, :fetch, :except, to: :materialize def initialize(types, values, additional_types, default_attributes, delegate_hash = {}) @types = types @@ -130,9 +57,14 @@ def initialize_dup(_) super end - def each_key(&block) + def select keys = types.keys | values.keys | delegate_hash.keys - keys.each(&block) + keys.each_with_object({}) do |key, hash| + attribute = self[key] + if yield(key, attribute) + hash[key] = attribute + end + end end def ==(other) From b20bbe723d9e2340b84805967bcaf2efddc01d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Wed, 26 Aug 2020 16:08:55 -0400 Subject: [PATCH 085/244] Merge pull request #39350 from jaynetics/fix_rounding_of_custom_formatted_negative_amounts Fix rounding of custom-formatted negative amounts --- .../number_helper/number_to_currency_converter.rb | 10 +++------- activesupport/test/number_helper_test.rb | 6 ++++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb b/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb index 4b8d267b4eff8..c0efababa9fdb 100644 --- a/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb @@ -9,15 +9,11 @@ class NumberToCurrencyConverter < NumberConverter # :nodoc: def convert number = self.number.to_s.strip - number_f = number.to_f format = options[:format] - if number_f.negative? - number = number_f.abs - - unless options[:precision] == 0 && number < 0.5 - format = options[:negative_format] - end + if number.sub!(/^-/, "") && + (options[:precision] != 0 || number.to_f > 0.5) + format = options[:negative_format] end rounded_number = NumberToRoundedConverter.convert(number, options) diff --git a/activesupport/test/number_helper_test.rb b/activesupport/test/number_helper_test.rb index 12f3bfef650fd..b527dffa85cc1 100644 --- a/activesupport/test/number_helper_test.rb +++ b/activesupport/test/number_helper_test.rb @@ -78,6 +78,12 @@ def test_number_to_currency assert_equal("1,234,567,890.50 - Kč", number_helper.number_to_currency("-1234567890.50", unit: "Kč", format: "%n %u", negative_format: "%n - %u")) assert_equal("0.00", number_helper.number_to_currency(+0.0, unit: "", negative_format: "(%n)")) assert_equal("$0", number_helper.number_to_currency(-0.456789, precision: 0)) + assert_equal("$1,11", number_helper.number_to_currency("1,11")) + assert_equal("$0,11", number_helper.number_to_currency("0,11")) + assert_equal("$,11", number_helper.number_to_currency(",11")) + assert_equal("-$1,11", number_helper.number_to_currency("-1,11")) + assert_equal("-$0,11", number_helper.number_to_currency("-0,11")) + assert_equal("-$,11", number_helper.number_to_currency("-,11")) end end From 35cbecb97a6e48a56421e0cdc1ffc8c999036dcc Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 1 Sep 2020 17:45:31 +0900 Subject: [PATCH 086/244] Merge pull request #40151 from kamipo/return_time_after_save Should not accidentally return decorated time object after `changes_applied` --- activerecord/lib/active_record/type/time.rb | 10 ++++++++++ activerecord/test/cases/type/time_test.rb | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/activerecord/lib/active_record/type/time.rb b/activerecord/lib/active_record/type/time.rb index f4da1ecf2c643..4e4f2acc63c49 100644 --- a/activerecord/lib/active_record/type/time.rb +++ b/activerecord/lib/active_record/type/time.rb @@ -16,6 +16,16 @@ def serialize(value) value end end + + private + def cast_value(value) + case value = super + when Value + value.__getobj__ + else + value + end + end end end end diff --git a/activerecord/test/cases/type/time_test.rb b/activerecord/test/cases/type/time_test.rb index 1a2c47479fec9..5aeaefd16e06c 100644 --- a/activerecord/test/cases/type/time_test.rb +++ b/activerecord/test/cases/type/time_test.rb @@ -11,11 +11,17 @@ def test_default_year_is_correct topic = Topic.new(bonus_time: { 4 => 10, 5 => 30 }) assert_equal expected_time, topic.bonus_time + assert_instance_of ::Time, topic.bonus_time topic.save! + + assert_equal expected_time, topic.bonus_time + assert_instance_of ::Time, topic.bonus_time + topic.reload assert_equal expected_time, topic.bonus_time + assert_instance_of ::Time, topic.bonus_time end end end From 49e13b226c1265b96119e115fd9380d50ad49fa9 Mon Sep 17 00:00:00 2001 From: sandstrom Date: Mon, 31 Aug 2020 16:31:30 +0200 Subject: [PATCH 087/244] Escape # in RFC 5987 pattern --- .../lib/action_dispatch/http/content_disposition.rb | 4 ++-- actionpack/test/dispatch/content_disposition_test.rb | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/content_disposition.rb b/actionpack/lib/action_dispatch/http/content_disposition.rb index 58164c15225d8..89b5bb2fa6a00 100644 --- a/actionpack/lib/action_dispatch/http/content_disposition.rb +++ b/actionpack/lib/action_dispatch/http/content_disposition.rb @@ -14,13 +14,13 @@ def initialize(disposition:, filename:) @filename = filename end - TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/ + TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!\#$+.^_`|~-]/ def ascii_filename 'filename="' + percent_escape(I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"' end - RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/ + RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!\#$&+.^_`|~-]/ def utf8_filename "filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR) diff --git a/actionpack/test/dispatch/content_disposition_test.rb b/actionpack/test/dispatch/content_disposition_test.rb index 3f5959da6e31b..6e1aae24fef95 100644 --- a/actionpack/test/dispatch/content_disposition_test.rb +++ b/actionpack/test/dispatch/content_disposition_test.rb @@ -28,6 +28,14 @@ class ContentDispositionTest < ActiveSupport::TestCase assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s end + test "encoding a filename with permitted chars" do + disposition = Http::ContentDisposition.new(disposition: :inline, filename: "argh+!#$-123_|&^`~.jpg") + + assert_equal %(filename="argh+!\#$-123_|%26^`~.jpg"), disposition.ascii_filename + assert_equal "filename*=UTF-8''argh+!\#$-123_|&^`~.jpg", disposition.utf8_filename + assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s + end + test "without filename" do disposition = Http::ContentDisposition.new(disposition: :inline, filename: nil) From 732ea1628cf46121e8ea287dd6a506f72db87502 Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Wed, 9 Sep 2020 14:41:31 -0400 Subject: [PATCH 088/244] Merge pull request from GHSA-cfjv-5498-mph5 Prior to this commit, when a translation key indicated that the translation text was HTML, the value returned by `I18n.translate` would always be marked as `html_safe`. However, the value returned by `I18n.translate` could be an untrusted value directly from `options[:default]`. This commit ensures values directly from `options[:default]` are not marked as `html_safe`. Co-authored-by: Jonathan Hefner --- .../lib/action_view/helpers/translation_helper.rb | 12 +++++++++++- actionview/test/template/translation_helper_test.rb | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb index f75e713b472ab..960c3f65c4f76 100644 --- a/actionview/lib/action_view/helpers/translation_helper.rb +++ b/actionview/lib/action_view/helpers/translation_helper.rb @@ -76,13 +76,20 @@ def translate(key, **options) if html_safe_translation_key?(key) html_safe_options = options.dup + options.except(*I18n::RESERVED_KEYS).each do |name, value| unless name == :count && value.is_a?(Numeric) html_safe_options[name] = ERB::Util.html_escape(value.to_s) end end + + html_safe_options[:default] = MISSING_TRANSLATION unless html_safe_options[:default].blank? + translation = I18n.translate(scope_key_by_partial(key), **html_safe_options.merge(raise: i18n_raise)) - if translation.respond_to?(:map) + + if translation.equal?(MISSING_TRANSLATION) + options[:default].first + elsif translation.respond_to?(:map) translation.map { |element| element.respond_to?(:html_safe) ? element.html_safe : element } else translation.respond_to?(:html_safe) ? translation.html_safe : translation @@ -121,6 +128,9 @@ def localize(object, **options) alias :l :localize private + MISSING_TRANSLATION = Object.new + private_constant :MISSING_TRANSLATION + def scope_key_by_partial(key) stringified_key = key.to_s if stringified_key.first == "." diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb index 4e6c6df285f5f..47e1e1871bbe7 100644 --- a/actionview/test/template/translation_helper_test.rb +++ b/actionview/test/template/translation_helper_test.rb @@ -217,6 +217,13 @@ def test_translate_with_last_default_not_named_html assert_equal false, translation.html_safe? end + def test_translate_does_not_mark_unsourced_string_default_as_html_safe + untrusted_string = "" + translation = translate(:"translations.missing", default: [:"translations.missing_html", untrusted_string]) + assert_equal untrusted_string, translation + assert_not_predicate translation, :html_safe? + end + def test_translate_with_string_default translation = translate(:'translations.missing', default: "A Generic String") assert_equal "A Generic String", translation From 9e9929e3d545999e51df746288dcea595728dc07 Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Wed, 9 Sep 2020 14:42:25 -0400 Subject: [PATCH 089/244] Merge pull request from GHSA-cfjv-5498-mph5 Prior to this commit, when a translation key indicated that the translation text was HTML, the value returned by `I18n.translate` would always be marked as `html_safe`. However, the value returned by `I18n.translate` could be an untrusted value directly from `options[:default]`. This commit ensures values directly from `options[:default]` are not marked as `html_safe`. Co-authored-by: Jonathan Hefner From a17cb9f8914a88d4fed0a31ef7baaa2a2a78f474 Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Wed, 9 Sep 2020 14:44:14 -0400 Subject: [PATCH 090/244] Merge pull request from GHSA-cfjv-5498-mph5 Prior to this commit, when a translation key indicated that the translation text was HTML, the value returned by `I18n.translate` would always be marked as `html_safe`. However, the value returned by `I18n.translate` could be an untrusted value directly from `options[:default]`. This commit ensures values directly from `options[:default]` are not marked as `html_safe`. Co-authored-by: Jonathan Hefner From 33b70ca393d62d5f67462a22b7d5c9d1f7b924dd Mon Sep 17 00:00:00 2001 From: Vincent Robert Date: Wed, 16 Sep 2020 16:18:53 +0200 Subject: [PATCH 091/244] Generate a preview without print margins When a PDF is used for both printing and displaying. It will most likely contain a crop box in order to hide print margins when displaying the PDF. Use Poppler's parameter to automatically use the crop box (visible box) rather than the media box (printable box) in order to remove those margins when drawing the PDF. See https://manpages.debian.org/testing/poppler-utils/pdftoppm.1.en.html --- activestorage/CHANGELOG.md | 7 ++++++ .../previewer/poppler_pdf_previewer.rb | 2 +- activestorage/test/fixtures/files/cropped.pdf | Bin 0 -> 14127 bytes activestorage/test/models/preview_test.rb | 13 +++++++++++ .../test/previewer/mupdf_previewer_test.rb | 21 +++++++++++++----- .../previewer/poppler_pdf_previewer_test.rb | 21 +++++++++++++----- 6 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 activestorage/test/fixtures/files/cropped.pdf diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index b3c541bc10080..5a4b93bfa4b31 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,10 @@ +* The Poppler PDF previewer renders a preview image using the original + document's crop box rather than its media box, hiding print margins. This + matches the behavior of the MuPDF previewer. + + *Vincent Robert* + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb b/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb index 6bf501a6074e0..f0599e3e15143 100644 --- a/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb +++ b/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb @@ -29,7 +29,7 @@ def preview private def draw_first_page_from(file, &block) # use 72 dpi to match thumbnail dimensions of the PDF - draw self.class.pdftoppm_path, "-singlefile", "-r", "72", "-png", file.path, &block + draw self.class.pdftoppm_path, "-singlefile", "-cropbox", "-r", "72", "-png", file.path, &block end end end diff --git a/activestorage/test/fixtures/files/cropped.pdf b/activestorage/test/fixtures/files/cropped.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8a54a1008df20ac78bcc95ad9fd68f1e87c35a87 GIT binary patch literal 14127 zcmbt*1yq!6&^EEs(wz&^xyu4ecXxM4cXx+`gc8!ypooC9ARQ6{(%py%NF$y9;;V0d zf1LC0;qdIv-ZgVyGyB~0TtlZSDa{6EhoI4YTt8ahF8+}>^05bv3kU)_o7tfW3IaJ4 zEuE}AY=GP_kvfn=+Sb9t(hYWXF!ivMv^00NumlPVqq%#yS(-Yc`M|SiqG&Q|g19&} zK|GL2h!%(ks#*!sW|Y@L(dp9|!IEW@S7u{mQW{ia><2Idl<-i5VVzoSl5 z5FV)%g%c0MyFjyaviLP9?A`rZ?iX->g>v10cmIy_Z>!Ywb+H6;sG3^;{O@MzNF$gK70^ zp8I~kt)c4XY_4JH0W^S3CMgZ%kaL7hDgNs!@#`uFGy-zys+ieXntK56Z7Amm210+% zCM~6Jls5CmXL6EaCXyhF*UaY^8GQehLWkfJrI1aDNJ>7TMu_tOE(E; zM;B+Odz6)C`!X9hV!tvnlZ18oSIk_5%p6-IQa{_B+PPSbtwZluC~N5K$wT@Jeh;HfArP9NnLOpomPEr}JsFRU`BbE=T<@wDzG zY?2`;fHYC#E4_=8k4gqdiq=o;ktUU4T>#iK%Rzo^TXE$gQ+j|fjUFu*HqVU=l**Tx zqJXC%*8uf8!{@8`N7*B?Xd30}SL@Z!ioe!J+0i0M0?Po^25k?ka(H{iN2*vCKkY=0 zn_7wzF(62a@*rfeF(@F3Cm!*#L@SUyY=2+B&N5q85Oc2yUT9p;>R1Oz0j&b`3UMJP zaut-AH-HOI14IlRCVSqM=v(|e9AWN>_NT{WT4Jz8_Mz^)Ba6#o?A99@d23XMNWCFO zbiV)~g5?u(9&3~5Z#d`PU-gNK5{`X>X&Rm&dZG5gdJxG}Twzv?y}Tb+oY{kkMig*O ztIF>|A&Z8d<z~>kdeP;u^_y1-zz#-wn%87SJM z3ZMw*%{9&S6XAr!yIMOc_TV2JQs6UuwzzVY;p(iiVg_P`5`9Qg+*zcOt^axmWH92rp zkwPg>bIT3tFRk~)0L-lo7ZNZHPd%I25(i9!bl zCE_UEsa_C;03egOJH2vAHo{a#Vp_rmi^$)XV9RJus5j8y9AuFu>Ia=L=c$j3x9 zE7EYJVN@PPD^U;F)DcqZ-&;k}196(szU2m3d_TVlC0U!mOE1ckSr0ubp^^V`#L!e( z#=g@8l+sPGV_PV5eIz3QbIt?Vkl~P#It0fQGpYysC*;^XH)trnw2A9#*E+InHUVGBRZf5MW4?E2NT?K-?>v9y%CYN4(q zu6Onx0}I@*7dLYc*;%#O>F5lso@-Lz01+?|WR&I5G?_0ysQ5SHV149i6Dr(0K_2+B zH%{BCdo$X@W4^0~`ka+Zj|dI4(Kl4}z1K%hY_Ne9aUcG3Ee^ONBS^qdlR&#)b*-=w-AgefDv59TJDtALLK*e?N zIx?^?vIuLx8V<>I$jxzmS6QewA-U>%w8~U7`L=&vXOZ+Pt!~>jjizlJ?dT}E?m+x^ zeSQpTmXhsaD}D9G%~-9rY50x>!X$x2gTCOEmwEC2-})3WW`VvRxX(%&E`=fjAE^Uk z_yne)GZRx@IvsJC%)vW!d!N(&@9*%oY zC{s4Jt^BhKzl>p=nT%>SGbTF=ZELN6U6rlFhNoEps(Q~U1Qy`vfT}=D(n=-k8gnN zFFlJH4P6%=!j_uw1P;kVG7IyIOS_*_$)V7oiKn;0d*sEp_3O%J7XuA9c-U2}HhnnJ zxiuhsht;A7fGh(1& zI>)n0D&u*zme28}v#K#QLw1>T-WRF{zF?E?Yl(KL0NmT=QY8_>X+4?fU~=`Yw_1ly0dHq25T3&_Gyu;KMkCSqTUBqUGlAtf?Kcz>1Su2?9b3?#wE zg*WY}R8}{4%0J=!wpvJuf-jC=w)?)x|NO&Stc3G}@uQ5Qm1BX}oOPDus*n`jRN^Uo zeU7J_3}d2tKI(LmqN{+{>~oA?Z2AJ-{8i|_r+u_(877Oi(_YMhW&*$|k2{Y7P9oWM zg+^X9Qin69>1^3kv72~xwFWoHqA81EM(6|~>=zLvKl-Ro<&~O8LUa0@M5436B?|b% z5;)?aJvflSS!OrCCA|4)^Sx}?t^O&(c8%rRFcp-6hgY|^qHl7aeJdP2frKQf3ZDXftYtX111&j3X|m|L?MYTYSNxz?k=Vl<6pi4<)mQ_j z&~)N5YVhZxFuoM+@}?Z8Iu>!*?AzEFIci+31J$@v(sq_6HIRpN|9Fyl#mj9_H&aRe zzn(B^>Gs0kO)^tGye3vHFouBo$kE*t792>xmNMMNurgM;%8*>y+|@ z_H0E*UCPgjoeUHgQ4^T6l>zt)Ksvha7ezp}YR@sdK!cg^G*VWBK<`iZ$E}S3+P$_f z#N^TYYbaw4Sj)6&o#Hp!2}&y8SWZ)cUD2W;fJ~WiL;~4<%9=@MxzIatngrzhGf#)1 z%_OHizc3-_x?($+cPySj(@?W>+GNzRY3jJ7*k%1ghAVvatMTX%PSh29R{+&icc2bP zH7o@X;HkB-mN=^D{IruL3R=ow=B`FyAv6>Hp@Ek^`9r)rdX=*H^Yw6GXzCA`;^Pc` z-$hYv!Zja+_A?0ez|lqUaePH^?Ymjm2-Z1pwn3r63um8EZ4mOtjg0xmB@?BfJ|d2R zRBkiBXN$tB+TbCKqe=;{lFf{wd2mBi{RT~ts30*fK3iRYj79%W5At9cKk^|3Q@pm4 zOe+56$6h{d)6TF-9Y7bs`XUbO9u*}yT1wmQObX%Bj#JS=MqhDH+Y~H##n4C7lx?g|0_S%*{oT-XRtswCWgM zxl@PH7{#KrtT7$aX&5&6Fg>J+YBjN?wAg4#G{Sr7DVwO4`rP}*@sRIGgXzpbgnpWp zJsGLMw4`VDG*dTEra>s^sUO^t3(CmC%IFZ_@m#31BdwX(R88d{XzAG+gpGM-2|e!7 zgvU|E4n?L{bn!0OHS+9;MW$)CYJR!0WGxVM?eky}&w?2TB`!qUMtisMv<&6!W`!He zT?cI;HQJsu|6NM^9)#aO4zPeou%oxs$mHWhcEKHNwddL`UO~eAiK%Z24z-~%zD2=Q zZ#%N@>?W^HwXVisKkR{#3cTBE*tWZ&*o03xEl#Kv9i7pw=kfVJwd(J-TdQX6HPn32 z#=MaVRJaEhKCpw# zva()G?I%6kH$#h3Dcv@4_Dw)T>QsF5=IXls$b2DHJuvU-Rsc<&Ai})7QVzfF4$c67 zT-;0@og^ZddYq2;RXRv zaTG(SFNNZc~0`h#eim*m0<*?8X_c{GvvEI&dsr+9o8=!O!}t zN5F18Lqw&!uno&RM0ssO5xkX$f}Emz((||x_g_drU)-eIoi%?ikXnVd!jg5K35>Wk3OHOwn zgHNxqLW7rd54A%{G7X4;065AVe)F(69U`Bcrgm57-3d$zZR^^u5_6nMbry=PSV?SH zKh9ZEu{fFG`e^(?)@!XGDB#KzofWt8g%=Jy4YoeQY~;S1lJ&&v@j)S@fT?&BYLqdk z$oCDEs&&_!g`jbgS`jUULphs$vPM#z1W{ncjf3$O-;(vC`jx&pxB21x&$z6G688sc zhR_{q_KNL*ptA=7bKz1RZ|E%g%@v;Rn3>rdO#22DWUqddoTi7JmN*bD7SqrMA3YEv zLidw)P~Jts6{n})DJX+~Ae45*_9$ppjNyK5(EzTg*zOjc7*?H_!8CNXv>4Vjy^Ux? zv@Y-NJS&5nZvzd4@1AZ;(_q@+!EQRmfb9s;qr%2iUBm{`YcnykaP>ljoy4lx`tn+^ zQvf!0=p7>Gcx}>ub7J?|qWc6A7Z;T0cT(wRZs%WFB{2B^BdzpT5($k%($dS;+)~EP z)b}6hCg30GrvJxu(mxW0yGDUN1l^NVH24Kt!pyZ=N$U9a=h*mjG)!Ub=9=;ffiDGR zO#<^v4m8P%@SnYDM^mfhL9#1BG7vSO4E_G(9Ns46mDXr-f==P;DvK&AeM|xnmHq?t zlb6*HUri0w*|#N^eJXnI+w=_gq5Uk#RZ~+0qFE8=%Yx z1LLYI@muPYHtj;SzJWoe!Y!!Gs0vrvk<(>#5gG9_&%C6+y?dU|rIe!|1KcQQLi5Ua zUYb*03-`fR*jF1w`h!)HhPxMV*%PgfD=*3p;Blwk5TD;hDYXi2_ea(vNfAKcF+Yn! z3)v?E3N)77yo@)AQ5Enp0=#veC_ALzrU_h1;y~dacC@QJ=ZT`8wY7UkOhh9uP60+l zAL5mBlz4k1^)V4o)C4It*ZzrF{YC70t1E6l3W?8&0<_Sv-$aZ(MB4zPW+pI`ve|>} zATkJfU>B3~MHhzpTXhMuF2hH)<$EKf!Gwil+7E3WeI`)ZTwltyE~;G}0S~^QKRKn8 zb=91RL~uSq^0INV85!8ZyJPad>Y(DsrcmuGV=^>eoAuYnkLlVxE}vZ`X&NQl+sWUk zz}!D3sK+e(^!f8=R#!D)-o}Ue9L_~0m&&?9J$OT-sW)6@<2nls0lrSAR!YtTd{qwa zAQ$1z<*uW(;f9mL^GahANAuC5g@Sd0GMl6zVi9{jsw9fmXQrRfI~qLSLDb>7<@*@0#YK+pQm>9r8YQ)9}~6zZGD46V`ue)?Ez4xE1L zzLgX@i7JZSW!V%-tQ>1ZrrM8+RH7h76FqUZXdZ%J<@PMI^2a$}&g>P^ZwOXqriEpd zaTz>psV&QDo-F<0=GIf(sN^uAxSE;<={LuTnfS!_VBuPH$md3STLzbnEUBRNA(h*k6YLr<(hJlLw~y}C%;dpWvlvTo0;=) z%Dk@3IPS#lgRCoCV}?5aXRE+Bg+tH3CvNyaeF=xnL!f8uE&&*7zD+zR-%~f?&8LDR zI-B&(u7gIfGJk+ylOx8&-bjzQ;1Q?!KD%o_U!LEs+Py`ZBPRP=_a1G{nv&sNI+7Fp z45e#}L+~yKd+s#3i~ct5rpR=dUTIVU+k3~Ad40@sg}64s7es4JFNU7dh4X!bVm83N z%jYOVtgG{=zk77<>HBaI(^6?BTu^ey5wbQ9k6IFLaV(@9vECT2rQFR$%mREU89 zb*A>6TzIrZM&bHM<42!0J!8!|2-e$|x3S{B9|N4W!XBXCieaHW3zR|;>?ZrMKR7sO zcu>oPd3y&uHN-eM{uo4b_VS!xwj2+9s9x*V8WS5EFKgRUS&p~JEPHB5kpDQ)EU9l^ zl!TWlge%K4@0(v3z(~Rwb8um^{BrtX%;FsxrQ;P|ZSeF#r;WJCZ?T}*aSWT@ta@At(sPC38o&iC}G#arU` zJa?S^L9~XAVY(0|z8kr`@WrRIjRb?+E4)<9UDk$D6q;)G2p}L?`bNVjOqkL zdC072JBc5unWtrfK^czX%!0fm7t^gHhCOW%oM&Ai40cKg`&=M0kuCn#)cb}4xin1P z=S)JLFnjEkMk^+JJl}C6aL4(H8T9euNu|K`3!IKfHxRY5Pmd#u`T2WeovPB~(eB3O zogAm`nU=VkSLwtXv$yUpofEx?z1eCd+pMMEY}0S11tv3T)iZ%2k1qGzY&R`7tr&?k zX8`=zlq}}My45q7g80VIA4mI^mp`1S3?#Pp$)8jhIhi|qUEJ@znumdsAjkRaq`~m( zDqBjjKFfk)LN*li)cZo8%)q1-S!X7atAGqe{0Z7iQRGf@ONV^A*xmLg4Ono%s<*iW zYaRq5J>KTxRhg6xxz#!jOzC{W1ayd9Mc-NsRN!WVE*?2`SP!~i2}w0%tW+XM*nD2+ z?KU7(NrebM+@O*WA9)DK7mHBJLtL%mJZ+{Ma9WL{i{8_J9OD_7d}LEjwRT*V&_P9O z(ji8!%Omw}P>oCTX@|SXB~)k^b*(AD+w(!5JiSkh%N2v}i9e~d0XpG!yPa%gDUL*@ z5-1GF_2y}oYxA*JpNnd@C+P;Fmylz0QBYh(qp00Z+rlthOCfcJGbiTP zkH|$cGpU#-og?VG2ugY<0**3!iG`h!**)?_S=)(qK9mOox?E>ou4?1qM*{d^`bvF_ zTZ4qY+TS7&k8GG!SRbKC!CHIdLdWV=cIX&;GZShKAr~u32!eC)je97ayg{Ul+h=QI zwDnvKJ~Ap<_VReQ))l-t*%%w4P>8qiO9W2R<(PRc!j;`v=bKyZ3@_`pCAb@jpswK(;k;qAs zCrKSWNx6W^^WC1>ytOQNn_WILo@J52GFgdyf>O~(4Sjy})lN**j-rqDO(%a3ovSwfL@MO=wQp2Ur7tk-S?BBF9OP*Z z!-ggN93{CO^f=I2<^+qh)p#R*urbX{0*)lz;yK&`ngsKRogSSE>tGK0mejQ)+K@mS zPG$q)%)qoe?pjVQ@>dh=9lDz(wx$DiW^SbT(QF4T|9Xd6g{imblII<#0Hz=X&Lh~f zr)cXwEqjewbXtm;YK0cJHGT>HjK>dPDvlDatw?*;trZo%WYRNVW=}AmE>(?7>!P@! zJR^32POpF?KRAkGT1g!H9~aX+z#pJeBYcn|@A;Z@nEUw|zr)hx~OJ;{Q4ASeb{(= zm$hUj^2m6k`GEy&yvBPMj6586vtZO}K?JYqR;Yb=<6a0g=sG;xql1uXT zMo1f&%h;in7p6(TEOR>GHqD`~VHS0wTWU<+KBF3_(O{=kL5sqg1dbF)2inBc7inq0 zb!t9Q&yGAYVP^I4Vm4^zKmDGp9$(^>dSki&Rlpcv+(sti`&K|dxw{2U*yPgt(~_>X zUKB)9VmIFrAx~aD$d)^C>EI&YvCXr&Tk#XeBNnI=V3=BJ61zNKonC;sMyxvRc#sB_ z*;pNw0tJuvy5L;3?mBj|v489u|3UXqfe((7tHHNMjq0HBtaX8-$dazcr4#i-W40$ z9HWUOw^zupN$RbAO(yDUX`W%N<(h20tTShRWS%ATwZ<-ne3+fuOSj&f04&F8}c!G;g!kR9R1rzF<9*JlssGyOA-y|7B23?xE^jD@BN{dX&K z{ac^l?eH}-5?jYly?-)xz+Oys68EN%CE;)phhpRS#d(CG59y=#NSMmc8J(jLb_tKU zkl#ytsWQ!06Yp3_>T1mJ z{5OpKSK+e!fk*b41$5KM%bGQP&H~g)I3B`-Q0)NMoDE<5wG4t&lVeX|q(YG|tv}+S zwRe=H4(BedKei(_Wkyhiob-d=RS6X#lMR{0SqfJJYoK=Z!78CQrhsntS5ckFcf>k^3Zz&ZobvVfBh!}?c2%&WGuW`nf< zW>JDZ@BN9AftbDJK{Q2ly*nqAmmD2mRl8Q`xEB zni{i&QNu0JmJwVUAl)&kA1ZK6K$ZZY7A+T|iVzu2?JheTPluYM)cRtaJ?efr_m8E_n_j);*^To7p4hb}xU)2fTV zx7}fgi#PD`41pLM9#a>-ebveeAagE>Fmc@?l#%g9wx{NFk3GbqX`Z!BmEL{oE;x|} zDnW|`hbA@2BN#+aw2qLhQPWMrc?ak}PGRDV1alJRqZX9WtbMF-I4%Ch()1}kjs9ys zsooGtGgnSrlj>3?-D+VRAm1>ZZpFGV0NJudQ!W#3{fu#Z{5(q$4uqd!GPpsX?-0!? zg-@~2%xm%|5Hk!y1hXGcZeXm(uD} zAI0J0T8!r)qL2#bR4I5mJ;w~2#NBf8-Cez@Z#EZgv&)o08aG0HepgzD^gF{jVsSZo z%MLqb94&-!r?mPnDQa3%wBTwTkwn*5%T)G(a7Pc|YL~KpP)0f!Cw=^a!GIpSv*X|n zpKH&~vI)J)4Rh{qi{v}Y7}&eg7I;l068cDv0AeY%{<`?Jg5=;J24>o@#myP^-C8@J z?dMNjtgzE0(P6}`(x~FNNBogdJcL6o|b|AS}Yl5TC*( z(?{`@5L4yFN9>k}PQXqQy%?c?L(Kf-ZN7x6(D5S=(nb`cCzpB1BS0>s8~DI*oOFb7 z(}y!~??YxQ1;|lkItNxHeF(CUiQ4B^=!Oey zN{T1w(!%3V+b7Z#A(TjECSVqkeRw9D==v2ADJtJIotUtPWGzZBZq-cNbjnN~G?{Lm zuB}M)jmHWb5_%E#%51XgwJt-Mh!-jk&dX}@CcLhcgO zKy1kA#QhFXk2M|F6tdm*aFzbhrC&0!`?!l0;OK8R_v=bNS@`bxwjjlN3U7SI#MU-@i|1D z+b7y)c4B9XupO_yOXZ(Lf>DIW|Fp&l8|bVrg8Of zlVmz&e#%_W+~Df1wb4hf1L&{oZ`2usQZn`iHLd7sV)^pR-|ZH&jS3enmI{@dzp2r+ zE>x}=!ZS)@H-L)O8`f)hi>oMb=yI4;sO{$qtL2vG7PZN=83gyYj{xT$$BMn|c#|KK z-)5R)TDWTd=xt)@D088Hp+FC>`Fq!xL*X?8`pW2Rxg@z~pOiFaCYCfGHxAbhW7vPQ zq30^)Zt5+lT+q`ilb*`s>k{k>DD-`K!GbOns~ek5xJYQiy34A;w#`bV$E5c_*Rl3{ zdH&lmc80`0|hdTDi;Zxl$(Z6F;8i(=&!)YLQy_Z zEtqFB9$t)1;enGl+ncKmLx*u|$PE4rRpWBS%h`HEOhXTc3eho$4u~e$h}}kAR~yLP z64@=-<4k;9@+Y+BQ`YpiF9(&TpKW-3bo{tDBQ$%{aK(b9fR!i{+nZecVuN%T-S}x* zg-)VQMSaql*}mO=u`s`IwD2=wyjHK)(m;-L(;I{vugk?B(+3-u(^o10UO*Y@CR!0d z8la6VjLwOQ`@j>>)dAnp6h_4{Wd+ZRy)S8_+x4QL`f#G)vCLMaN%#>tQ6wBCm(RiID>x%D= zO+I+91EyazMO`Ir^ssC^J2X1CyiNq9g;$4UA4=-NC(Q zk69iu_0DkqgR-|#N8{>A>vp^&&{1~wU_g4{nI+k>Q_RwYTAo^E>tmam{ckyG zTiAvSFde!b2po17t!m2c=F@15M^DTKzQlY{p<77WUe*iLxmX-L4c~2fb^7Ycd&LXI zdtq^_@rQ1PnV#|N$h#Gz^7X-^f}{E-ot;)~Qv=t>Shn#N@wJ?9s$1kM>|`d3zZZQE zC5_Mg*7DuIem8rrcYeBU*)ez={uyF7vM?n+d2?{znW}xcm}9r;!fIL9@OHuX#y0C< zlVHhR*~7$PnFyIzy`Ax%lL8ad&^ORzp3Y}UJymP2z0Nl)Clda6rCX|y!Vl*FUTVI> zFTLkf`#Bhbv%WEbZ?_n3a!=on=*Q^iPc2MEzc1pk^;h&?-U=DdrWm4N6M1w9) zT{anFEYjs3d#nGQ@q*A+;L^<~atW5P$eG+7UyEpCx_y6^ zGFqA&=xB1=go~r&Ak>34(M~%Pdm3zX-;$R?$f~|!+j0^v3yuVS~!GA9y z_+v~7Qx8)IXX`&$`tHB!`P!Cl?zYZOKn^fF*Wdg9ru#E$IeFN6I9OUR{a!8jHy@u- z$AyXUo4t zzt0W^Kt`s&%>TRLPxIgF3IzYEwh;65uz@WW{73D;eHp;dk^=CrDgjtAf`z9!tQ_N~ zNnm__30M_|hqD_R_!ry%=VzF8CGU?TKbL-A@8E3lkIxF0zTVDmuzlqG^^{mlOjVKp zw-k-@kInt7YQe|N(h3a(xVa(RKr7%MGB76(6t+wEFQC&e83+XCg{}J^ zGB7769}Il|kikCOPx&ty%*Owbaq|7Q9fTLA#6SCTgScT}{D%xSFE`Al|B!*WLC}A< z1MzXgH27CLKJI%%{i82zJjlQG1#?3FV*@ZJ7uUbXgUNXQy%sPh_x%?BYYuL%|3Sv{ zUz>9O$1bq_fc#rGn2h^xw)b!|wRNy``&sg%Ve1Ej3+ybb?(7V6^Ltl@;YQBM${FVK zf4rB3dA%SMYQ@9JXKrr6Ys$+BHiPn*nsV{-K{?HNIKfbJh@~*v|Gf#UROV-O3CweU z0t?K^%MC`OqmxpRM!TQv-h=KP<2N4vLg_z!;~$^}{sJwB=0Du&m;a#s_MiXJJ%0HR z@V5{B>12$Krsl9{^E+U{Vh)&_od;;hXzK26>1gI~UwZ`Rli>t$f(@De8;e+hVlFPQ z!XKFX!P>Ednb7|9#GkQ*69nRep_~r{<>dPvOa2xRe}|5L#^}F?Xqd77EMK}WK>Bat zlbf^4&pIa{FO(eyFbEV40^w!{fq~p$C_97;=D=J~K6WT9n%sAH_PCE4uo5Fx)4$hK z{i}THKXKvz6c!*{JpX|(1Pb{Z{QnL^IT*-b0Fs7bOhQ7ER}6+RaVU?N*iVc}++$1v zA|)&+Dai%l;gja$l;9TQg-SrdQe5KVl3bh;P+lG$9w~_MAKLs4$$#Qo74~BQ`!$3i X?jP`m6=}iho&H25gqM%+7b5=`Zb+nG literal 0 HcmV?d00001 diff --git a/activestorage/test/models/preview_test.rb b/activestorage/test/models/preview_test.rb index 7879f960fa90c..5b2bbd45b0fce 100644 --- a/activestorage/test/models/preview_test.rb +++ b/activestorage/test/models/preview_test.rb @@ -17,6 +17,19 @@ class ActiveStorage::PreviewTest < ActiveSupport::TestCase assert_equal 792, image.height end + test "previewing a cropped PDF" do + blob = create_file_blob(filename: "cropped.pdf", content_type: "application/pdf") + preview = blob.preview(resize: "640x280").processed + + assert_predicate preview.image, :attached? + assert_equal "cropped.png", preview.image.filename.to_s + assert_equal "image/png", preview.image.content_type + + image = read_image(preview.image) + assert_equal 430, image.width + assert_equal 145, image.height + end + test "previewing an MP4 video" do blob = create_file_blob(filename: "video.mp4", content_type: "video/mp4") preview = blob.preview(resize: "640x280").processed diff --git a/activestorage/test/previewer/mupdf_previewer_test.rb b/activestorage/test/previewer/mupdf_previewer_test.rb index 6c2db6fcbf4db..65869dfe37c72 100644 --- a/activestorage/test/previewer/mupdf_previewer_test.rb +++ b/activestorage/test/previewer/mupdf_previewer_test.rb @@ -6,12 +6,10 @@ require "active_storage/previewer/mupdf_previewer" class ActiveStorage::Previewer::MuPDFPreviewerTest < ActiveSupport::TestCase - setup do - @blob = create_file_blob(filename: "report.pdf", content_type: "application/pdf") - end - test "previewing a PDF document" do - ActiveStorage::Previewer::MuPDFPreviewer.new(@blob).preview do |attachable| + blob = create_file_blob(filename: "report.pdf", content_type: "application/pdf") + + ActiveStorage::Previewer::MuPDFPreviewer.new(blob).preview do |attachable| assert_equal "image/png", attachable[:content_type] assert_equal "report.png", attachable[:filename] @@ -20,4 +18,17 @@ class ActiveStorage::Previewer::MuPDFPreviewerTest < ActiveSupport::TestCase assert_equal 792, image.height end end + + test "previewing a cropped PDF document" do + blob = create_file_blob(filename: "cropped.pdf", content_type: "application/pdf") + + ActiveStorage::Previewer::MuPDFPreviewer.new(blob).preview do |attachable| + assert_equal "image/png", attachable[:content_type] + assert_equal "cropped.png", attachable[:filename] + + image = MiniMagick::Image.read(attachable[:io]) + assert_equal 430, image.width + assert_equal 145, image.height + end + end end diff --git a/activestorage/test/previewer/poppler_pdf_previewer_test.rb b/activestorage/test/previewer/poppler_pdf_previewer_test.rb index 2b41c8b642abc..5809b5a058976 100644 --- a/activestorage/test/previewer/poppler_pdf_previewer_test.rb +++ b/activestorage/test/previewer/poppler_pdf_previewer_test.rb @@ -6,12 +6,10 @@ require "active_storage/previewer/poppler_pdf_previewer" class ActiveStorage::Previewer::PopplerPDFPreviewerTest < ActiveSupport::TestCase - setup do - @blob = create_file_blob(filename: "report.pdf", content_type: "application/pdf") - end - test "previewing a PDF document" do - ActiveStorage::Previewer::PopplerPDFPreviewer.new(@blob).preview do |attachable| + blob = create_file_blob(filename: "report.pdf", content_type: "application/pdf") + + ActiveStorage::Previewer::PopplerPDFPreviewer.new(blob).preview do |attachable| assert_equal "image/png", attachable[:content_type] assert_equal "report.png", attachable[:filename] @@ -20,4 +18,17 @@ class ActiveStorage::Previewer::PopplerPDFPreviewerTest < ActiveSupport::TestCas assert_equal 792, image.height end end + + test "previewing a cropped PDF document" do + blob = create_file_blob(filename: "cropped.pdf", content_type: "application/pdf") + + ActiveStorage::Previewer::PopplerPDFPreviewer.new(blob).preview do |attachable| + assert_equal "image/png", attachable[:content_type] + assert_equal "cropped.png", attachable[:filename] + + image = MiniMagick::Image.read(attachable[:io]) + assert_equal 430, image.width + assert_equal 145, image.height + end + end end From bba75d106cc49dae266c8b833a4156754f7e737b Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 21 Sep 2020 15:57:38 -0400 Subject: [PATCH 092/244] Improve while_preventing_writes documentation Adds a note to clarify that `while_preventing_writes` is not meant to be a replacement for a readonly replica user. Closes #39132 and #39133 Co-authored-by: Eike Send --- .../connection_adapters/abstract/connection_pool.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 3da017b8999e1..31fb946ce6331 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -1035,6 +1035,12 @@ def prevent_writes=(prevent_writes) # :nodoc: # In some cases you may want to prevent writes to the database # even if you are on a database that can write. `while_preventing_writes` # will prevent writes to the database for the duration of the block. + # + # This method does not provide the same protection as a readonly + # user and is meant to be a safeguard against accidental writes. + # + # See `READ_QUERY` for the queries that are blocked by this + # method. def while_preventing_writes(enabled = true) original, self.prevent_writes = self.prevent_writes, enabled yield From e8157f0e4faa9f9b07f7fea61321db979b474770 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 28 Jun 2019 13:07:39 +0900 Subject: [PATCH 093/244] Add "SCHEMA" to the query in `configure_connection` like as other adapters This makes to be able to ignore the query in `assert_queries` even if accidentally reconnected a connection. https://buildkite.com/rails/rails/builds/61917#4c49187a-3173-4d5c-8a8d-d65768f5bfc9/1000-1799 --- .../active_record/connection_adapters/abstract_mysql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index e0bd8f2f176c6..3d6d0579fe906 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -744,7 +744,7 @@ def configure_connection end.compact.join(", ") # ...and send them all in one query - execute "SET #{encoding} #{sql_mode_assignment} #{variable_assignments}" + execute("SET #{encoding} #{sql_mode_assignment} #{variable_assignments}", "SCHEMA") end def column_definitions(table_name) # :nodoc: From bd5d907e72fe799f5455804843a92695a5f29e63 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 7 Oct 2020 09:28:29 -0700 Subject: [PATCH 094/244] Prevent XSS in the Actionable Exceptions middleware [CVE-2020-8264] --- .../action_dispatch/middleware/actionable_exceptions.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb index 266fd92ce9856..1593ca22d0319 100644 --- a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "erb" +require "uri" require "action_dispatch/http/request" require "active_support/actionable_error" @@ -27,7 +28,13 @@ def actionable_request?(request) end def redirect_to(location) - body = "You are being redirected." + uri = URI.parse location + + if uri.relative? || uri.scheme == "http" || uri.scheme == "https" + body = "You are being redirected." + else + return [400, {"Content-Type" => "text/plain"}, ["Invalid redirection URI"]] + end [302, { "Content-Type" => "text/html; charset=#{Response.default_charset}", From fe76a95b0d252a2d7c25e69498b720c96b243ea2 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 7 Oct 2020 09:48:32 -0700 Subject: [PATCH 095/244] Preparing for 6.0.3.4 release --- Gemfile.lock | 102 +++++++++--------- RAILS_VERSION | 2 +- actioncable/CHANGELOG.md | 5 + actioncable/lib/action_cable/gem_version.rb | 2 +- actioncable/package.json | 2 +- actionmailbox/CHANGELOG.md | 5 + .../lib/action_mailbox/gem_version.rb | 2 +- actionmailer/CHANGELOG.md | 5 + actionmailer/lib/action_mailer/gem_version.rb | 2 +- actionpack/CHANGELOG.md | 5 + actionpack/lib/action_pack/gem_version.rb | 2 +- actiontext/CHANGELOG.md | 5 + actiontext/lib/action_text/gem_version.rb | 2 +- actiontext/package.json | 2 +- actionview/CHANGELOG.md | 5 + actionview/lib/action_view/gem_version.rb | 2 +- actionview/package.json | 2 +- activejob/CHANGELOG.md | 5 + activejob/lib/active_job/gem_version.rb | 2 +- activemodel/CHANGELOG.md | 5 + activemodel/lib/active_model/gem_version.rb | 2 +- activerecord/CHANGELOG.md | 5 + activerecord/lib/active_record/gem_version.rb | 2 +- activestorage/CHANGELOG.md | 5 + .../lib/active_storage/gem_version.rb | 2 +- activestorage/package.json | 2 +- activesupport/CHANGELOG.md | 5 + .../lib/active_support/gem_version.rb | 2 +- guides/CHANGELOG.md | 5 + railties/CHANGELOG.md | 5 + railties/lib/rails/gem_version.rb | 2 +- version.rb | 2 +- 32 files changed, 135 insertions(+), 68 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index afd5189bc874a..140f4071a3d9b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,79 +17,79 @@ GIT PATH remote: . specs: - actioncable (6.0.3.3) - actionpack (= 6.0.3.3) + actioncable (6.0.3.4) + actionpack (= 6.0.3.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.3.3) - actionpack (= 6.0.3.3) - activejob (= 6.0.3.3) - activerecord (= 6.0.3.3) - activestorage (= 6.0.3.3) - activesupport (= 6.0.3.3) + actionmailbox (6.0.3.4) + actionpack (= 6.0.3.4) + activejob (= 6.0.3.4) + activerecord (= 6.0.3.4) + activestorage (= 6.0.3.4) + activesupport (= 6.0.3.4) mail (>= 2.7.1) - actionmailer (6.0.3.3) - actionpack (= 6.0.3.3) - actionview (= 6.0.3.3) - activejob (= 6.0.3.3) + actionmailer (6.0.3.4) + actionpack (= 6.0.3.4) + actionview (= 6.0.3.4) + activejob (= 6.0.3.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.3.3) - actionview (= 6.0.3.3) - activesupport (= 6.0.3.3) + actionpack (6.0.3.4) + actionview (= 6.0.3.4) + activesupport (= 6.0.3.4) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.3.3) - actionpack (= 6.0.3.3) - activerecord (= 6.0.3.3) - activestorage (= 6.0.3.3) - activesupport (= 6.0.3.3) + actiontext (6.0.3.4) + actionpack (= 6.0.3.4) + activerecord (= 6.0.3.4) + activestorage (= 6.0.3.4) + activesupport (= 6.0.3.4) nokogiri (>= 1.8.5) - actionview (6.0.3.3) - activesupport (= 6.0.3.3) + actionview (6.0.3.4) + activesupport (= 6.0.3.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.3.3) - activesupport (= 6.0.3.3) + activejob (6.0.3.4) + activesupport (= 6.0.3.4) globalid (>= 0.3.6) - activemodel (6.0.3.3) - activesupport (= 6.0.3.3) - activerecord (6.0.3.3) - activemodel (= 6.0.3.3) - activesupport (= 6.0.3.3) - activestorage (6.0.3.3) - actionpack (= 6.0.3.3) - activejob (= 6.0.3.3) - activerecord (= 6.0.3.3) + activemodel (6.0.3.4) + activesupport (= 6.0.3.4) + activerecord (6.0.3.4) + activemodel (= 6.0.3.4) + activesupport (= 6.0.3.4) + activestorage (6.0.3.4) + actionpack (= 6.0.3.4) + activejob (= 6.0.3.4) + activerecord (= 6.0.3.4) marcel (~> 0.3.1) - activesupport (6.0.3.3) + activesupport (6.0.3.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.3.3) - actioncable (= 6.0.3.3) - actionmailbox (= 6.0.3.3) - actionmailer (= 6.0.3.3) - actionpack (= 6.0.3.3) - actiontext (= 6.0.3.3) - actionview (= 6.0.3.3) - activejob (= 6.0.3.3) - activemodel (= 6.0.3.3) - activerecord (= 6.0.3.3) - activestorage (= 6.0.3.3) - activesupport (= 6.0.3.3) + rails (6.0.3.4) + actioncable (= 6.0.3.4) + actionmailbox (= 6.0.3.4) + actionmailer (= 6.0.3.4) + actionpack (= 6.0.3.4) + actiontext (= 6.0.3.4) + actionview (= 6.0.3.4) + activejob (= 6.0.3.4) + activemodel (= 6.0.3.4) + activerecord (= 6.0.3.4) + activestorage (= 6.0.3.4) + activesupport (= 6.0.3.4) bundler (>= 1.3.0) - railties (= 6.0.3.3) + railties (= 6.0.3.4) sprockets-rails (>= 2.0.0) - railties (6.0.3.3) - actionpack (= 6.0.3.3) - activesupport (= 6.0.3.3) + railties (6.0.3.4) + actionpack (= 6.0.3.4) + activesupport (= 6.0.3.4) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -520,6 +520,8 @@ GEM websocket (1.2.8) websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) + websocket-driver (0.7.1-java) + websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) xpath (3.2.0) nokogiri (~> 1.8) diff --git a/RAILS_VERSION b/RAILS_VERSION index b78e7815ba447..7340754a215aa 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.3.3 +6.0.3.4 diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 99ee7ed4c26d5..58c7c17da55ed 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index beadc28443866..6984a8a208e33 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index 358ea3aebfa51..0cd7753a5bd30 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.3-3", + "version": "6.0.3-4", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index 3797bd89a297f..1447196502669 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index 8e03f9ce978a7..2290fd9b53921 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 382c9c4bf2767..17778d22c6675 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index 5ef8dadcb5676..3bc01ca9c9172 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 8afc64bd2c185..e07e13cfdaf84 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* [CVE-2020-8264] Prevent XSS in Actionable Exceptions + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index 0e333ee7341ab..14939dc23b46e 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index b7c2763b87683..6e85c1f449390 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index 9032ec529515d..c523b3127e2b7 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index e8f7bef71d027..6b32510ade88a 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.3-3", + "version": "6.0.3-4", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index b7c6e3a1ccda0..0eed66805efb5 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * [CVE-2020-8185] Fix potential XSS vulnerability in the `translate`/`t` helper. diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 01f66794810e4..2ef7413e53a5b 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 813ceea197954..4ad4a7b36f198 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.3-3", + "version": "6.0.3-4", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index bb50a5a17a1c6..77ba625be177e 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index 01d09129bce2f..968a3dfc59b64 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 76417e68ea6f7..34d91e4449021 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index 3e343808e5d4b..73a8a61115e2f 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 19a2b849c11d3..45cb7492c8622 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index 34c105b07343f..8ff780b53ec89 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index fdf993803caff..18a74102b52e8 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index b782e51cee3ac..f451216c87820 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index 0b0a0a05b918a..d0f738cb9ac8c 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.3-3", + "version": "6.0.3-4", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 1703bbbeffd23..25661e1983e3c 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 1d203f49d1c3e..62fec91674c45 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index 3b2c39dab16a9..65205fddc1f86 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 89b05eae7b1db..b1011ce08ed45 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.4 (October 07, 2020) ## + +* No changes. + + ## Rails 6.0.3.3 (September 09, 2020) ## * No changes. diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index f7940df28d552..a81462170f9a4 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index f7940df28d552..a81462170f9a4 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From e66f29477925a70d335fad757b02cca59d1ea1e2 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 7 Oct 2020 09:28:29 -0700 Subject: [PATCH 096/244] Prevent XSS in the Actionable Exceptions middleware [CVE-2020-8264] --- .../action_dispatch/middleware/actionable_exceptions.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb index 266fd92ce9856..1593ca22d0319 100644 --- a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "erb" +require "uri" require "action_dispatch/http/request" require "active_support/actionable_error" @@ -27,7 +28,13 @@ def actionable_request?(request) end def redirect_to(location) - body = "You are being redirected." + uri = URI.parse location + + if uri.relative? || uri.scheme == "http" || uri.scheme == "https" + body = "You are being redirected." + else + return [400, {"Content-Type" => "text/plain"}, ["Invalid redirection URI"]] + end [302, { "Content-Type" => "text/html; charset=#{Response.default_charset}", From db82b8df30de8e88b57e49caf497c7c7da3e04c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Wed, 7 Oct 2020 13:14:58 -0400 Subject: [PATCH 097/244] Merge pull request #40353 from jrochkind/more_specific_bad_content_type_error Raise more specific exception for invalid mime type from user-agent --- actionpack/lib/action_dispatch/http/mime_negotiation.rb | 6 ++++++ .../lib/action_dispatch/middleware/debug_exceptions.rb | 2 +- .../lib/action_dispatch/middleware/exception_wrapper.rb | 2 +- .../lib/action_dispatch/middleware/public_exceptions.rb | 2 +- actionpack/test/dispatch/debug_exceptions_test.rb | 6 +++--- actionpack/test/dispatch/show_exceptions_test.rb | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index a2cac49082c75..653542febc3c7 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -7,6 +7,8 @@ module Http module MimeNegotiation extend ActiveSupport::Concern + class InvalidType < ::Mime::Type::InvalidMimeType; end + RESCUABLE_MIME_FORMAT_ERRORS = [ ActionController::BadRequest, ActionDispatch::Http::Parameters::ParseError, @@ -25,6 +27,8 @@ def content_mime_type nil end set_header k, v + rescue ::Mime::Type::InvalidMimeType => e + raise InvalidType, e.message end end @@ -47,6 +51,8 @@ def accepts Mime::Type.parse(header) end set_header k, v + rescue ::Mime::Type::InvalidMimeType => e + raise InvalidType, e.message end end diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb index 7f6d918446716..119c9f37cb855 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb @@ -63,7 +63,7 @@ def render_exception(request, exception) if request.get_header("action_dispatch.show_detailed_exceptions") begin content_type = request.formats.first - rescue Mime::Type::InvalidMimeType + rescue ActionDispatch::Http::MimeNegotiation::InvalidType content_type = Mime[:text] end diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb index 2da0ef9600a91..b82565847b8f8 100644 --- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb +++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb @@ -12,7 +12,7 @@ class ExceptionWrapper "ActionController::UnknownHttpMethod" => :method_not_allowed, "ActionController::NotImplemented" => :not_implemented, "ActionController::UnknownFormat" => :not_acceptable, - "Mime::Type::InvalidMimeType" => :not_acceptable, + "ActionDispatch::Http::MimeNegotiation::InvalidType" => :not_acceptable, "ActionController::MissingExactTemplate" => :not_acceptable, "ActionController::InvalidAuthenticityToken" => :unprocessable_entity, "ActionController::InvalidCrossOriginRequest" => :unprocessable_entity, diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb index 3a2a1d73346ad..4404dbe874bd3 100644 --- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb @@ -23,7 +23,7 @@ def call(env) status = request.path_info[1..-1].to_i begin content_type = request.formats.first - rescue Mime::Type::InvalidMimeType + rescue ActionDispatch::Http::MimeNegotiation::InvalidType content_type = Mime[:text] end body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) } diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb index 64ceab56ef177..8ad20fc1a43d1 100644 --- a/actionpack/test/dispatch/debug_exceptions_test.rb +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -81,7 +81,7 @@ def call(env) when "/unprocessable_entity" raise ActionController::InvalidAuthenticityToken when "/invalid_mimetype" - raise Mime::Type::InvalidMimeType + raise ActionDispatch::Http::MimeNegotiation::InvalidType when "/not_found_original_exception" begin raise AbstractController::ActionNotFound.new @@ -216,7 +216,7 @@ def call(env) get "/invalid_mimetype", headers: { "Accept" => "text/html,*", "action_dispatch.show_exceptions" => true } assert_response 406 - assert_match(/Mime::Type::InvalidMimeType/, body) + assert_match(/ActionDispatch::Http::MimeNegotiation::InvalidType/, body) end test "rescue with text error for xhr request" do @@ -313,7 +313,7 @@ def call(env) assert_response 406 assert_no_match(//, body) assert_equal "application/json", response.media_type - assert_match(/Mime::Type::InvalidMimeType/, body) + assert_match(/ActionDispatch::Http::MimeNegotiation::InvalidType/, body) end test "rescue with HTML format for HTML API request" do diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb index 6fafa4e426710..a370076af52ed 100644 --- a/actionpack/test/dispatch/show_exceptions_test.rb +++ b/actionpack/test/dispatch/show_exceptions_test.rb @@ -10,7 +10,7 @@ def call(env) when "/not_found" raise AbstractController::ActionNotFound when "/invalid_mimetype" - raise Mime::Type::InvalidMimeType + raise ActionDispatch::Http::MimeNegotiation::InvalidType when "/bad_params", "/bad_params.json" begin raise StandardError.new From e6b5ee92fa80dbe4c6cf9fa89a15687861b2ab20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 7 Oct 2020 17:55:18 +0000 Subject: [PATCH 098/244] Fix style of this file --- .../lib/action_dispatch/middleware/actionable_exceptions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb index 1593ca22d0319..932d41d26a9e1 100644 --- a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb @@ -33,7 +33,7 @@ def redirect_to(location) if uri.relative? || uri.scheme == "http" || uri.scheme == "https" body = "You are being redirected." else - return [400, {"Content-Type" => "text/plain"}, ["Invalid redirection URI"]] + return [400, { "Content-Type" => "text/plain"}, ["Invalid redirection URI"]] end [302, { From 80eca675de66051f8cf5539ad47e2978b162e41a Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Wed, 7 Oct 2020 19:37:13 +0100 Subject: [PATCH 099/244] Add missing space before closing hash brace --- .../lib/action_dispatch/middleware/actionable_exceptions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb index 932d41d26a9e1..a5ae54296aeec 100644 --- a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb @@ -33,7 +33,7 @@ def redirect_to(location) if uri.relative? || uri.scheme == "http" || uri.scheme == "https" body = "You are being redirected." else - return [400, { "Content-Type" => "text/plain"}, ["Invalid redirection URI"]] + return [400, { "Content-Type" => "text/plain" }, ["Invalid redirection URI"]] end [302, { From efb13168cd4bb7fd2b8f07f4a5fdc555a32deeb0 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Wed, 7 Oct 2020 21:47:59 +0100 Subject: [PATCH 100/244] Prefix keys in Active Storage service test Otherwise this test fails when run concurrently. https://buildkite.com/rails/rails/builds/71999#77923632-f943-4fa0-b478-0af38001c22b/1032-1098 https://buildkite.com/rails/rails/builds/71999#01fdec79-dc1f-4a6a-b730-ac0df134a2e7/970-1062 --- .../test/service/shared_service_tests.rb | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/activestorage/test/service/shared_service_tests.rb b/activestorage/test/service/shared_service_tests.rb index 17f37360560ef..3d4884b50c777 100644 --- a/activestorage/test/service/shared_service_tests.rb +++ b/activestorage/test/service/shared_service_tests.rb @@ -123,18 +123,20 @@ module ActiveStorage::Service::SharedServiceTests end test "deleting by prefix" do - @service.upload("a/a/a", StringIO.new(FIXTURE_DATA)) - @service.upload("a/a/b", StringIO.new(FIXTURE_DATA)) - @service.upload("a/b/a", StringIO.new(FIXTURE_DATA)) - - @service.delete_prefixed("a/a/") - assert_not @service.exist?("a/a/a") - assert_not @service.exist?("a/a/b") - assert @service.exist?("a/b/a") + key = SecureRandom.base58(24) + + @service.upload("#{key}/a/a/a", StringIO.new(FIXTURE_DATA)) + @service.upload("#{key}/a/a/b", StringIO.new(FIXTURE_DATA)) + @service.upload("#{key}/a/b/a", StringIO.new(FIXTURE_DATA)) + + @service.delete_prefixed("#{key}/a/a/") + assert_not @service.exist?("#{key}/a/a/a") + assert_not @service.exist?("#{key}/a/a/b") + assert @service.exist?("#{key}/a/b/a") ensure - @service.delete("a/a/a") - @service.delete("a/a/b") - @service.delete("a/b/a") + @service.delete("#{key}/a/a/a") + @service.delete("#{key}/a/a/b") + @service.delete("#{key}/a/b/a") end end end From cd49246d56c643c4816153bb85a44a2c0b85f077 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 9 Oct 2020 19:02:27 +0200 Subject: [PATCH 101/244] Fixes case in guides title --- guides/source/autoloading_and_reloading_constants.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/source/autoloading_and_reloading_constants.md b/guides/source/autoloading_and_reloading_constants.md index cc2a08d05467e..fa1b97cafbf00 100644 --- a/guides/source/autoloading_and_reloading_constants.md +++ b/guides/source/autoloading_and_reloading_constants.md @@ -81,7 +81,7 @@ The section _Customizing Inflections_ below documents ways to override this defa Please, check the [Zeitwerk documentation](https://github.com/fxn/zeitwerk#file-structure) for further details. -Autoload paths +Autoload Paths -------------- We call _autoload paths_ to the list of application directories whose contents are to be autoloaded. For example, `app/models`. Such directories represent the root namespace: `Object`. From 2851edd02f6f46cf5952c90f87847de7389772fd Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 9 Oct 2020 20:06:39 +0200 Subject: [PATCH 102/244] documents differences zeitwerk vs classic mode [skip ci] --- .../autoloading_and_reloading_constants.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/guides/source/autoloading_and_reloading_constants.md b/guides/source/autoloading_and_reloading_constants.md index fa1b97cafbf00..a8affec578340 100644 --- a/guides/source/autoloading_and_reloading_constants.md +++ b/guides/source/autoloading_and_reloading_constants.md @@ -356,6 +356,56 @@ You can check if `zeitwerk` mode is enabled with Rails.autoloaders.zeitwerk_enabled? ``` +Differences with Classic Mode +----------------------------- + +### Ruby Constant Lookup Compliance + +`classic` mode cannot match constant lookup semantics due to fundamental limitations of the technique it is based on, whereas `zeitwerk` mode works like Ruby. + +For example, in `classic` mode defining classes or modules in namespaces with qualified constants this way + +```ruby +class Admin::UsersController < ApplicationController +end +``` + +was not recommended because the resolution of constants inside their body was britle. You'd better write them in this style: + +```ruby +module Admin + class UsersController < ApplicationController + end +end +``` + +In `zeitwerk` mode that does not matter anymore, you can pick either style. + +The resolution of a constant could depend on load order, the definition of a class or module object could depend on load order, there was edge cases with singleton classes, oftentimes you had to use `require_dependency` as a workaround, .... The guide for `classic` mode documents [these issues](autoloading_and_reloading_constants_classic_mode.html#common-gotchas). + +All these problems are solved in `zeitwerk` mode, it just works as expected, and `require_dependency` should not be used anymore, it is no longer needed. + +### Less File Lookups + +In `classic` mode, every single missing constant triggers a file lookup that walks the autoload paths. In `zeitwerk` mode there is only one pass, which is done once, not per missing constant, which is generally more performant. Subdirectories are visited only if their namespace is used. + +### Underscore vs Camelize + +Inflections go the other way around. In `classic` mode, given a missing constant Rails _underscores_ its name and performs a file lookup. On the other hand, `zeitwerk` mode checks first the file system, and _camelizes_ file names to know the constant those files are expected to define. While in common names these operations match, if acronyms or custom inflection rules are configured, they may not. + +For example, by default `"HTMLParser".underscore` is `"html_parser"`, and `"html_parser".camelize` is `"HtmlParser"`. + +### More Differences + +There are some other subtle differences, please check Please check [this section of _Upgrading Ruby on Rails_](upgrading_ruby_on_rails.html#autoloading) guide for details. + +Classic Mode is Deprecated +-------------------------- + +By now, it is still possible to use `classic` mode. However, `classic` is deprecated and will be eventually removed. + +New applications should use `zeitwerk` mode (which is the default), and applications being upgrade are strongly encouraged to migrate to `zeitwerk` mode. Please check the [_Upgrading Ruby on Rails_](upgrading_ruby_on_rails.html#autoloading) guide for details. + Opting Out ---------- From 2b4025368f2266ee13bc6c89f1757a0f685307cf Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 9 Oct 2020 20:18:10 +0200 Subject: [PATCH 103/244] edits in the constants guide [skip ci] --- guides/source/autoloading_and_reloading_constants.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/guides/source/autoloading_and_reloading_constants.md b/guides/source/autoloading_and_reloading_constants.md index a8affec578340..59188d741ee64 100644 --- a/guides/source/autoloading_and_reloading_constants.md +++ b/guides/source/autoloading_and_reloading_constants.md @@ -387,17 +387,21 @@ All these problems are solved in `zeitwerk` mode, it just works as expected, and ### Less File Lookups -In `classic` mode, every single missing constant triggers a file lookup that walks the autoload paths. In `zeitwerk` mode there is only one pass, which is done once, not per missing constant, which is generally more performant. Subdirectories are visited only if their namespace is used. +In `classic` mode, every single missing constant triggers a file lookup that walks the autoload paths. + +In `zeitwerk` mode there is only one pass. That pass is done once, not per missing constant, and so it is generally more performant. Subdirectories are visited only if their namespace is used. ### Underscore vs Camelize -Inflections go the other way around. In `classic` mode, given a missing constant Rails _underscores_ its name and performs a file lookup. On the other hand, `zeitwerk` mode checks first the file system, and _camelizes_ file names to know the constant those files are expected to define. While in common names these operations match, if acronyms or custom inflection rules are configured, they may not. +Inflections go the other way around. + +In `classic` mode, given a missing constant Rails _underscores_ its name and performs a file lookup. On the other hand, `zeitwerk` mode checks first the file system, and _camelizes_ file names to know the constant those files are expected to define. -For example, by default `"HTMLParser".underscore` is `"html_parser"`, and `"html_parser".camelize` is `"HtmlParser"`. +While in common names these operations match, if acronyms or custom inflection rules are configured, they may not. For example, by default `"HTMLParser".underscore` is `"html_parser"`, and `"html_parser".camelize` is `"HtmlParser"`. ### More Differences -There are some other subtle differences, please check Please check [this section of _Upgrading Ruby on Rails_](upgrading_ruby_on_rails.html#autoloading) guide for details. +There are some other subtle differences, please check [this section of _Upgrading Ruby on Rails_](upgrading_ruby_on_rails.html#autoloading) guide for details. Classic Mode is Deprecated -------------------------- From 5ccc67605ec462a8e164635c75be84a3af0234f5 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Fri, 23 Oct 2020 23:52:57 +0100 Subject: [PATCH 104/244] Merge pull request #40246 from lorennorman/fix-invalid-http-method Expose rack.request_method through request.raw_request_method for Logger --- actionpack/lib/action_dispatch/http/request.rb | 2 ++ railties/CHANGELOG.md | 7 +++++++ railties/lib/rails/rack/logger.rb | 2 +- railties/test/application/middleware/exceptions_test.rb | 5 +++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 79058ce6a70cf..6f1430fab866c 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -133,6 +133,8 @@ def key?(key) HTTP_METHOD_LOOKUP[method] = method.underscore.to_sym } + alias raw_request_method request_method # :nodoc: + # Returns the HTTP \method that the application should see. # In the case where the \method was overridden by a middleware # (for instance, if a HEAD request was converted to a GET, diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index b1011ce08ed45..498f8e611bf91 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,10 @@ +* Return a 405 Method Not Allowed response when a request uses an unknown HTTP method. + + Fixes #38998. + + *Loren Norman* + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/railties/lib/rails/rack/logger.rb b/railties/lib/rails/rack/logger.rb index 8d69663dbdc0e..1f37ee9845451 100644 --- a/railties/lib/rails/rack/logger.rb +++ b/railties/lib/rails/rack/logger.rb @@ -47,7 +47,7 @@ def call_app(request, env) # :doc: # Started GET "/session/new" for 127.0.0.1 at 2012-09-26 14:51:42 -0700 def started_request_message(request) # :doc: 'Started %s "%s" for %s at %s' % [ - request.request_method, + request.raw_request_method, request.filtered_path, request.remote_ip, Time.now.to_default_s ] diff --git a/railties/test/application/middleware/exceptions_test.rb b/railties/test/application/middleware/exceptions_test.rb index 5fae521937f05..87529c951c0a7 100644 --- a/railties/test/application/middleware/exceptions_test.rb +++ b/railties/test/application/middleware/exceptions_test.rb @@ -46,6 +46,11 @@ def index assert_equal 404, last_response.status end + test "renders unknown http methods as 405" do + request "/", { "REQUEST_METHOD" => "NOT_AN_HTTP_METHOD" } + assert_equal 405, last_response.status + end + test "uses custom exceptions app" do add_to_config <<-RUBY config.exceptions_app = lambda do |env| From 67e4702fe57ae36f503e9f63695ac1a35f208e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Thu, 29 Oct 2020 21:47:40 -0400 Subject: [PATCH 105/244] Merge pull request #39550 from vipulnsward/expiry-fix Fix parsing of jsonified expiry date on AS::Message::Metadata for old json format --- activesupport/lib/active_support/messages/metadata.rb | 10 +++++++++- activesupport/test/message_verifier_test.rb | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/messages/metadata.rb b/activesupport/lib/active_support/messages/metadata.rb index e3be0b65e67a2..4734cce819870 100644 --- a/activesupport/lib/active_support/messages/metadata.rb +++ b/activesupport/lib/active_support/messages/metadata.rb @@ -7,7 +7,7 @@ module Messages #:nodoc: class Metadata #:nodoc: def initialize(message, expires_at = nil, purpose = nil) @message, @purpose = message, purpose - @expires_at = expires_at.is_a?(String) ? Time.iso8601(expires_at) : expires_at + @expires_at = expires_at.is_a?(String) ? parse_expires_at(expires_at) : expires_at end def as_json(options = {}) @@ -67,6 +67,14 @@ def match?(purpose) def fresh? @expires_at.nil? || Time.now.utc < @expires_at end + + def parse_expires_at(expires_at) + if ActiveSupport.use_standard_json_time_format + Time.iso8601(expires_at) + else + Time.parse(expires_at) + end + end end end end diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 1ffc830238c01..f98a9ece2a577 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -160,6 +160,14 @@ def test_verify_raises_when_purpose_differs end end + def test_verify_with_use_standard_json_time_format_as_false + format_before = ActiveSupport.use_standard_json_time_format + ActiveSupport.use_standard_json_time_format = false + assert_equal "My Name", @verifier.verify(generate("My Name")) + ensure + ActiveSupport.use_standard_json_time_format = format_before + end + def test_verify_raises_when_expired signed_message = generate(data, expires_in: 1.month) From f0cdd75e088928eaa61518e2ba532d30c1706947 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Fri, 30 Oct 2020 12:00:55 +0000 Subject: [PATCH 106/244] Merge pull request #40448 from BKSpurgeon/fix-timezone-rounding-bug Fix: timezone bug - rounding problem --- .../lib/active_support/core_ext/time/calculations.rb | 4 +++- activesupport/test/core_ext/time_with_zone_test.rb | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index eed34965e398f..be1f85b573875 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -47,7 +47,9 @@ def at_with_coercion(*args) # Time.at can be called with a time or numerical value time_or_number = args.first - if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime) + if time_or_number.is_a?(ActiveSupport::TimeWithZone) + at_without_coercion(time_or_number.to_r).getlocal + elsif time_or_number.is_a?(DateTime) at_without_coercion(time_or_number.to_f).getlocal else at_without_coercion(time_or_number) diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index f6e836e446c16..3f8b6ed36237a 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -1110,6 +1110,13 @@ def test_use_zone_raises_on_invalid_timezone assert_equal ActiveSupport::TimeZone["Alaska"], Time.zone end + def test_time_at_precision + Time.use_zone "UTC" do + time = "2019-01-01 00:00:00Z".to_time.end_of_month + assert_equal Time.at(time), Time.at(time.in_time_zone) + end + end + def test_time_zone_getter_and_setter Time.zone = ActiveSupport::TimeZone["Alaska"] assert_equal ActiveSupport::TimeZone["Alaska"], Time.zone From 88c7ee7f3e094bc4d57049bbc89f6e3d73976348 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Fri, 30 Oct 2020 15:48:06 +0000 Subject: [PATCH 107/244] Merge pull request #39754 from stevenweber/s/34255-fix Set inverse during has one autosave if necessary --- activerecord/CHANGELOG.md | 6 ++++++ .../lib/active_record/autosave_association.rb | 2 +- .../cases/associations/inverse_associations_test.rb | 11 +++++++++++ activerecord/test/models/face.rb | 1 + activerecord/test/models/man.rb | 1 + 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index eee4c11688d37..636c72a8e4582 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* Allow the inverse of a `has_one` association that was previously autosaved to be loaded. + + Fixes #34255. + + *Steven Weber* + * Reset statement cache for association if `table_name` is changed. Fixes #36453. diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 933a0557f05fa..dfb7294133531 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -444,7 +444,7 @@ def save_has_one_association(reflection) unless reflection.through_reflection record[reflection.foreign_key] = key if inverse_reflection = reflection.inverse_of - record.association(inverse_reflection.name).loaded! + record.association(inverse_reflection.name).inversed_from(self) end end diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb index 25b150443b6d8..eab8d1cdc6e58 100644 --- a/activerecord/test/cases/associations/inverse_associations_test.rb +++ b/activerecord/test/cases/associations/inverse_associations_test.rb @@ -697,6 +697,17 @@ def test_inversed_instance_should_not_be_reloaded_after_stale_state_changed_with assert_equal old_inversed_man.object_id, new_inversed_man.object_id end + def test_inversed_instance_should_load_after_autosave_if_it_is_not_already_loaded + man = Man.create! + man.create_autosave_face! + + man.autosave_face.reload # clear cached load of autosave_man + man.autosave_face.description = "new description" + man.save! + + assert_not_nil man.autosave_face.autosave_man + end + def test_should_not_try_to_set_inverse_instances_when_the_inverse_is_a_has_many i = interests(:llama_wrangling) m = i.polymorphic_man diff --git a/activerecord/test/models/face.rb b/activerecord/test/models/face.rb index e900fd40fb1d1..009b85fe62562 100644 --- a/activerecord/test/models/face.rb +++ b/activerecord/test/models/face.rb @@ -2,6 +2,7 @@ class Face < ActiveRecord::Base belongs_to :man, inverse_of: :face + belongs_to :autosave_man, class_name: "Man", foreign_key: :man_id, inverse_of: :autosave_face belongs_to :human, polymorphic: true belongs_to :polymorphic_man, polymorphic: true, inverse_of: :polymorphic_face # Oracle identifier length is limited to 30 bytes or less, `polymorphic` renamed `poly` diff --git a/activerecord/test/models/man.rb b/activerecord/test/models/man.rb index e26920e951075..a812670ed46fc 100644 --- a/activerecord/test/models/man.rb +++ b/activerecord/test/models/man.rb @@ -2,6 +2,7 @@ class Man < ActiveRecord::Base has_one :face, inverse_of: :man + has_one :autosave_face, class_name: "Face", autosave: true, foreign_key: :man_id, inverse_of: :autosave_man has_one :polymorphic_face, class_name: "Face", as: :polymorphic_man, inverse_of: :polymorphic_man has_one :polymorphic_face_without_inverse, class_name: "Face", as: :poly_man_without_inverse has_many :interests, inverse_of: :man From 2f23919f46ec705f3a67180f230df8a69f64e11a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Fri, 30 Oct 2020 16:42:29 -0400 Subject: [PATCH 108/244] Merge pull request #39532 from vipulnsward/fix-tz-perform-now Set timezone on a Job initialization to make it conform more with perform_later when doing JobClass.perform_now --- activejob/lib/active_job/core.rb | 3 ++- activejob/test/cases/timezones_test.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/activejob/lib/active_job/core.rb b/activejob/lib/active_job/core.rb index 977455b4e4298..187ca6d0894c8 100644 --- a/activejob/lib/active_job/core.rb +++ b/activejob/lib/active_job/core.rb @@ -85,6 +85,7 @@ def initialize(*arguments) @priority = self.class.priority @executions = 0 @exception_executions = {} + @timezone = Time.zone.try(:name) end ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true) @@ -101,7 +102,7 @@ def serialize "executions" => executions, "exception_executions" => exception_executions, "locale" => I18n.locale.to_s, - "timezone" => Time.zone.try(:name), + "timezone" => timezone, "enqueued_at" => Time.now.utc.iso8601 } end diff --git a/activejob/test/cases/timezones_test.rb b/activejob/test/cases/timezones_test.rb index e2095b020d4a8..d1a34212ac8b6 100644 --- a/activejob/test/cases/timezones_test.rb +++ b/activejob/test/cases/timezones_test.rb @@ -21,4 +21,16 @@ class TimezonesTest < ActiveSupport::TestCase assert_equal "Just 5 hours to go", JobBuffer.last_value end + + test "perform_now passes down current timezone to the job" do + Time.zone = "America/New_York" + + Time.use_zone("London") do + job = TimezoneDependentJob.new("2018-01-01T00:00:00Z") + assert_equal "London", job.timezone + job.perform_now + end + + assert_equal "Happy New Year!", JobBuffer.last_value + end end From c198dc8cc9ed55280cde1be150c7ee29e7f9d3e5 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sun, 4 Oct 2020 00:26:03 +0100 Subject: [PATCH 109/244] Avoid chdir error in Railties tests on Ruby master https://github.com/ruby/ruby/commit/5d7953f86b7ae164017e2292dfb3c108e0e02527 https://buildkite.com/rails/rails/builds/71925#9839c015-e562-4145-932c-75b9c118bfca/1043-1055 --- railties/test/application/rake/dbs_test.rb | 35 ++++++++++--------- railties/test/application/rake/log_test.rb | 5 +-- .../test/application/rake/migrations_test.rb | 13 ++++--- .../test/application/rake/multi_dbs_test.rb | 27 +++++++------- .../test/application/rake/restart_test.rb | 7 ++-- railties/test/application/rake/tmp_test.rb | 5 +-- railties/test/chdir_helpers.rb | 12 +++++++ 7 files changed, 62 insertions(+), 42 deletions(-) create mode 100644 railties/test/chdir_helpers.rb diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index 54a09e122097a..24ce92abba2d3 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -1,12 +1,13 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "chdir_helpers" require "env_helpers" module ApplicationTests module RakeTests class RakeDbsTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation, EnvHelpers + include ActiveSupport::Testing::Isolation, ChdirHelpers, EnvHelpers def setup build_app @@ -28,7 +29,7 @@ def set_database_url end def db_create_and_drop(expected_database, environment_loaded: true) - Dir.chdir(app_path) do + chdir(app_path) do output = rails("db:create") assert_match(/Created database/, output) assert File.exist?(expected_database) @@ -41,7 +42,7 @@ def db_create_and_drop(expected_database, environment_loaded: true) end def db_create_with_warning(expected_database) - Dir.chdir(app_path) do + chdir(app_path) do output = rails("db:create") assert_match(/Rails couldn't infer whether you are using multiple databases/, output) assert_match(/Created database/, output) @@ -184,7 +185,7 @@ def db_create_with_warning(expected_database) end def with_database_existing - Dir.chdir(app_path) do + chdir(app_path) do set_database_url rails "db:create" yield @@ -200,7 +201,7 @@ def with_database_existing end def with_bad_permissions - Dir.chdir(app_path) do + chdir(app_path) do skip "Can't avoid permissions as root" if Process.uid.zero? set_database_url @@ -248,7 +249,7 @@ def with_bad_permissions end test "db:truncate_all truncates all non-internal tables" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" require "#{app_path}/config/environment" @@ -273,7 +274,7 @@ def with_bad_permissions test "db:truncate_all does not truncate any tables when environment is protected" do with_rails_env "production" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" require "#{app_path}/config/environment" @@ -320,7 +321,7 @@ def db_migrate_and_status(expected_database) end def db_schema_dump - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate", "db:schema:dump" schema_dump = File.read("db/schema.rb") @@ -338,7 +339,7 @@ def db_schema_dump end def db_schema_cache_dump(filename = "db/schema_cache.yml") - Dir.chdir(app_path) do + chdir(app_path) do rails "db:schema:cache:dump" cache_size = lambda { rails("runner", "p ActiveRecord::Base.connection.schema_cache.size").strip } @@ -356,7 +357,7 @@ def db_schema_cache_dump(filename = "db/schema_cache.yml") end test "db:schema:cache:dump with custom filename" do - Dir.chdir(app_path) do + chdir(app_path) do File.open("#{app_path}/config/database.yml", "w") do |f| f.puts <<-YAML default: &default @@ -378,7 +379,7 @@ def db_schema_cache_dump(filename = "db/schema_cache.yml") end def db_fixtures_load(expected_database) - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" reload rails "db:migrate", "db:fixtures:load" @@ -410,7 +411,7 @@ def db_fixtures_load(expected_database) end def db_structure_dump_and_load(expected_database) - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate", "db:structure:dump" structure_dump = File.read("db/structure.sql") @@ -507,7 +508,7 @@ def db_structure_dump_and_load(expected_database) end def db_test_load_structure - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate", "db:structure:dump", "db:test:load_structure" ActiveRecord::Base.configurations = Rails.application.config.database_configuration @@ -590,7 +591,7 @@ def db_test_load_structure end test "db:seed:replant truncates all non-internal tables and loads the seeds" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" require "#{app_path}/config/environment" @@ -623,7 +624,7 @@ def db_test_load_structure test "db:seed:replant does not truncate any tables and does not load the seeds when environment is protected" do with_rails_env "production" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" require "#{app_path}/config/environment" @@ -656,7 +657,7 @@ def db_test_load_structure end test "db:prepare setup the database" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" output = rails("db:prepare") assert_match(/CreateBooks: migrated/, output) @@ -672,7 +673,7 @@ def db_test_load_structure end test "db:prepare does not touch schema when dumping is disabled" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:create", "db:migrate" diff --git a/railties/test/application/rake/log_test.rb b/railties/test/application/rake/log_test.rb index 678f26db26aae..fae358a052221 100644 --- a/railties/test/application/rake/log_test.rb +++ b/railties/test/application/rake/log_test.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "chdir_helpers" module ApplicationTests module RakeTests class LogTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, ChdirHelpers def setup build_app @@ -16,7 +17,7 @@ def teardown end test "log:clear clear all environments log files by default" do - Dir.chdir(app_path) do + chdir(app_path) do File.open("config/environments/staging.rb", "w") File.write("log/staging.log", "staging") diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb index 47c5ac105a4e7..aac0506e6d676 100644 --- a/railties/test/application/rake/migrations_test.rb +++ b/railties/test/application/rake/migrations_test.rb @@ -1,10 +1,13 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "chdir_helpers" module ApplicationTests module RakeTests class RakeMigrationsTest < ActiveSupport::TestCase + include ChdirHelpers + def setup build_app FileUtils.rm_rf("#{app_path}/config/environments") @@ -265,7 +268,7 @@ class TwoMigration < ActiveRecord::Migration::Current end test "raise error on any move when current migration does not exist" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "user", "username:string", "password:string" rails "generate", "migration", "add_email_to_users", "email:string" rails "db:migrate" @@ -411,7 +414,7 @@ class TwoMigration < ActiveRecord::Migration::Current test "schema generation when dump_schema_after_migration is set" do add_to_config("config.active_record.dump_schema_after_migration = false") - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" output = rails("generate", "model", "author", "name:string") version = output =~ %r{[^/]+db/migrate/(\d+)_create_authors\.rb} && $1 @@ -422,7 +425,7 @@ class TwoMigration < ActiveRecord::Migration::Current add_to_config("config.active_record.dump_schema_after_migration = true") - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "reviews", "book_id:integer" rails "db:migrate" @@ -432,7 +435,7 @@ class TwoMigration < ActiveRecord::Migration::Current end test "default schema generation after migration" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" @@ -442,7 +445,7 @@ class TwoMigration < ActiveRecord::Migration::Current end test "migration status migrated file is deleted" do - Dir.chdir(app_path) do + chdir(app_path) do rails "generate", "model", "user", "username:string", "password:string" rails "generate", "migration", "add_email_to_users", "email:string" rails "db:migrate" diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb index 16c4040c87d51..754ab258c25cb 100644 --- a/railties/test/application/rake/multi_dbs_test.rb +++ b/railties/test/application/rake/multi_dbs_test.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "chdir_helpers" module ApplicationTests module RakeTests class RakeMultiDbsTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, ChdirHelpers def setup build_app(multi_db: true) @@ -17,7 +18,7 @@ def teardown end def db_create_and_drop(namespace, expected_database) - Dir.chdir(app_path) do + chdir(app_path) do output = rails("db:create") assert_match(/Created database/, output) assert_match_namespace(namespace, output) @@ -33,7 +34,7 @@ def db_create_and_drop(namespace, expected_database) end def db_create_and_drop_namespace(namespace, expected_database) - Dir.chdir(app_path) do + chdir(app_path) do output = rails("db:create:#{namespace}") assert_match(/Created database/, output) assert_match_namespace(namespace, output) @@ -55,7 +56,7 @@ def assert_match_namespace(namespace, output) end def db_migrate_and_migrate_status - Dir.chdir(app_path) do + chdir(app_path) do generate_models_for_animals rails "db:migrate" output = rails "db:migrate:status" @@ -65,7 +66,7 @@ def db_migrate_and_migrate_status end def db_migrate_and_schema_cache_dump - Dir.chdir(app_path) do + chdir(app_path) do generate_models_for_animals rails "db:migrate" rails "db:schema:cache:dump" @@ -75,7 +76,7 @@ def db_migrate_and_schema_cache_dump end def db_migrate_and_schema_cache_dump_and_schema_cache_clear - Dir.chdir(app_path) do + chdir(app_path) do generate_models_for_animals rails "db:migrate" rails "db:schema:cache:dump" @@ -86,7 +87,7 @@ def db_migrate_and_schema_cache_dump_and_schema_cache_clear end def db_migrate_and_schema_dump_and_load(format) - Dir.chdir(app_path) do + chdir(app_path) do generate_models_for_animals rails "db:migrate", "db:#{format}:dump" @@ -113,7 +114,7 @@ def db_migrate_and_schema_dump_and_load(format) end def db_migrate_namespaced(namespace) - Dir.chdir(app_path) do + chdir(app_path) do generate_models_for_animals output = rails("db:migrate:#{namespace}") if namespace == "primary" @@ -125,7 +126,7 @@ def db_migrate_namespaced(namespace) end def db_migrate_status_namespaced(namespace) - Dir.chdir(app_path) do + chdir(app_path) do generate_models_for_animals output = rails("db:migrate:status:#{namespace}") if namespace == "primary" @@ -137,7 +138,7 @@ def db_migrate_status_namespaced(namespace) end def db_up_and_down(version, namespace = nil) - Dir.chdir(app_path) do + chdir(app_path) do generate_models_for_animals rails("db:migrate") @@ -167,7 +168,7 @@ def db_up_and_down(version, namespace = nil) end def db_prepare - Dir.chdir(app_path) do + chdir(app_path) do generate_models_for_animals output = rails("db:prepare") @@ -232,7 +233,7 @@ def generate_models_for_animals end test "db:migrate set back connection to its original state" do - Dir.chdir(app_path) do + chdir(app_path) do dummy_task = <<~RUBY task foo: :environment do Book.first @@ -368,7 +369,7 @@ class TwoMigration < ActiveRecord::Migration::Current test "db:prepare setups missing database without clearing existing one" do require "#{app_path}/config/environment" - Dir.chdir(app_path) do + chdir(app_path) do # Bug not visible on SQLite3. Can be simplified when https://github.com/rails/rails/issues/36383 resolved use_postgresql(multi_db: true) generate_models_for_animals diff --git a/railties/test/application/rake/restart_test.rb b/railties/test/application/rake/restart_test.rb index 8614560bf23bd..c4e737ac9cd1c 100644 --- a/railties/test/application/rake/restart_test.rb +++ b/railties/test/application/rake/restart_test.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "chdir_helpers" module ApplicationTests module RakeTests class RakeRestartTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, ChdirHelpers def setup build_app @@ -16,7 +17,7 @@ def teardown end test "rails restart touches tmp/restart.txt" do - Dir.chdir(app_path) do + chdir(app_path) do rails "restart" assert File.exist?("tmp/restart.txt") @@ -29,7 +30,7 @@ def teardown end test "rails restart should work even if tmp folder does not exist" do - Dir.chdir(app_path) do + chdir(app_path) do FileUtils.remove_dir("tmp") rails "restart" assert File.exist?("tmp/restart.txt") diff --git a/railties/test/application/rake/tmp_test.rb b/railties/test/application/rake/tmp_test.rb index 048fd7adcce49..518ba8f044c7d 100644 --- a/railties/test/application/rake/tmp_test.rb +++ b/railties/test/application/rake/tmp_test.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "chdir_helpers" module ApplicationTests module RakeTests class TmpTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, ChdirHelpers def setup build_app @@ -16,7 +17,7 @@ def teardown end test "tmp:clear clear cache, socket and screenshot files" do - Dir.chdir(app_path) do + chdir(app_path) do FileUtils.mkdir_p("tmp/cache") FileUtils.touch("tmp/cache/cache_file") diff --git a/railties/test/chdir_helpers.rb b/railties/test/chdir_helpers.rb new file mode 100644 index 0000000000000..b7c81e3ae7334 --- /dev/null +++ b/railties/test/chdir_helpers.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module ChdirHelpers + private + def chdir(dir) + pwd = Dir.pwd + Dir.chdir(dir) + yield + ensure + Dir.chdir(pwd) + end +end From 496eb969d13b8252463f78b4ae08c762ef508637 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Fri, 16 Oct 2020 01:00:12 +0100 Subject: [PATCH 110/244] Work around getaddrinfo deadlock in forked process See https://bugs.ruby-lang.org/issues/17220. This will prevent every CI run from getting stuck and eventually timing out after 30 minutes. --- activejob/test/support/integration/adapters/sidekiq.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activejob/test/support/integration/adapters/sidekiq.rb b/activejob/test/support/integration/adapters/sidekiq.rb index 0c01f4e83e9d5..c6cdc3fbb1b92 100644 --- a/activejob/test/support/integration/adapters/sidekiq.rb +++ b/activejob/test/support/integration/adapters/sidekiq.rb @@ -24,6 +24,7 @@ def start_workers continue_read, continue_write = IO.pipe death_read, death_write = IO.pipe + sleep 1 @pid = fork do continue_read.close death_write.close From 29d56d145460faad57cb36fdb63e41a26dd76e41 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sun, 25 Oct 2020 15:49:38 +0900 Subject: [PATCH 111/244] Merge pull request #40451 from yahonda/sneakers Address Active Job integration test with sneakers against ruby 3.0.0dev --- activejob/test/support/integration/adapters/sneakers.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activejob/test/support/integration/adapters/sneakers.rb b/activejob/test/support/integration/adapters/sneakers.rb index 89dc61ca28df8..cfc3d0c89c2ab 100644 --- a/activejob/test/support/integration/adapters/sneakers.rb +++ b/activejob/test/support/integration/adapters/sneakers.rb @@ -28,6 +28,7 @@ def clear_jobs end def start_workers + sleep 1 @pid = fork do queues = %w(integration_tests) workers = queues.map do |q| From c3cbb6d5b1a893f27b7d86270ff222e72ec024ec Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 26 Oct 2020 22:12:56 +0900 Subject: [PATCH 112/244] Merge pull request #40453 from yahonda/resque_start_workers Workaround Active Job integration test with resque against ruby 3.0.0dev --- activejob/test/support/integration/adapters/resque.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activejob/test/support/integration/adapters/resque.rb b/activejob/test/support/integration/adapters/resque.rb index cd129e72b2c0c..e4e7fee864bab 100644 --- a/activejob/test/support/integration/adapters/resque.rb +++ b/activejob/test/support/integration/adapters/resque.rb @@ -19,6 +19,7 @@ def clear_jobs end def start_workers + sleep 1 @resque_thread = Thread.new do w = Resque::Worker.new("integration_tests") w.term_child = true From 7474a8373627222077e92cc1d20f2479a1d56f23 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sun, 1 Nov 2020 16:58:22 +0000 Subject: [PATCH 113/244] Avoid chdir error in bin/setup test on Ruby master Followup to c198dc8cc9ed55280cde1be150c7ee29e7f9d3e5. --- railties/test/application/bin_setup_test.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb index aa0da0931d120..057a2a5ebcd29 100644 --- a/railties/test/application/bin_setup_test.rb +++ b/railties/test/application/bin_setup_test.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "chdir_helpers" module ApplicationTests class BinSetupTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, ChdirHelpers setup :build_app teardown :teardown_app @@ -28,7 +29,7 @@ def test_bin_setup end def test_bin_setup_output - Dir.chdir(app_path) do + chdir(app_path) do # SQLite3 seems to auto-create the database on first checkout. rails "db:system:change", "--to=postgresql" rails "db:drop" From 81a92bbd3b80b53b877c15843a424ef1f9823e20 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Tue, 3 Nov 2020 18:12:24 +0000 Subject: [PATCH 114/244] Merge pull request #40517 from eugeneius/depend_on_message Use LoadError#original_message if available in depend_on --- activesupport/lib/active_support/dependencies.rb | 7 ++++++- activesupport/test/dependencies_test.rb | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 6d71a67a46c07..b62be06b4e9b1 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -367,7 +367,12 @@ def depend_on(file_name, message = "No such file to load -- %s.rb") require_or_load(path || file_name) rescue LoadError => load_error if file_name = load_error.message[/ -- (.*?)(\.rb)?$/, 1] - load_error.message.replace(message % file_name) + load_error_message = if load_error.respond_to?(:original_message) + load_error.original_message + else + load_error.message + end + load_error_message.replace(message % file_name) load_error.copy_blame!(load_error) end raise diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 6bad69f7f224c..7f5c04a9d7982 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -40,6 +40,13 @@ def test_depend_on_path assert_equal expected.path, e.path end + def test_depend_on_message + e = assert_raises(LoadError) do + ActiveSupport::Dependencies.depend_on "omgwtfbbq" + end + assert_equal "No such file to load -- omgwtfbbq.rb", e.message + end + def test_require_dependency_accepts_an_object_which_implements_to_path o = Object.new def o.to_path; "dependencies/service_one"; end From b227e9fd95f90ed4b9637bd6b23097f71e2e66ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Tue, 3 Nov 2020 14:31:46 -0500 Subject: [PATCH 115/244] Merge pull request #40526 from nburwell/doc/add_examples_to_active_record_ignored_columns Add example usage pattern of ActiveRecord::Base.ignored_columns= --- .../lib/active_record/model_schema.rb | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 022d1ba88483d..913369a1d1bcd 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -287,6 +287,35 @@ def ignored_columns # Sets the columns names the model should ignore. Ignored columns won't have attribute # accessors defined, and won't be referenced in SQL queries. + # + # A common usage pattern for this method is to ensure all references to an attribute + # have been removed and deployed, before a migration to drop the column from the database + # has been deployed and run. Using this two step approach to dropping columns ensures there + # is no code that raises errors due to having a cached schema in memory at the time the + # schema migration is run. + # + # For example, given a model where you want to drop the "category" attribute, first mark it + # as ignored: + # + # class Project < ActiveRecord::Base + # # schema: + # # id :bigint + # # name :string, limit: 255 + # # category :string, limit: 255 + # + # self.ignored_columns = [:category] + # end + # + # The schema still contains `category`, but now the model omits it, so any meta-driven code or + # schema caching will not attempt to use the column: + # + # Project.columns_hash["category"] => nil + # + # You will get an error if accessing that attribute directly, so ensure all usages of the + # column are removed (automated tests can help you find any usages). + # + # user = Project.create!(name: "First Project") + # user.category # => raises NoMethodError def ignored_columns=(columns) @ignored_columns = columns.map(&:to_s) end From a496537e364d76798683c921664d2f48b90fef5c Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sun, 8 Nov 2020 13:41:51 +0900 Subject: [PATCH 116/244] `Registry#find_registration` should take keyword argument --- activemodel/lib/active_model/type/registry.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activemodel/lib/active_model/type/registry.rb b/activemodel/lib/active_model/type/registry.rb index 4bd76363cfae2..9e6f8d907887d 100644 --- a/activemodel/lib/active_model/type/registry.rb +++ b/activemodel/lib/active_model/type/registry.rb @@ -33,8 +33,8 @@ def registration_klass Registration end - def find_registration(symbol, *args) - registrations.find { |r| r.matches?(symbol, *args) } + def find_registration(symbol, *args, **kwargs) + registrations.find { |r| r.matches?(symbol, *args, **kwargs) } end end From 1c35b0a34a44e591e7bb56c988369057bf824390 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sun, 15 Nov 2020 01:02:22 +0000 Subject: [PATCH 117/244] Reset Time.zone to avoid leaking into other tests https://buildkite.com/rails/rails/builds/72478#93358e11-6e26-4588-a791-26f9512157c2/1074-1087 https://buildkite.com/rails/rails/builds/72747#10657eba-2359-47ca-9914-49a48b3f2d3c/967-976 https://buildkite.com/rails/rails/builds/72795#3f4bff27-3f42-4678-b643-08cc811c8954/999-1012 --- activejob/test/cases/timezones_test.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/activejob/test/cases/timezones_test.rb b/activejob/test/cases/timezones_test.rb index d1a34212ac8b6..c98520bf68d2d 100644 --- a/activejob/test/cases/timezones_test.rb +++ b/activejob/test/cases/timezones_test.rb @@ -32,5 +32,7 @@ class TimezonesTest < ActiveSupport::TestCase end assert_equal "Happy New Year!", JobBuffer.last_value + ensure + Time.zone = nil end end From e2ef9af8f9d47857f5974e74b1bbd6fbbc0da6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Mon, 30 Nov 2020 18:44:12 -0500 Subject: [PATCH 118/244] Merge pull request #40045 from sandip-mane/40041-hosts-case-fix Adds a fix to whitelist hostnames with case-insensitive matching --- .../middleware/host_authorization.rb | 4 +- .../test/dispatch/host_authorization_test.rb | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index de7739b9b6807..a3c728b8dc6d7 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -46,9 +46,9 @@ def sanitize_regexp(host) def sanitize_string(host) if host.start_with?(".") - /\A(.+\.)?#{Regexp.escape(host[1..-1])}\z/ + /\A(.+\.)?#{Regexp.escape(host[1..-1])}\z/i else - host + /\A#{host}\z/i end end end diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb index 5263dd2597f28..4174de134552d 100644 --- a/actionpack/test/dispatch/host_authorization_test.rb +++ b/actionpack/test/dispatch/host_authorization_test.rb @@ -42,6 +42,50 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_equal "Success", body end + test "hosts are matched case insensitive" do + @app = ActionDispatch::HostAuthorization.new(App, "Example.local") + + get "/", env: { + "HOST" => "example.local", + } + + assert_response :ok + assert_equal "Success", body + end + + test "hosts are matched case insensitive with titlecased host" do + @app = ActionDispatch::HostAuthorization.new(App, "example.local") + + get "/", env: { + "HOST" => "Example.local", + } + + assert_response :ok + assert_equal "Success", body + end + + test "hosts are matched case insensitive with hosts array" do + @app = ActionDispatch::HostAuthorization.new(App, ["Example.local"]) + + get "/", env: { + "HOST" => "example.local", + } + + assert_response :ok + assert_equal "Success", body + end + + test "regex matches are not title cased" do + @app = ActionDispatch::HostAuthorization.new(App, [/www.Example.local/]) + + get "/", env: { + "HOST" => "www.example.local", + } + + assert_response :forbidden + assert_match "Blocked host: www.example.local", response.body + end + test "passes requests to allowed hosts with domain name notation" do @app = ActionDispatch::HostAuthorization.new(App, ".example.com") From fc99589f175a0152c5b62e985c9368db4f11c341 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sat, 21 Nov 2020 11:03:04 +0900 Subject: [PATCH 119/244] Mark scrub as an unsafe method on SafeBuffer --- .../lib/active_support/core_ext/string/output_safety.rb | 2 +- activesupport/test/safe_buffer_test.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index e226779422f1d..5893360904eb6 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -135,7 +135,7 @@ module ActiveSupport #:nodoc: class SafeBuffer < String UNSAFE_STRING_METHODS = %w( capitalize chomp chop delete delete_prefix delete_suffix - downcase lstrip next reverse rstrip slice squeeze strip + downcase lstrip next reverse rstrip scrub slice squeeze strip succ swapcase tr tr_s unicode_normalize upcase ) diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 9a0ac88a9264b..2796aacad14fe 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -88,6 +88,7 @@ def test_titleize next: nil, reverse: nil, rstrip: nil, + scrub: nil, slice: "foo", squeeze: nil, strip: nil, From ca1e8d6ae4a3b5f173cbae449564e15bb2cbd861 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 1 Dec 2020 17:42:37 +0900 Subject: [PATCH 120/244] Merge pull request #40663 from amatsuda/keep_safe_buffer Let AS::SafeBuffer#[] and * return value be an instance of SafeBuffer in Ruby 3.0 --- .../active_support/core_ext/string/output_safety.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 5893360904eb6..5b2b3162f2e00 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -153,12 +153,12 @@ def initialize def [](*args) if html_safe? - new_safe_buffer = super + new_string = super - if new_safe_buffer - new_safe_buffer.instance_variable_set :@html_safe, true - end + return unless new_string + new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string) + new_safe_buffer.instance_variable_set :@html_safe, true new_safe_buffer else to_str[*args] @@ -214,7 +214,8 @@ def +(other) end def *(*) - new_safe_buffer = super + new_string = super + new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string) new_safe_buffer.instance_variable_set(:@html_safe, @html_safe) new_safe_buffer end From b03c7962fc712a40462fb95ef9804b31c962385c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 8 Dec 2020 18:09:32 +0000 Subject: [PATCH 121/244] Fix schema dumper when datetime infitnity defaults are set Fixes #40751. --- .../connection_adapters/postgresql/oid/date_time.rb | 8 ++++++++ activerecord/test/cases/schema_dumper_test.rb | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_time.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_time.rb index cd667422f5598..11ac7206df2cf 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_time.rb @@ -16,6 +16,14 @@ def cast_value(value) super end end + + def type_cast_for_schema(value) + case value + when ::Float::INFINITY then "::Float::INFINITY" + when -::Float::INFINITY then "-::Float::INFINITY" + else super + end + end end end end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index bb7184c5fc4f6..683b097f15784 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -501,6 +501,8 @@ class SchemaDumperDefaultsTest < ActiveRecord::TestCase @connection.create_table :infinity_defaults, force: true do |t| t.float :float_with_inf_default, default: Float::INFINITY t.float :float_with_nan_default, default: Float::NAN + t.datetime :beginning_of_time, default: "-infinity" + t.datetime :end_of_time, default: "infinity" end end end @@ -519,10 +521,12 @@ def test_schema_dump_defaults_with_universally_supported_types assert_match %r{t\.decimal\s+"decimal_with_default",\s+precision: 20,\s+scale: 10,\s+default: "1234567890.0123456789"}, output end - def test_schema_dump_with_float_column_infinity_default + def test_schema_dump_with_column_infinity_default skip unless current_adapter?(:PostgreSQLAdapter) output = dump_table_schema("infinity_defaults") assert_match %r{t\.float\s+"float_with_inf_default",\s+default: ::Float::INFINITY}, output assert_match %r{t\.float\s+"float_with_nan_default",\s+default: ::Float::NAN}, output + assert_match %r{t\.datetime\s+"beginning_of_time",\s+default: -::Float::INFINITY}, output + assert_match %r{t\.datetime\s+"end_of_time",\s+default: ::Float::INFINITY}, output end end From 9698570a354791f9f9986325b4315a397cda22aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 8 Dec 2020 22:33:39 +0000 Subject: [PATCH 122/244] Merge PR #39587 Closes #39587. --- actionview/CHANGELOG.md | 8 ++++++++ .../lib/action_view/helpers/sanitize_helper.rb | 4 ++-- actionview/test/template/sanitize_helper_test.rb | 13 +++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 9c1e8eb0f58ec..67337ed55b238 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,11 @@ +* SanitizeHelper.sanitized_allowed_attributes and SanitizeHelper.sanitized_allowed_tags + call safe_list_sanitizer's class method + + Fixes #39586 + + *Taufiq Muhammadi* + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/actionview/lib/action_view/helpers/sanitize_helper.rb b/actionview/lib/action_view/helpers/sanitize_helper.rb index 8724e04d56a43..3035c320f355a 100644 --- a/actionview/lib/action_view/helpers/sanitize_helper.rb +++ b/actionview/lib/action_view/helpers/sanitize_helper.rb @@ -129,11 +129,11 @@ def sanitizer_vendor end def sanitized_allowed_tags - safe_list_sanitizer.allowed_tags + sanitizer_vendor.safe_list_sanitizer.allowed_tags end def sanitized_allowed_attributes - safe_list_sanitizer.allowed_attributes + sanitizer_vendor.safe_list_sanitizer.allowed_attributes end # Gets the Rails::Html::FullSanitizer instance used by +strip_tags+. Replace with diff --git a/actionview/test/template/sanitize_helper_test.rb b/actionview/test/template/sanitize_helper_test.rb index 181f09ab65899..4a2a21996be66 100644 --- a/actionview/test/template/sanitize_helper_test.rb +++ b/actionview/test/template/sanitize_helper_test.rb @@ -40,4 +40,17 @@ def test_strip_tags_will_not_encode_special_characters def test_sanitize_is_marked_safe assert_predicate sanitize(""), :html_safe? end + + def test_sanitized_allowed_tags_class_method + expected = Set.new(["strong", "em", "b", "i", "p", "code", "pre", "tt", "samp", "kbd", "var", + "sub", "sup", "dfn", "cite", "big", "small", "address", "hr", "br", "div", "span", "h1", "h2", + "h3", "h4", "h5", "h6", "ul", "ol", "li", "dl", "dt", "dd", "abbr", "acronym", "a", "img", + "blockquote", "del", "ins"]) + assert_equal(expected, self.class.sanitized_allowed_tags) + end + + def test_sanitized_allowed_attributes_class_method + expected = Set.new(["href", "src", "width", "height", "alt", "cite", "datetime", "title", "class", "name", "xml:lang", "abbr"]) + assert_equal(expected, self.class.sanitized_allowed_attributes) + end end From 539dc16221cbabdd46dbe762a458e046c6e827b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Wed, 9 Dec 2020 12:11:31 -0500 Subject: [PATCH 123/244] Merge pull request #40679 from ghiculescu/negative-enum-warning Better handling of negative elements in enum --- activerecord/CHANGELOG.md | 6 ++ activerecord/lib/active_record/enum.rb | 19 ++++-- activerecord/test/cases/enum_test.rb | 81 ++++++++++++++++++++++++-- 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 636c72a8e4582..f73d2ab366257 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* Only warn about negative enums if a positive form that would cause conflicts exists. + + Fixes #39065. + + *Alex Ghiculescu* + * Allow the inverse of a `has_one` association that was previously autosaved to be loaded. Fixes #34255. diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index fc49f752aa4c2..5ef8bad342103 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -173,6 +173,7 @@ def enum(definitions) _enum_methods_module.module_eval do pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index + value_method_names = [] pairs.each do |label, value| if enum_prefix == true prefix = "#{name}_" @@ -186,6 +187,7 @@ def enum(definitions) end value_method_name = "#{prefix}#{label}#{suffix}" + value_method_names << value_method_name enum_values[label] = value label = label.to_s @@ -200,8 +202,6 @@ def enum(definitions) # scope :active, -> { where(status: 0) } # scope :not_active, -> { where.not(status: 0) } if enum_scopes != false - klass.send(:detect_negative_condition!, value_method_name) - klass.send(:detect_enum_conflict!, name, value_method_name, true) klass.scope value_method_name, -> { where(attr => value) } @@ -209,6 +209,7 @@ def enum(definitions) klass.scope "not_#{value_method_name}", -> { where.not(attr => value) } end end + klass.send(:detect_negative_enum_conditions!, value_method_names) if enum_scopes != false end enum_values.freeze end @@ -264,10 +265,16 @@ def raise_conflict_error(enum_name, method_name, type: "instance", source: "Acti } end - def detect_negative_condition!(method_name) - if method_name.start_with?("not_") && logger - logger.warn "An enum element in #{self.name} uses the prefix 'not_'." \ - " This will cause a conflict with auto generated negative scopes." + def detect_negative_enum_conditions!(method_names) + return unless logger + + method_names.select { |m| m.start_with?("not_") }.each do |potential_not| + inverted_form = potential_not.sub("not_", "") + if method_names.include?(inverted_form) + logger.warn "Enum element '#{potential_not}' in #{self.name} uses the prefix 'not_'." \ + " This has caused a conflict with auto generated negative scopes." \ + " Avoid using enum elements starting with 'not' where the positive form is also an element." + end end end end diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb index 0ae156320a5df..1b59f5d8bc65f 100644 --- a/activerecord/test/cases/enum_test.rb +++ b/activerecord/test/cases/enum_test.rb @@ -567,14 +567,18 @@ def self.name; "Book"; end assert_raises(NoMethodError) { klass.proposed } end - test "enums with a negative condition log a warning" do + test "enum logs a warning if auto-generated negative scopes would clash with other enum names" do old_logger = ActiveRecord::Base.logger logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new ActiveRecord::Base.logger = logger - expected_message = "An enum element in Book uses the prefix 'not_'."\ - " This will cause a conflict with auto generated negative scopes." + expected_message_1 = "Enum element 'not_sent' in Book uses the prefix 'not_'."\ + " This has caused a conflict with auto generated negative scopes."\ + " Avoid using enum elements starting with 'not' where the positive form is also an element." + + # this message comes from ActiveRecord::Scoping::Named, but it's worth noting that both occur in this case + expected_message_2 = "Creating scope :not_sent. Overwriting existing method Book.not_sent." Class.new(ActiveRecord::Base) do def self.name @@ -585,7 +589,76 @@ def self.name end end - assert_match(expected_message, logger.logged(:warn).first) + assert_includes(logger.logged(:warn), expected_message_1) + assert_includes(logger.logged(:warn), expected_message_2) + ensure + ActiveRecord::Base.logger = old_logger + end + + test "enum logs a warning if auto-generated negative scopes would clash with other enum names regardless of order" do + old_logger = ActiveRecord::Base.logger + logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new + + ActiveRecord::Base.logger = logger + + expected_message_1 = "Enum element 'not_sent' in Book uses the prefix 'not_'."\ + " This has caused a conflict with auto generated negative scopes."\ + " Avoid using enum elements starting with 'not' where the positive form is also an element." + + # this message comes from ActiveRecord::Scoping::Named, but it's worth noting that both occur in this case + expected_message_2 = "Creating scope :not_sent. Overwriting existing method Book.not_sent." + + Class.new(ActiveRecord::Base) do + def self.name + "Book" + end + silence_warnings do + enum status: [:not_sent, :sent] + end + end + + assert_includes(logger.logged(:warn), expected_message_1) + assert_includes(logger.logged(:warn), expected_message_2) + ensure + ActiveRecord::Base.logger = old_logger + end + + test "enum doesn't log a warning if no clashes detected" do + old_logger = ActiveRecord::Base.logger + logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new + + ActiveRecord::Base.logger = logger + + Class.new(ActiveRecord::Base) do + def self.name + "Book" + end + silence_warnings do + enum status: [:not_sent] + end + end + + assert_empty(logger.logged(:warn)) + ensure + ActiveRecord::Base.logger = old_logger + end + + test "enum doesn't log a warning if opting out of scopes" do + old_logger = ActiveRecord::Base.logger + logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new + + ActiveRecord::Base.logger = logger + + Class.new(ActiveRecord::Base) do + def self.name + "Book" + end + silence_warnings do + enum status: [:not_sent, :sent], _scopes: false + end + end + + assert_empty(logger.logged(:warn)) ensure ActiveRecord::Base.logger = old_logger end From 901f12212c488f6edfcf6f8ad3230bce6b3d5792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Wed, 9 Dec 2020 13:38:44 -0500 Subject: [PATCH 124/244] Merge pull request #40168 from igor04/disable_with_and_automatically_disable_submit_tag Do not use submit_tag auto-disabling when disable_with is set to false --- actionview/lib/action_view/helpers/form_tag_helper.rb | 11 +++++------ actionview/test/template/form_tag_helper_test.rb | 10 ++++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/actionview/lib/action_view/helpers/form_tag_helper.rb b/actionview/lib/action_view/helpers/form_tag_helper.rb index 244b341b0701d..1dfb66958b557 100644 --- a/actionview/lib/action_view/helpers/form_tag_helper.rb +++ b/actionview/lib/action_view/helpers/form_tag_helper.rb @@ -896,16 +896,15 @@ def sanitize_to_id(name) end def set_default_disable_with(value, tag_options) - return unless ActionView::Base.automatically_disable_submit_tag - data = tag_options["data"] + data = tag_options.fetch("data", {}) - unless tag_options["data-disable-with"] == false || (data && data["disable_with"] == false) + if tag_options["data-disable-with"] == false || data["disable_with"] == false + data.delete("disable_with") + elsif ActionView::Base.automatically_disable_submit_tag disable_with_text = tag_options["data-disable-with"] - disable_with_text ||= data["disable_with"] if data + disable_with_text ||= data["disable_with"] disable_with_text ||= value.to_s.clone tag_options.deep_merge!("data" => { "disable_with" => disable_with_text }) - else - data.delete("disable_with") if data end tag_options.delete("data-disable-with") diff --git a/actionview/test/template/form_tag_helper_test.rb b/actionview/test/template/form_tag_helper_test.rb index 80afed96e5876..17c2fe4f79b38 100644 --- a/actionview/test/template/form_tag_helper_test.rb +++ b/actionview/test/template/form_tag_helper_test.rb @@ -538,6 +538,16 @@ def test_empty_submit_tag_with_opt_out ActionView::Base.automatically_disable_submit_tag = true end + def test_empty_submit_tag_with_opt_out_and_explicit_disabling + ActionView::Base.automatically_disable_submit_tag = false + assert_dom_equal( + %(), + submit_tag("Save", data: { disable_with: false }) + ) + ensure + ActionView::Base.automatically_disable_submit_tag = true + end + def test_submit_tag_having_data_disable_with_string assert_dom_equal( %(), From b373235ba97a727be844ccbbc4851ba15ac8eb2e Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sat, 26 Dec 2020 10:30:50 +0000 Subject: [PATCH 125/244] Merge pull request #40936 from yahonda/follow_up_ruby_3990 Remove ChdirHelpers because https://bugs.ruby-lang.org/issues/15661 has been addressed --- railties/test/application/bin_setup_test.rb | 5 ++- railties/test/application/rake/dbs_test.rb | 35 +++++++++---------- railties/test/application/rake/log_test.rb | 5 ++- .../test/application/rake/migrations_test.rb | 13 +++---- .../test/application/rake/multi_dbs_test.rb | 27 +++++++------- .../test/application/rake/restart_test.rb | 7 ++-- railties/test/application/rake/tmp_test.rb | 5 ++- railties/test/chdir_helpers.rb | 12 ------- 8 files changed, 44 insertions(+), 65 deletions(-) delete mode 100644 railties/test/chdir_helpers.rb diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb index 057a2a5ebcd29..aa0da0931d120 100644 --- a/railties/test/application/bin_setup_test.rb +++ b/railties/test/application/bin_setup_test.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true require "isolation/abstract_unit" -require "chdir_helpers" module ApplicationTests class BinSetupTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation, ChdirHelpers + include ActiveSupport::Testing::Isolation setup :build_app teardown :teardown_app @@ -29,7 +28,7 @@ def test_bin_setup end def test_bin_setup_output - chdir(app_path) do + Dir.chdir(app_path) do # SQLite3 seems to auto-create the database on first checkout. rails "db:system:change", "--to=postgresql" rails "db:drop" diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index 24ce92abba2d3..54a09e122097a 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -1,13 +1,12 @@ # frozen_string_literal: true require "isolation/abstract_unit" -require "chdir_helpers" require "env_helpers" module ApplicationTests module RakeTests class RakeDbsTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation, ChdirHelpers, EnvHelpers + include ActiveSupport::Testing::Isolation, EnvHelpers def setup build_app @@ -29,7 +28,7 @@ def set_database_url end def db_create_and_drop(expected_database, environment_loaded: true) - chdir(app_path) do + Dir.chdir(app_path) do output = rails("db:create") assert_match(/Created database/, output) assert File.exist?(expected_database) @@ -42,7 +41,7 @@ def db_create_and_drop(expected_database, environment_loaded: true) end def db_create_with_warning(expected_database) - chdir(app_path) do + Dir.chdir(app_path) do output = rails("db:create") assert_match(/Rails couldn't infer whether you are using multiple databases/, output) assert_match(/Created database/, output) @@ -185,7 +184,7 @@ def db_create_with_warning(expected_database) end def with_database_existing - chdir(app_path) do + Dir.chdir(app_path) do set_database_url rails "db:create" yield @@ -201,7 +200,7 @@ def with_database_existing end def with_bad_permissions - chdir(app_path) do + Dir.chdir(app_path) do skip "Can't avoid permissions as root" if Process.uid.zero? set_database_url @@ -249,7 +248,7 @@ def with_bad_permissions end test "db:truncate_all truncates all non-internal tables" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" require "#{app_path}/config/environment" @@ -274,7 +273,7 @@ def with_bad_permissions test "db:truncate_all does not truncate any tables when environment is protected" do with_rails_env "production" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" require "#{app_path}/config/environment" @@ -321,7 +320,7 @@ def db_migrate_and_status(expected_database) end def db_schema_dump - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate", "db:schema:dump" schema_dump = File.read("db/schema.rb") @@ -339,7 +338,7 @@ def db_schema_dump end def db_schema_cache_dump(filename = "db/schema_cache.yml") - chdir(app_path) do + Dir.chdir(app_path) do rails "db:schema:cache:dump" cache_size = lambda { rails("runner", "p ActiveRecord::Base.connection.schema_cache.size").strip } @@ -357,7 +356,7 @@ def db_schema_cache_dump(filename = "db/schema_cache.yml") end test "db:schema:cache:dump with custom filename" do - chdir(app_path) do + Dir.chdir(app_path) do File.open("#{app_path}/config/database.yml", "w") do |f| f.puts <<-YAML default: &default @@ -379,7 +378,7 @@ def db_schema_cache_dump(filename = "db/schema_cache.yml") end def db_fixtures_load(expected_database) - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" reload rails "db:migrate", "db:fixtures:load" @@ -411,7 +410,7 @@ def db_fixtures_load(expected_database) end def db_structure_dump_and_load(expected_database) - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate", "db:structure:dump" structure_dump = File.read("db/structure.sql") @@ -508,7 +507,7 @@ def db_structure_dump_and_load(expected_database) end def db_test_load_structure - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate", "db:structure:dump", "db:test:load_structure" ActiveRecord::Base.configurations = Rails.application.config.database_configuration @@ -591,7 +590,7 @@ def db_test_load_structure end test "db:seed:replant truncates all non-internal tables and loads the seeds" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" require "#{app_path}/config/environment" @@ -624,7 +623,7 @@ def db_test_load_structure test "db:seed:replant does not truncate any tables and does not load the seeds when environment is protected" do with_rails_env "production" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" require "#{app_path}/config/environment" @@ -657,7 +656,7 @@ def db_test_load_structure end test "db:prepare setup the database" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" output = rails("db:prepare") assert_match(/CreateBooks: migrated/, output) @@ -673,7 +672,7 @@ def db_test_load_structure end test "db:prepare does not touch schema when dumping is disabled" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:create", "db:migrate" diff --git a/railties/test/application/rake/log_test.rb b/railties/test/application/rake/log_test.rb index fae358a052221..678f26db26aae 100644 --- a/railties/test/application/rake/log_test.rb +++ b/railties/test/application/rake/log_test.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true require "isolation/abstract_unit" -require "chdir_helpers" module ApplicationTests module RakeTests class LogTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation, ChdirHelpers + include ActiveSupport::Testing::Isolation def setup build_app @@ -17,7 +16,7 @@ def teardown end test "log:clear clear all environments log files by default" do - chdir(app_path) do + Dir.chdir(app_path) do File.open("config/environments/staging.rb", "w") File.write("log/staging.log", "staging") diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb index aac0506e6d676..47c5ac105a4e7 100644 --- a/railties/test/application/rake/migrations_test.rb +++ b/railties/test/application/rake/migrations_test.rb @@ -1,13 +1,10 @@ # frozen_string_literal: true require "isolation/abstract_unit" -require "chdir_helpers" module ApplicationTests module RakeTests class RakeMigrationsTest < ActiveSupport::TestCase - include ChdirHelpers - def setup build_app FileUtils.rm_rf("#{app_path}/config/environments") @@ -268,7 +265,7 @@ class TwoMigration < ActiveRecord::Migration::Current end test "raise error on any move when current migration does not exist" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "user", "username:string", "password:string" rails "generate", "migration", "add_email_to_users", "email:string" rails "db:migrate" @@ -414,7 +411,7 @@ class TwoMigration < ActiveRecord::Migration::Current test "schema generation when dump_schema_after_migration is set" do add_to_config("config.active_record.dump_schema_after_migration = false") - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" output = rails("generate", "model", "author", "name:string") version = output =~ %r{[^/]+db/migrate/(\d+)_create_authors\.rb} && $1 @@ -425,7 +422,7 @@ class TwoMigration < ActiveRecord::Migration::Current add_to_config("config.active_record.dump_schema_after_migration = true") - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "reviews", "book_id:integer" rails "db:migrate" @@ -435,7 +432,7 @@ class TwoMigration < ActiveRecord::Migration::Current end test "default schema generation after migration" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" rails "db:migrate" @@ -445,7 +442,7 @@ class TwoMigration < ActiveRecord::Migration::Current end test "migration status migrated file is deleted" do - chdir(app_path) do + Dir.chdir(app_path) do rails "generate", "model", "user", "username:string", "password:string" rails "generate", "migration", "add_email_to_users", "email:string" rails "db:migrate" diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb index 754ab258c25cb..16c4040c87d51 100644 --- a/railties/test/application/rake/multi_dbs_test.rb +++ b/railties/test/application/rake/multi_dbs_test.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true require "isolation/abstract_unit" -require "chdir_helpers" module ApplicationTests module RakeTests class RakeMultiDbsTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation, ChdirHelpers + include ActiveSupport::Testing::Isolation def setup build_app(multi_db: true) @@ -18,7 +17,7 @@ def teardown end def db_create_and_drop(namespace, expected_database) - chdir(app_path) do + Dir.chdir(app_path) do output = rails("db:create") assert_match(/Created database/, output) assert_match_namespace(namespace, output) @@ -34,7 +33,7 @@ def db_create_and_drop(namespace, expected_database) end def db_create_and_drop_namespace(namespace, expected_database) - chdir(app_path) do + Dir.chdir(app_path) do output = rails("db:create:#{namespace}") assert_match(/Created database/, output) assert_match_namespace(namespace, output) @@ -56,7 +55,7 @@ def assert_match_namespace(namespace, output) end def db_migrate_and_migrate_status - chdir(app_path) do + Dir.chdir(app_path) do generate_models_for_animals rails "db:migrate" output = rails "db:migrate:status" @@ -66,7 +65,7 @@ def db_migrate_and_migrate_status end def db_migrate_and_schema_cache_dump - chdir(app_path) do + Dir.chdir(app_path) do generate_models_for_animals rails "db:migrate" rails "db:schema:cache:dump" @@ -76,7 +75,7 @@ def db_migrate_and_schema_cache_dump end def db_migrate_and_schema_cache_dump_and_schema_cache_clear - chdir(app_path) do + Dir.chdir(app_path) do generate_models_for_animals rails "db:migrate" rails "db:schema:cache:dump" @@ -87,7 +86,7 @@ def db_migrate_and_schema_cache_dump_and_schema_cache_clear end def db_migrate_and_schema_dump_and_load(format) - chdir(app_path) do + Dir.chdir(app_path) do generate_models_for_animals rails "db:migrate", "db:#{format}:dump" @@ -114,7 +113,7 @@ def db_migrate_and_schema_dump_and_load(format) end def db_migrate_namespaced(namespace) - chdir(app_path) do + Dir.chdir(app_path) do generate_models_for_animals output = rails("db:migrate:#{namespace}") if namespace == "primary" @@ -126,7 +125,7 @@ def db_migrate_namespaced(namespace) end def db_migrate_status_namespaced(namespace) - chdir(app_path) do + Dir.chdir(app_path) do generate_models_for_animals output = rails("db:migrate:status:#{namespace}") if namespace == "primary" @@ -138,7 +137,7 @@ def db_migrate_status_namespaced(namespace) end def db_up_and_down(version, namespace = nil) - chdir(app_path) do + Dir.chdir(app_path) do generate_models_for_animals rails("db:migrate") @@ -168,7 +167,7 @@ def db_up_and_down(version, namespace = nil) end def db_prepare - chdir(app_path) do + Dir.chdir(app_path) do generate_models_for_animals output = rails("db:prepare") @@ -233,7 +232,7 @@ def generate_models_for_animals end test "db:migrate set back connection to its original state" do - chdir(app_path) do + Dir.chdir(app_path) do dummy_task = <<~RUBY task foo: :environment do Book.first @@ -369,7 +368,7 @@ class TwoMigration < ActiveRecord::Migration::Current test "db:prepare setups missing database without clearing existing one" do require "#{app_path}/config/environment" - chdir(app_path) do + Dir.chdir(app_path) do # Bug not visible on SQLite3. Can be simplified when https://github.com/rails/rails/issues/36383 resolved use_postgresql(multi_db: true) generate_models_for_animals diff --git a/railties/test/application/rake/restart_test.rb b/railties/test/application/rake/restart_test.rb index c4e737ac9cd1c..8614560bf23bd 100644 --- a/railties/test/application/rake/restart_test.rb +++ b/railties/test/application/rake/restart_test.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true require "isolation/abstract_unit" -require "chdir_helpers" module ApplicationTests module RakeTests class RakeRestartTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation, ChdirHelpers + include ActiveSupport::Testing::Isolation def setup build_app @@ -17,7 +16,7 @@ def teardown end test "rails restart touches tmp/restart.txt" do - chdir(app_path) do + Dir.chdir(app_path) do rails "restart" assert File.exist?("tmp/restart.txt") @@ -30,7 +29,7 @@ def teardown end test "rails restart should work even if tmp folder does not exist" do - chdir(app_path) do + Dir.chdir(app_path) do FileUtils.remove_dir("tmp") rails "restart" assert File.exist?("tmp/restart.txt") diff --git a/railties/test/application/rake/tmp_test.rb b/railties/test/application/rake/tmp_test.rb index 518ba8f044c7d..048fd7adcce49 100644 --- a/railties/test/application/rake/tmp_test.rb +++ b/railties/test/application/rake/tmp_test.rb @@ -1,12 +1,11 @@ # frozen_string_literal: true require "isolation/abstract_unit" -require "chdir_helpers" module ApplicationTests module RakeTests class TmpTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation, ChdirHelpers + include ActiveSupport::Testing::Isolation def setup build_app @@ -17,7 +16,7 @@ def teardown end test "tmp:clear clear cache, socket and screenshot files" do - chdir(app_path) do + Dir.chdir(app_path) do FileUtils.mkdir_p("tmp/cache") FileUtils.touch("tmp/cache/cache_file") diff --git a/railties/test/chdir_helpers.rb b/railties/test/chdir_helpers.rb deleted file mode 100644 index b7c81e3ae7334..0000000000000 --- a/railties/test/chdir_helpers.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -module ChdirHelpers - private - def chdir(dir) - pwd = Dir.pwd - Dir.chdir(dir) - yield - ensure - Dir.chdir(pwd) - end -end From 9624a60caf19f15df62a9ce31218ff8f9fdd79cc Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 23 Dec 2020 07:46:28 +0900 Subject: [PATCH 126/244] Merge pull request #40909 from yahonda/lock_webpacker_version_to_5 Lock rails/webpacker npm package version to 5 --- railties/test/isolation/assets/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/isolation/assets/package.json b/railties/test/isolation/assets/package.json index 7c34450fe09f8..b6748cb45870f 100644 --- a/railties/test/isolation/assets/package.json +++ b/railties/test/isolation/assets/package.json @@ -5,7 +5,7 @@ "@rails/actioncable": "file:../../../../actioncable", "@rails/activestorage": "file:../../../../activestorage", "@rails/ujs": "file:../../../../actionview", - "@rails/webpacker": "https://github.com/rails/webpacker.git", + "@rails/webpacker": "^5.2.1", "turbolinks": "^5.2.0" } } From 262ab35a070ecf862c0ddfa12255b77e4d455694 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 10 Sep 2020 18:47:01 +0900 Subject: [PATCH 127/244] Merge pull request #40210 from utilum/update_minitest_to_ruby3_compatible Update Minitest to allow installation with Ruby 3. --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 74f61621abdf4..c0c9b59b5fafe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -308,7 +308,7 @@ GEM mini_magick (4.9.5) mini_mime (1.0.2) mini_portile2 (2.4.0) - minitest (5.14.0) + minitest (5.14.2) minitest-bisect (1.5.1) minitest-server (~> 1.0) path_expander (~> 1.1) From fad971f02f675236b3bbe6c38109ff06a7cf53be Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 24 Sep 2020 15:24:26 +0900 Subject: [PATCH 128/244] Use master branch for `listen` and `redis-namespace` To fix CI build in Ruby 3.0 for the time being. --- Gemfile | 4 ++-- Gemfile.lock | 28 ++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 60766bd39126a..96f41572ec75e 100644 --- a/Gemfile +++ b/Gemfile @@ -41,7 +41,7 @@ end # Active Support gem "dalli" -gem "listen", "~> 3.2", require: false +gem "listen", "~> 3.2", require: false, github: "guard/listen" gem "libxml-ruby", platforms: :ruby gem "connection_pool", require: false gem "rexml", require: false @@ -71,7 +71,7 @@ group :cable do gem "hiredis", require: false gem "redis", "~> 4.0", require: false - gem "redis-namespace" + gem "redis-namespace", github: "resque/redis-namespace" gem "websocket-client-simple", github: "matthewd/websocket-client-simple", branch: "close-race", require: false diff --git a/Gemfile.lock b/Gemfile.lock index c0c9b59b5fafe..bd376a795d90a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,14 @@ GIT queue_classic (4.0.0.pre.alpha1) pg (>= 0.17, < 2.0) +GIT + remote: https://github.com/guard/listen.git + revision: 86e06aeb0878dcd46fd635d620656748255d3f67 + specs: + listen (3.2.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + GIT remote: https://github.com/matthewd/websocket-client-simple.git revision: e161305f1a466b9398d86df3b1731b03362da91b @@ -14,6 +22,13 @@ GIT event_emitter websocket +GIT + remote: https://github.com/resque/redis-namespace.git + revision: c31e63dc3cd5e59ef5ea394d4d46ac60d1e6f82e + specs: + redis-namespace (1.8.0) + redis (>= 3.0.4) + PATH remote: . specs: @@ -292,9 +307,6 @@ GEM mustache nokogiri libxml-ruby (3.1.0) - listen (3.2.0) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) loofah (2.7.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) @@ -378,14 +390,12 @@ GEM loofah (~> 2.3) rainbow (3.0.0) rake (13.0.1) - rb-fsevent (0.10.3) + rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) rdoc (6.2.1) redcarpet (3.2.3) redis (4.2.0) - redis-namespace (1.7.0) - redis (>= 3.0.4) regexp_parser (1.6.0) representable (3.0.4) declarative (< 0.1.0) @@ -529,9 +539,11 @@ GEM PLATFORMS java + mswin64 ruby x64-mingw32 x86-mingw32 + x86-mswin32 DEPENDENCIES activerecord-jdbcmysql-adapter (>= 1.3.0) @@ -558,7 +570,7 @@ DEPENDENCIES json (>= 2.0.0) kindlerb (~> 1.2.0) libxml-ruby - listen (~> 3.2) + listen (~> 3.2)! minitest-bisect minitest-reporters minitest-retry @@ -576,7 +588,7 @@ DEPENDENCIES rake (>= 11.1) redcarpet (~> 3.2.3) redis (~> 4.0) - redis-namespace + redis-namespace! resque resque-scheduler rexml From 924cbe6367f28ab3115484510e617b6f6670e51c Mon Sep 17 00:00:00 2001 From: utilum Date: Mon, 21 Sep 2020 05:19:59 +0000 Subject: [PATCH 129/244] Update w3c_validtors for Ruby 3 compatibility (#40227) * Update w3c_validtors for Ruby 3 compatibility * Update google-api-client for Ruby 3 compatibility Co-authored-by: Ryuta Kamizono --- Gemfile | 2 +- Gemfile.lock | 50 ++++++++++++++++++++++++++------------------------ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/Gemfile b/Gemfile index 96f41572ec75e..125619b68d575 100644 --- a/Gemfile +++ b/Gemfile @@ -35,7 +35,7 @@ gem "rubocop-rails", require: false group :doc do gem "sdoc", "~> 1.1" gem "redcarpet", "~> 3.2.3", platforms: :ruby - gem "w3c_validators" + gem "w3c_validators", "~> 1.3.6" gem "kindlerb", "~> 1.2.0" end diff --git a/Gemfile.lock b/Gemfile.lock index bd376a795d90a..59c319f496df0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -127,7 +127,7 @@ GEM public_suffix (>= 2.0.2, < 5.0) amq-protocol (2.3.0) ansi (1.5.0) - ast (2.4.0) + ast (2.4.1) aws-eventstream (1.0.3) aws-partitions (1.260.0) aws-sdk-core (3.86.0) @@ -212,7 +212,7 @@ GEM daemons (1.3.1) dalli (2.7.10) dante (0.2.0) - declarative (0.0.10) + declarative (0.0.20) declarative-option (0.1.0) delayed_job (4.1.8) activesupport (>= 3.0, < 6.1) @@ -234,7 +234,7 @@ GEM event_emitter (0.2.6) eventmachine (1.2.7) execjs (2.7.0) - faraday (0.17.1) + faraday (0.17.3) multipart-post (>= 1.2, < 3) faraday_middleware (0.13.1) faraday (>= 0.7.4, < 1.0) @@ -258,13 +258,14 @@ GEM raabro (~> 1.1) globalid (0.4.2) activesupport (>= 4.2.0) - google-api-client (0.36.2) + google-api-client (0.45.0) addressable (~> 2.5, >= 2.5.1) googleauth (~> 0.9) httpclient (>= 2.8.1, < 3.0) mini_mime (~> 1.0) representable (~> 3.0) retriable (>= 2.0, < 4.0) + rexml signet (~> 0.12) google-cloud-core (1.4.1) google-cloud-env (~> 1.0) @@ -277,13 +278,13 @@ GEM google-cloud-core (~> 1.2) googleauth (~> 0.9) mini_mime (~> 1.0) - googleauth (0.10.0) - faraday (~> 0.12) + googleauth (0.14.0) + faraday (>= 0.17.3, < 2.0) jwt (>= 1.4, < 3.0) memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) - signet (~> 0.12) + signet (~> 0.14) hashdiff (1.0.0) hiredis (0.6.3) hiredis (0.6.3-java) @@ -300,9 +301,9 @@ GEM jdbc-postgres (42.2.6) jdbc-sqlite3 (3.28.0) jmespath (1.4.0) - json (2.3.0) - json (2.3.0-java) - jwt (2.2.1) + json (2.3.1) + json (2.3.1-java) + jwt (2.2.2) kindlerb (1.2.0) mustache nokogiri @@ -338,7 +339,7 @@ GEM msgpack (1.3.1-java) msgpack (1.3.1-x64-mingw32) msgpack (1.3.1-x86-mingw32) - multi_json (1.14.1) + multi_json (1.15.0) multipart-post (2.1.1) mustache (1.1.1) mustermann (1.0.3) @@ -347,23 +348,23 @@ GEM mysql2 (0.5.3-x86-mingw32) nio4r (2.5.2) nio4r (2.5.2-java) - nokogiri (1.10.7) + nokogiri (1.10.10) mini_portile2 (~> 2.4.0) - nokogiri (1.10.7-java) - nokogiri (1.10.7-x64-mingw32) + nokogiri (1.10.10-java) + nokogiri (1.10.10-x64-mingw32) mini_portile2 (~> 2.4.0) - nokogiri (1.10.7-x86-mingw32) + nokogiri (1.10.10-x86-mingw32) mini_portile2 (~> 2.4.0) - os (1.0.1) - parallel (1.19.1) - parser (2.6.5.0) - ast (~> 2.4.0) + os (1.1.1) + parallel (1.19.2) + parser (2.7.1.4) + ast (~> 2.4.1) path_expander (1.1.0) pg (1.2.0) pg (1.2.0-x64-mingw32) pg (1.2.0-x86-mingw32) psych (3.1.0) - public_suffix (4.0.2) + public_suffix (4.0.6) puma (4.3.1) nio4r (~> 2.0) puma (4.3.1-java) @@ -461,9 +462,9 @@ GEM rack-protection (>= 2.0.0) redis (>= 4.1.0) sigdump (0.2.4) - signet (0.12.0) + signet (0.14.0) addressable (~> 2.3) - faraday (~> 0.9) + faraday (>= 0.17.3, < 2.0) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) sinatra (2.0.7) @@ -511,9 +512,10 @@ GEM useragent (0.16.10) vegas (0.1.11) rack (>= 1.0.0) - w3c_validators (1.3.4) + w3c_validators (1.3.6) json (>= 1.8) nokogiri (~> 1.6) + rexml (~> 3.2) wdm (0.1.1) webdrivers (4.1.3) nokogiri (~> 1.6) @@ -608,7 +610,7 @@ DEPENDENCIES turbolinks (~> 5) tzinfo-data uglifier (>= 1.3.0) - w3c_validators + w3c_validators (~> 1.3.6) wdm (>= 0.1.0) webdrivers webmock From 47ddcd4a2fa722d4621778f99c216bea4c121863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 29 Dec 2020 01:11:25 +0000 Subject: [PATCH 130/244] Support selenium-webdriver 4 * Use public API to add argument to the selenium driver. While `args` is also public API it doesn't know how to handle if no argument is being set yet in Selenium 4. * Fix assertions to match return on Selenium 4 --- Gemfile | 2 +- Gemfile.lock | 11 ++++++----- .../lib/action_dispatch/system_testing/browser.rb | 6 +++--- .../test/dispatch/system_testing/driver_test.rb | 12 ++++++++---- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index 125619b68d575..1d356003355b3 100644 --- a/Gemfile +++ b/Gemfile @@ -10,7 +10,7 @@ gemspec gem "rake", ">= 11.1" gem "capybara", ">= 2.15" -gem "selenium-webdriver", ">= 3.141.592" +gem "selenium-webdriver", ">= 4.0.0.alpha7" gem "rack-cache", "~> 1.2" gem "sass-rails" diff --git a/Gemfile.lock b/Gemfile.lock index 59c319f496df0..0c76776adfc89 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -197,7 +197,7 @@ GEM rack-test (>= 0.6.3) regexp_parser (~> 1.5) xpath (~> 3.2) - childprocess (3.0.0) + childprocess (4.0.0) coffee-script (2.4.1) coffee-script-source execjs @@ -450,9 +450,10 @@ GEM tilt sdoc (1.1.0) rdoc (>= 5.0) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) + selenium-webdriver (4.0.0.alpha7) + childprocess (>= 0.5, < 5.0) rubyzip (>= 1.2.2) + websocket (~> 1.0) sequel (5.27.0) serverengine (2.0.7) sigdump (~> 0.2.2) @@ -599,7 +600,7 @@ DEPENDENCIES rubocop-rails sass-rails sdoc (~> 1.1) - selenium-webdriver (>= 3.141.592) + selenium-webdriver (>= 4.0.0.alpha7) sequel sidekiq sneakers @@ -618,4 +619,4 @@ DEPENDENCIES websocket-client-simple! BUNDLED WITH - 2.1.4 + 2.2.3 diff --git a/actionpack/lib/action_dispatch/system_testing/browser.rb b/actionpack/lib/action_dispatch/system_testing/browser.rb index e861e52f0943c..ab416b4600750 100644 --- a/actionpack/lib/action_dispatch/system_testing/browser.rb +++ b/actionpack/lib/action_dispatch/system_testing/browser.rb @@ -64,14 +64,14 @@ def preload private def headless_chrome_browser_options - capabilities.args << "--headless" - capabilities.args << "--disable-gpu" if Gem.win_platform? + capabilities.add_argument("--headless") + capabilities.add_argument("--disable-gpu") if Gem.win_platform? capabilities end def headless_firefox_browser_options - capabilities.args << "-headless" + capabilities.add_argument("-headless") capabilities end diff --git a/actionpack/test/dispatch/system_testing/driver_test.rb b/actionpack/test/dispatch/system_testing/driver_test.rb index 7877215110ae6..affe091d8f3ad 100644 --- a/actionpack/test/dispatch/system_testing/driver_test.rb +++ b/actionpack/test/dispatch/system_testing/driver_test.rb @@ -71,7 +71,8 @@ class DriverTest < ActiveSupport::TestCase "args" => ["start-maximized"], "mobileEmulation" => { "deviceName" => "iphone 6" }, "prefs" => { "detach" => true } - } + }, + "browserName" => "chrome" } assert_equal expected, driver_option.as_json end @@ -92,7 +93,8 @@ class DriverTest < ActiveSupport::TestCase "args" => ["start-maximized"], "mobileEmulation" => { "deviceName" => "iphone 6" }, "prefs" => { "detach" => true } - } + }, + "browserName" => "chrome" } assert_equal expected, driver_option.as_json end @@ -111,7 +113,8 @@ class DriverTest < ActiveSupport::TestCase "moz:firefoxOptions" => { "args" => ["--host=127.0.0.1"], "prefs" => { "browser.startup.homepage" => "http://www.seleniumhq.com/" } - } + }, + "browserName" => "firefox" } assert_equal expected, driver_option.as_json end @@ -130,7 +133,8 @@ class DriverTest < ActiveSupport::TestCase "moz:firefoxOptions" => { "args" => ["--host=127.0.0.1"], "prefs" => { "browser.startup.homepage" => "http://www.seleniumhq.com/" } - } + }, + "browserName" => "firefox" } assert_equal expected, driver_option.as_json end From 91d852fe2c6a6bf51287a1ad95ef6e21ffa9d261 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Fri, 1 Jan 2021 16:05:37 +0000 Subject: [PATCH 131/244] Fix rounding NaN and Infinity on newer BigDecimal Since BigDecimal 2.0.3, BigDecimal#round returns an integer if the requested precision is less than 1: https://github.com/ruby/bigdecimal/commit/e8fc98050167fd943574609988b8754414e0a7c1 NaN and Infinity cannot be represented as an integer, so rounding these values now raises a FloatDomainError. This is a regression of the fix in 081a3963ea2aab617a92874d7ef59ce98eee6a64. Specifying the rounding mode restores the previous behaviour. This isn't a problem on master or 6-1-stable, as the rounding mode is always specified there since 7905bdfd8b2ae50319cd7a9a74ee1f8c865d648d. --- .../lib/active_support/number_helper/rounding_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/number_helper/rounding_helper.rb b/activesupport/lib/active_support/number_helper/rounding_helper.rb index 2ad8d49c4edb0..7f7242f8651a0 100644 --- a/activesupport/lib/active_support/number_helper/rounding_helper.rb +++ b/activesupport/lib/active_support/number_helper/rounding_helper.rb @@ -26,7 +26,7 @@ def digit_count(number) private def round_without_significant(number) - number = number.round(precision) + number = number.round(precision, BigDecimal.mode(BigDecimal::ROUND_MODE)) number = number.to_i if precision == 0 && number.finite? number = number.abs if number.zero? # prevent showing negative zeros number From b547765fbc4bcd4618999067828d040462c9cd73 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sun, 13 Dec 2020 17:52:37 +0900 Subject: [PATCH 132/244] Merge pull request #40825 from yahonda/ruby3_webrick_bundled_gem Ruby 3 does not have webrick by default --- Gemfile | 3 ++- Gemfile.lock | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 1d356003355b3..d5ae76288b8f6 100644 --- a/Gemfile +++ b/Gemfile @@ -46,8 +46,9 @@ gem "libxml-ruby", platforms: :ruby gem "connection_pool", require: false gem "rexml", require: false -# for railties app_generator_test +# for railties gem "bootsnap", ">= 1.4.2", require: false +gem "webrick", require: false # Active Job group :job do diff --git a/Gemfile.lock b/Gemfile.lock index 0c76776adfc89..32093487f29f2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -530,6 +530,7 @@ GEM activesupport (>= 4.2) rack-proxy (>= 0.6.1) railties (>= 4.2) + webrick (1.7.0) websocket (1.2.8) websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) @@ -616,6 +617,7 @@ DEPENDENCIES webdrivers webmock webpacker (~> 4.0) + webrick websocket-client-simple! BUNDLED WITH From f64f7c649d7d6c05bd1a0309f6dd3936ff2c4644 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 19 Jun 2020 12:34:22 +0900 Subject: [PATCH 133/244] Merge pull request #39666 from kamipo/use_native_hash_except Use native `Hash#except` if it is defined --- activesupport/lib/active_support/core_ext/hash/except.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/core_ext/hash/except.rb b/activesupport/lib/active_support/core_ext/hash/except.rb index 5013812460930..ec96929b0ae6b 100644 --- a/activesupport/lib/active_support/core_ext/hash/except.rb +++ b/activesupport/lib/active_support/core_ext/hash/except.rb @@ -11,7 +11,7 @@ class Hash # @person.update(params[:person].except(:admin)) def except(*keys) slice(*self.keys - keys) - end + end unless method_defined?(:except) # Removes the given keys from hash and returns it. # hash = { a: true, b: false, c: nil } From fe9808585c1f0600b22535f6c306631aad210d84 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 6 Jan 2021 18:20:05 +0900 Subject: [PATCH 134/244] Merge pull request #41027 from flavorjones/flavorjones-fix-nokogiri-xml-mini-test Remove leading whitespace from the XML under test --- activesupport/test/xml_mini/xml_mini_engine_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/test/xml_mini/xml_mini_engine_test.rb b/activesupport/test/xml_mini/xml_mini_engine_test.rb index 967e072411d7d..219443d4a18a2 100644 --- a/activesupport/test/xml_mini/xml_mini_engine_test.rb +++ b/activesupport/test/xml_mini/xml_mini_engine_test.rb @@ -50,7 +50,7 @@ def test_file_from_xml def test_exception_thrown_on_expansion_attack assert_raise expansion_attack_error do - Hash.from_xml(<<-eoxml) + Hash.from_xml(<<~eoxml) From 11928670bdcca61ae128da306d39291d0556e942 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 13 Jan 2021 14:56:52 +0900 Subject: [PATCH 135/244] Fix `build` multiple records on association relation not to raise deprecation warning It should restore the original `current_scope` if building multiple records in a `scoping` since `_deprecated_scope_block` overrides `current_scope` to raise the deprecation warning. Fixes #41076. --- .../active_record/associations/collection_association.rb | 7 +++++++ .../test/cases/associations/has_many_associations_test.rb | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index e67eb7036e055..3c8a7da774ea3 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -332,6 +332,13 @@ def merge_target_lists(persisted, memory) persisted + memory end + def build_record(attributes) + previous = klass.current_scope(true) if block_given? + super + ensure + klass.current_scope = previous if previous + end + def _create_record(attributes, raise = false, &block) unless owner.persisted? raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved" diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index dddab9a499585..0a63a6ddd814c 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -377,7 +377,7 @@ def test_building_the_associated_object_with_an_unrelated_type test "building the association with an array" do speedometer = Speedometer.new(speedometer_id: "a") data = [{ name: "first" }, { name: "second" }] - speedometer.minivans.build(data) + speedometer.minivans.all.build(data) assert_equal 2, speedometer.minivans.size assert speedometer.save From d0c915ec075b96421a90fe0bd326421819c81f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 19 Jan 2021 20:43:24 +0000 Subject: [PATCH 136/244] Rename master to main in all code references --- .github/stale.yml | 2 +- CONTRIBUTING.md | 6 +-- README.md | 2 +- RELEASING_RAILS.md | 2 +- actionmailer/README.rdoc | 2 +- actionpack/README.rdoc | 2 +- actionview/README.rdoc | 2 +- .../assets/javascripts/rails-ujs/BANNER.js | 2 +- actionview/package.json | 2 +- activejob/README.md | 2 +- activemodel/README.rdoc | 2 +- activerecord/README.rdoc | 2 +- activestorage/README.md | 2 +- activesupport/README.rdoc | 2 +- ...er_master.rb => action_controller_main.rb} | 2 +- ...ctive_job_master.rb => active_job_main.rb} | 2 +- ...record_master.rb => active_record_main.rb} | 2 +- ...er.rb => active_record_migrations_main.rb} | 2 +- .../{generic_master.rb => generic_main.rb} | 2 +- guides/source/4_0_release_notes.md | 4 +- guides/source/_welcome.html.erb | 2 +- guides/source/action_mailer_basics.md | 2 +- guides/source/active_storage_overview.md | 2 +- .../source/contributing_to_ruby_on_rails.md | 50 +++++++++---------- guides/source/i18n.md | 14 +++--- guides/source/kindle/rails_guides.opf.erb | 2 +- guides/source/layout.html.erb | 4 +- guides/source/maintenance_policy.md | 2 +- guides/source/security.md | 2 +- .../working_with_javascript_in_rails.md | 4 +- railties/README.rdoc | 2 +- railties/lib/rails/api/task.rb | 2 +- railties/lib/rails/generators/app_base.rb | 2 +- 33 files changed, 68 insertions(+), 68 deletions(-) rename guides/bug_report_templates/{action_controller_master.rb => action_controller_main.rb} (93%) rename guides/bug_report_templates/{active_job_master.rb => active_job_main.rb} (88%) rename guides/bug_report_templates/{active_record_master.rb => active_record_main.rb} (94%) rename guides/bug_report_templates/{active_record_migrations_master.rb => active_record_migrations_main.rb} (95%) rename guides/bug_report_templates/{generic_master.rb => generic_main.rb} (86%) diff --git a/.github/stale.yml b/.github/stale.yml index 21d9d792b025d..cf2bd96c759cf 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -18,7 +18,7 @@ markComment: > The resources of the Rails team are limited, and so we are asking for your help. - If you can still reproduce this error on the `5-2-stable` branch or on `master`, + If you can still reproduce this error on the `5-2-stable` branch or on `main`, please reply with all of the information you have about it in order to keep the issue open. Thank you for all your contributions. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7e34cecb2e902..216c329e3215e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,9 +10,9 @@ * If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/rails/rails/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring. * If possible, use the relevant bug report templates to create the issue. Simply copy the content of the appropriate template into a .rb file, make the necessary changes to demonstrate the issue, and **paste the content into the issue description**: - * [**Active Record** (models, database) issues](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_master.rb) - * [**Action Pack** (controllers, routing) issues](https://github.com/rails/rails/blob/master/guides/bug_report_templates/action_controller_master.rb) - * [**Generic template** for other issues](https://github.com/rails/rails/blob/master/guides/bug_report_templates/generic_master.rb) + * [**Active Record** (models, database) issues](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_main.rb) + * [**Action Pack** (controllers, routing) issues](https://github.com/rails/rails/blob/main/guides/bug_report_templates/action_controller_main.rb) + * [**Generic template** for other issues](https://github.com/rails/rails/blob/main/guides/bug_report_templates/generic_main.rb) * For more detailed information on submitting a bug report and creating an issue, visit our [reporting guidelines](https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#reporting-an-issue). diff --git a/README.md b/README.md index c18a0d782617a..b51feb181c527 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ Everyone interacting in Rails and its sub-projects' codebases, issue trackers, c ## Code Status -[![Build Status](https://badge.buildkite.com/ab1152b6a1f6a61d3ea4ec5b3eece8d4c2b830998459c75352.svg?branch=master)](https://buildkite.com/rails/rails) +[![Build Status](https://badge.buildkite.com/ab1152b6a1f6a61d3ea4ec5b3eece8d4c2b830998459c75352.svg?branch=main)](https://buildkite.com/rails/rails) ## License diff --git a/RELEASING_RAILS.md b/RELEASING_RAILS.md index cd850e6ddf104..e4026c7d32ea7 100644 --- a/RELEASING_RAILS.md +++ b/RELEASING_RAILS.md @@ -93,7 +93,7 @@ You can review the commits for the 3.0.10 release like this: ``` If you're doing a stable branch release, you should also ensure that all of -the CHANGELOG entries in the stable branch are also synced to the master +the CHANGELOG entries in the stable branch are also synced to the main branch. ### Put the new version in the RAILS_VERSION file. diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc index f9c84b4232c8f..d55459de86fc3 100644 --- a/actionmailer/README.rdoc +++ b/actionmailer/README.rdoc @@ -116,7 +116,7 @@ The latest version of Action Mailer can be installed with RubyGems: Source code can be downloaded as part of the Rails project on GitHub: -* https://github.com/rails/rails/tree/master/actionmailer +* https://github.com/rails/rails/tree/main/actionmailer == License diff --git a/actionpack/README.rdoc b/actionpack/README.rdoc index 67d0c62a84815..30b52efb37c52 100644 --- a/actionpack/README.rdoc +++ b/actionpack/README.rdoc @@ -33,7 +33,7 @@ The latest version of Action Pack can be installed with RubyGems: Source code can be downloaded as part of the Rails project on GitHub: -* https://github.com/rails/rails/tree/master/actionpack +* https://github.com/rails/rails/tree/main/actionpack == License diff --git a/actionview/README.rdoc b/actionview/README.rdoc index 388aa4ff7b113..fcc43c4eeeb29 100644 --- a/actionview/README.rdoc +++ b/actionview/README.rdoc @@ -15,7 +15,7 @@ The latest version of Action View can be installed with RubyGems: Source code can be downloaded as part of the Rails project on GitHub: -* https://github.com/rails/rails/tree/master/actionview +* https://github.com/rails/rails/tree/main/actionview == License diff --git a/actionview/app/assets/javascripts/rails-ujs/BANNER.js b/actionview/app/assets/javascripts/rails-ujs/BANNER.js index 47ecd66003a1b..6a48891886d73 100644 --- a/actionview/app/assets/javascripts/rails-ujs/BANNER.js +++ b/actionview/app/assets/javascripts/rails-ujs/BANNER.js @@ -1,5 +1,5 @@ /* Unobtrusive JavaScript -https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts +https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts Released under the MIT license */ diff --git a/actionview/package.json b/actionview/package.json index 4ad4a7b36f198..69af1aff0a9fd 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -11,7 +11,7 @@ }, "scripts": { "build": "bundle exec blade build", - "test": "echo \"See the README: https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts#how-to-run-tests\" && exit 1", + "test": "echo \"See the README: https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts#how-to-run-tests\" && exit 1", "lint": "coffeelint app/assets/javascripts && eslint test/ujs/public/test" }, "repository": { diff --git a/activejob/README.md b/activejob/README.md index 35536980e5fd0..0ecacf5d2c097 100644 --- a/activejob/README.md +++ b/activejob/README.md @@ -109,7 +109,7 @@ The latest version of Active Job can be installed with RubyGems: Source code can be downloaded as part of the Rails project on GitHub: -* https://github.com/rails/rails/tree/master/activejob +* https://github.com/rails/rails/tree/main/activejob ## License diff --git a/activemodel/README.rdoc b/activemodel/README.rdoc index bf910846c41d5..cd2f6c068e42a 100644 --- a/activemodel/README.rdoc +++ b/activemodel/README.rdoc @@ -241,7 +241,7 @@ The latest version of Active Model can be installed with RubyGems: Source code can be downloaded as part of the Rails project on GitHub -* https://github.com/rails/rails/tree/master/activemodel +* https://github.com/rails/rails/tree/main/activemodel == License diff --git a/activerecord/README.rdoc b/activerecord/README.rdoc index f02ff204000e6..cf96a260c852a 100644 --- a/activerecord/README.rdoc +++ b/activerecord/README.rdoc @@ -194,7 +194,7 @@ The latest version of Active Record can be installed with RubyGems: Source code can be downloaded as part of the Rails project on GitHub: -* https://github.com/rails/rails/tree/master/activerecord +* https://github.com/rails/rails/tree/main/activerecord == License diff --git a/activestorage/README.md b/activestorage/README.md index 01f41adf4bd68..4eba3343fb926 100644 --- a/activestorage/README.md +++ b/activestorage/README.md @@ -10,7 +10,7 @@ You can read more about Active Storage in the [Active Storage Overview](https:// ## Compared to other storage solutions -A key difference to how Active Storage works compared to other attachment solutions in Rails is through the use of built-in [Blob](https://github.com/rails/rails/blob/master/activestorage/app/models/active_storage/blob.rb) and [Attachment](https://github.com/rails/rails/blob/master/activestorage/app/models/active_storage/attachment.rb) models (backed by Active Record). This means existing application models do not need to be modified with additional columns to associate with files. Active Storage uses polymorphic associations via the `Attachment` join model, which then connects to the actual `Blob`. +A key difference to how Active Storage works compared to other attachment solutions in Rails is through the use of built-in [Blob](https://github.com/rails/rails/blob/main/activestorage/app/models/active_storage/blob.rb) and [Attachment](https://github.com/rails/rails/blob/main/activestorage/app/models/active_storage/attachment.rb) models (backed by Active Record). This means existing application models do not need to be modified with additional columns to associate with files. Active Storage uses polymorphic associations via the `Attachment` join model, which then connects to the actual `Blob`. `Blob` models store attachment metadata (filename, content-type, etc.), and their identifier key in the storage service. Blob models do not store the actual binary data. They are intended to be immutable in spirit. One file, one blob. You can associate the same blob with multiple application models as well. And if you want to do transformations of a given `Blob`, the idea is that you'll simply create a new one, rather than attempt to mutate the existing one (though of course you can delete the previous version later if you don't need it). diff --git a/activesupport/README.rdoc b/activesupport/README.rdoc index c56e63fa85ced..c2df6d73b2751 100644 --- a/activesupport/README.rdoc +++ b/activesupport/README.rdoc @@ -15,7 +15,7 @@ The latest version of Active Support can be installed with RubyGems: Source code can be downloaded as part of the Rails project on GitHub: -* https://github.com/rails/rails/tree/master/activesupport +* https://github.com/rails/rails/tree/main/activesupport == License diff --git a/guides/bug_report_templates/action_controller_master.rb b/guides/bug_report_templates/action_controller_main.rb similarity index 93% rename from guides/bug_report_templates/action_controller_master.rb rename to guides/bug_report_templates/action_controller_main.rb index eef98e36fd0b1..ba3c5c80896b2 100644 --- a/guides/bug_report_templates/action_controller_master.rb +++ b/guides/bug_report_templates/action_controller_main.rb @@ -7,7 +7,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } - gem "rails", github: "rails/rails", branch: "6-0-stable" + gem "rails", github: "rails/rails", branch: "main" end require "action_controller/railtie" diff --git a/guides/bug_report_templates/active_job_master.rb b/guides/bug_report_templates/active_job_main.rb similarity index 88% rename from guides/bug_report_templates/active_job_master.rb rename to guides/bug_report_templates/active_job_main.rb index c2d7d08c47680..335a78f392e5a 100644 --- a/guides/bug_report_templates/active_job_master.rb +++ b/guides/bug_report_templates/active_job_main.rb @@ -7,7 +7,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } - gem "rails", github: "rails/rails", branch: "6-0-stable" + gem "rails", github: "rails/rails", branch: "main" end require "active_job" diff --git a/guides/bug_report_templates/active_record_master.rb b/guides/bug_report_templates/active_record_main.rb similarity index 94% rename from guides/bug_report_templates/active_record_master.rb rename to guides/bug_report_templates/active_record_main.rb index ea05f9727b371..f8acbabfa3b2f 100644 --- a/guides/bug_report_templates/active_record_master.rb +++ b/guides/bug_report_templates/active_record_main.rb @@ -7,7 +7,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } - gem "rails", github: "rails/rails", branch: "6-0-stable" + gem "rails", github: "rails/rails", branch: "main" gem "sqlite3" end diff --git a/guides/bug_report_templates/active_record_migrations_master.rb b/guides/bug_report_templates/active_record_migrations_main.rb similarity index 95% rename from guides/bug_report_templates/active_record_migrations_master.rb rename to guides/bug_report_templates/active_record_migrations_main.rb index 539bd659c9131..61e9c75345520 100644 --- a/guides/bug_report_templates/active_record_migrations_master.rb +++ b/guides/bug_report_templates/active_record_migrations_main.rb @@ -7,7 +7,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } - gem "rails", github: "rails/rails", branch: "6-0-stable" + gem "rails", github: "rails/rails", branch: "main" gem "sqlite3" end diff --git a/guides/bug_report_templates/generic_master.rb b/guides/bug_report_templates/generic_main.rb similarity index 86% rename from guides/bug_report_templates/generic_master.rb rename to guides/bug_report_templates/generic_main.rb index 6fd6664939cad..576b95e108f1b 100644 --- a/guides/bug_report_templates/generic_master.rb +++ b/guides/bug_report_templates/generic_main.rb @@ -7,7 +7,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } - gem "rails", github: "rails/rails", branch: "6-0-stable" + gem "rails", github: "rails/rails", branch: "main" end require "active_support" diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md index e4b1b04681628..7ac09d07f8ded 100644 --- a/guides/source/4_0_release_notes.md +++ b/guides/source/4_0_release_notes.md @@ -234,11 +234,11 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/4-0-stable/a The method `change_table` is also reversible, as long as its block doesn't call `remove`, `change` or `change_default` * New method `reversible` makes it possible to specify code to be run when migrating up or down. - See the [Guide on Migration](https://github.com/rails/rails/blob/master/guides/source/active_record_migrations.md#using-reversible) + See the [Guide on Migration](https://github.com/rails/rails/blob/main/guides/source/active_record_migrations.md#using-reversible) * New method `revert` will revert a whole migration or the given block. If migrating down, the given migration / block is run normally. - See the [Guide on Migration](https://github.com/rails/rails/blob/master/guides/source/active_record_migrations.md#reverting-previous-migrations) + See the [Guide on Migration](https://github.com/rails/rails/blob/main/guides/source/active_record_migrations.md#reverting-previous-migrations) * Adds PostgreSQL array type support. Any datatype can be used to create an array column, with full migration and schema dumper support. diff --git a/guides/source/_welcome.html.erb b/guides/source/_welcome.html.erb index b5dd135295527..18dd5da2b503d 100644 --- a/guides/source/_welcome.html.erb +++ b/guides/source/_welcome.html.erb @@ -2,7 +2,7 @@ <% if @edge %>

    - These are Edge Guides, based on master@<%= @edge[0, 7] %>. + These are Edge Guides, based on main@<%= @edge[0, 7] %>.

    If you are looking for the ones for the stable version, please check diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md index 9f4a567f96f88..8aaffb5d11a4a 100644 --- a/guides/source/action_mailer_basics.md +++ b/guides/source/action_mailer_basics.md @@ -579,7 +579,7 @@ URL helper. <%= user_url(@user, host: 'example.com') %> ``` -NOTE: non-`GET` links require [rails-ujs](https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts) or +NOTE: non-`GET` links require [rails-ujs](https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts) or [jQuery UJS](https://github.com/rails/jquery-ujs), and won't work in mailer templates. They will result in normal `GET` requests. diff --git a/guides/source/active_storage_overview.md b/guides/source/active_storage_overview.md index d7755615c3322..6755f3d9c11b7 100644 --- a/guides/source/active_storage_overview.md +++ b/guides/source/active_storage_overview.md @@ -853,5 +853,5 @@ Implementing Support for Other Cloud Services If you need to support a cloud service other than these, you will need to implement the Service. Each service extends -[`ActiveStorage::Service`](https://github.com/rails/rails/blob/master/activestorage/lib/active_storage/service.rb) +[`ActiveStorage::Service`](https://github.com/rails/rails/blob/main/activestorage/lib/active_storage/service.rb) by implementing the methods necessary to upload and download files to the cloud. diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md index eeb301e684408..957eb524ee581 100644 --- a/guides/source/contributing_to_ruby_on_rails.md +++ b/guides/source/contributing_to_ruby_on_rails.md @@ -39,13 +39,13 @@ Then, don't get your hopes up! Unless you have a "Code Red, Mission Critical, th Having a way to reproduce your issue will be very helpful for others to help confirm, investigate, and ultimately fix your issue. You can do this by providing an executable test case. To make this process easier, we have prepared several bug report templates for you to use as a starting point: -* Template for Active Record (models, database) issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_master.rb) -* Template for testing Active Record (migration) issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_migrations_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_migrations_master.rb) -* Template for Action Pack (controllers, routing) issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/action_controller_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/action_controller_master.rb) -* Template for Active Job issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_job_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_job_master.rb) -* Generic template for other issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/generic_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/generic_master.rb) +* Template for Active Record (models, database) issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_main.rb) +* Template for testing Active Record (migration) issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_migrations_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_migrations_main.rb) +* Template for Action Pack (controllers, routing) issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/action_controller_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/action_controller_main.rb) +* Template for Active Job issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_job_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_job_main.rb) +* Generic template for other issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/generic_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/generic_main.rb) -These templates include the boilerplate code to set up a test case against either a released version of Rails (`*_gem.rb`) or edge Rails (`*_master.rb`). +These templates include the boilerplate code to set up a test case against either a released version of Rails (`*_gem.rb`) or edge Rails (`*_main.rb`). Simply copy the content of the appropriate template into a `.rb` file and make the necessary changes to demonstrate the issue. You can execute it by running `ruby the_file.rb` in your terminal. If all goes well, you should see your test case failing. @@ -134,8 +134,8 @@ learn about Ruby on Rails, and the API, which serves as a reference. You can help improve the Rails guides by making them more coherent, consistent, or readable, adding missing information, correcting factual errors, fixing typos, or bringing them up to date with the latest edge Rails. -To do so, make changes to Rails guides source files (located [here](https://github.com/rails/rails/tree/master/guides/source) on GitHub). Then open a pull request to apply your -changes to the master branch. +To do so, make changes to Rails guides source files (located [here](https://github.com/rails/rails/tree/main/guides/source) on GitHub). Then open a pull request to apply your +changes to the main branch. When working with documentation, please take into account the [API Documentation Guidelines](api_documentation_guidelines.html) and the [Ruby on Rails Guides Guidelines](ruby_on_rails_guides_guidelines.html). @@ -286,7 +286,7 @@ Therefore, you should test your change against a list of representative scenarios. Ideally, they should be based on real-world scenarios extracted from production applications. -You can use the [benchmark template](https://github.com/rails/rails/blob/master/guides/bug_report_templates/benchmark.rb) +You can use the [benchmark template](https://github.com/rails/rails/blob/main/guides/bug_report_templates/benchmark.rb) as a starting point. It includes the boilerplate code to setup a benchmark using the [benchmark-ips](https://github.com/evanphx/benchmark-ips) gem. The template is designed for testing relatively self-contained changes that can be @@ -504,10 +504,10 @@ simplifies future cherry picks and keeps the git log clean. ### Update Your Branch -It's pretty likely that other changes to master have happened while you were working. Go get them: +It's pretty likely that other changes to main have happened while you were working. Go get them: ```bash -$ git checkout master +$ git checkout main $ git pull --rebase ``` @@ -515,7 +515,7 @@ Now reapply your patch on top of the latest changes: ```bash $ git checkout my_new_branch -$ git rebase master +$ git rebase main ``` No conflicts? Tests still pass? Change still seems reasonable to you? Then move on. @@ -545,16 +545,16 @@ $ git fetch rails Merge the new content: ```bash -$ git checkout master -$ git rebase rails/master +$ git checkout main +$ git rebase rails/main $ git checkout my_new_branch -$ git rebase rails/master +$ git rebase rails/main ``` Update your fork: ```bash -$ git push fork master +$ git push fork main $ git push fork my_new_branch ``` @@ -566,7 +566,7 @@ the right panel. On the next page, press "New pull request" in the upper right hand corner. Click on "Edit", if you need to change the branches being compared (it compares -"master" by default) and press "Click to create a pull request for this +"main" by default) and press "Click to create a pull request for this comparison". Ensure the changesets you introduced are included. Fill in some details about @@ -610,7 +610,7 @@ extraneous commits can add a lot of noise. ```bash $ git fetch rails $ git checkout my_new_branch -$ git rebase -i rails/master +$ git rebase -i rails/main < Choose 'squash' for all of your commits except the first one. > < Edit the commit message to make sense, and describe all your changes. > @@ -652,20 +652,20 @@ TIP: You may want to [put your Git branch name in your shell prompt](http://qugs #### Backporting -Changes that are merged into master are intended for the next major release of Rails. Sometimes, it might be beneficial for your changes to propagate back to the maintenance releases for older stable branches. Generally, security fixes and bug fixes are good candidates for a backport, while new features and patches that introduce a change in behavior will not be accepted. When in doubt, it is best to consult a Rails team member before backporting your changes to avoid wasted effort. +Changes that are merged into main are intended for the next major release of Rails. Sometimes, it might be beneficial for your changes to propagate back to the maintenance releases for older stable branches. Generally, security fixes and bug fixes are good candidates for a backport, while new features and patches that introduce a change in behavior will not be accepted. When in doubt, it is best to consult a Rails team member before backporting your changes to avoid wasted effort. -For simple fixes, the easiest way to backport your changes is to [extract a diff from your changes in master and apply them to the target branch](http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git). +For simple fixes, the easiest way to backport your changes is to [extract a diff from your changes in main and apply them to the target branch](http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git). -First, make sure your changes are the only difference between your current branch and master: +First, make sure your changes are the only difference between your current branch and main: ```bash -$ git log master..HEAD +$ git log main..HEAD ``` Then extract the diff: ```bash -$ git format-patch master --stdout > ~/my_changes.patch +$ git format-patch main --stdout > ~/my_changes.patch ``` Switch over to the target branch and apply your changes: @@ -675,9 +675,9 @@ $ git checkout -b my_backport_branch 4-2-stable $ git apply ~/my_changes.patch ``` -This works well for simple changes. However, if your changes are complicated or if the code in master has deviated significantly from your target branch, it might require more work on your part. The difficulty of a backport varies greatly from case to case, and sometimes it is simply not worth the effort. +This works well for simple changes. However, if your changes are complicated or if the code in main has deviated significantly from your target branch, it might require more work on your part. The difficulty of a backport varies greatly from case to case, and sometimes it is simply not worth the effort. -Once you have resolved all conflicts and made sure all the tests are passing, push your changes and open a separate pull request for your backport. It is also worth noting that older branches might have a different set of build targets than master. When possible, it is best to first test your backport locally against the oldest Ruby version permitted by the target branch's `rails.gemspec` before submitting your pull request. +Once you have resolved all conflicts and made sure all the tests are passing, push your changes and open a separate pull request for your backport. It is also worth noting that older branches might have a different set of build targets than main. When possible, it is best to first test your backport locally against the oldest Ruby version permitted by the target branch's `rails.gemspec` before submitting your pull request. And then... think about your next contribution! diff --git a/guides/source/i18n.md b/guides/source/i18n.md index 0518da9fc26e0..6dc19bc299822 100644 --- a/guides/source/i18n.md +++ b/guides/source/i18n.md @@ -103,7 +103,7 @@ en: hello: "Hello world" ``` -This means, that in the `:en` locale, the key _hello_ will map to the _Hello world_ string. Every string inside Rails is internationalized in this way, see for instance Active Model validation messages in the [`activemodel/lib/active_model/locale/en.yml`](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/locale/en.yml) file or time and date formats in the [`activesupport/lib/active_support/locale/en.yml`](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml) file. You can use YAML or standard Ruby Hashes to store translations in the default (Simple) backend. +This means, that in the `:en` locale, the key _hello_ will map to the _Hello world_ string. Every string inside Rails is internationalized in this way, see for instance Active Model validation messages in the [`activemodel/lib/active_model/locale/en.yml`](https://github.com/rails/rails/blob/main/activemodel/lib/active_model/locale/en.yml) file or time and date formats in the [`activesupport/lib/active_support/locale/en.yml`](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml) file. You can use YAML or standard Ruby Hashes to store translations in the default (Simple) backend. The I18n library will use **English** as a **default locale**, i.e. if a different locale is not set, `:en` will be used for looking up translations. @@ -1059,23 +1059,23 @@ Rails uses fixed strings and other localizations, such as format strings and oth #### Action View Helper Methods -* `distance_of_time_in_words` translates and pluralizes its result and interpolates the number of seconds, minutes, hours, and so on. See [datetime.distance_in_words](https://github.com/rails/rails/blob/master/actionview/lib/action_view/locale/en.yml#L4) translations. +* `distance_of_time_in_words` translates and pluralizes its result and interpolates the number of seconds, minutes, hours, and so on. See [datetime.distance_in_words](https://github.com/rails/rails/blob/main/actionview/lib/action_view/locale/en.yml#L4) translations. -* `datetime_select` and `select_month` use translated month names for populating the resulting select tag. See [date.month_names](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L15) for translations. `datetime_select` also looks up the order option from [date.order](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L18) (unless you pass the option explicitly). All date selection helpers translate the prompt using the translations in the [datetime.prompts](https://github.com/rails/rails/blob/master/actionview/lib/action_view/locale/en.yml#L39) scope if applicable. +* `datetime_select` and `select_month` use translated month names for populating the resulting select tag. See [date.month_names](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml#L15) for translations. `datetime_select` also looks up the order option from [date.order](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml#L18) (unless you pass the option explicitly). All date selection helpers translate the prompt using the translations in the [datetime.prompts](https://github.com/rails/rails/blob/main/actionview/lib/action_view/locale/en.yml#L39) scope if applicable. -* The `number_to_currency`, `number_with_precision`, `number_to_percentage`, `number_with_delimiter`, and `number_to_human_size` helpers use the number format settings located in the [number](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L37) scope. +* The `number_to_currency`, `number_with_precision`, `number_to_percentage`, `number_with_delimiter`, and `number_to_human_size` helpers use the number format settings located in the [number](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml#L37) scope. #### Active Model Methods -* `model_name.human` and `human_attribute_name` use translations for model names and attribute names if available in the [activerecord.models](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L36) scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes". +* `model_name.human` and `human_attribute_name` use translations for model names and attribute names if available in the [activerecord.models](https://github.com/rails/rails/blob/main/activerecord/lib/active_record/locale/en.yml#L36) scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes". * `ActiveModel::Errors#generate_message` (which is used by Active Model validations but may also be used manually) uses `model_name.human` and `human_attribute_name` (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes". -* `ActiveModel::Errors#full_messages` prepends the attribute name to the error message using a separator that will be looked up from [errors.format](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/locale/en.yml#L4) (and which defaults to `"%{attribute} %{message}"`). +* `ActiveModel::Errors#full_messages` prepends the attribute name to the error message using a separator that will be looked up from [errors.format](https://github.com/rails/rails/blob/main/activemodel/lib/active_model/locale/en.yml#L4) (and which defaults to `"%{attribute} %{message}"`). #### Active Support Methods -* `Array#to_sentence` uses format settings as given in the [support.array](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L33) scope. +* `Array#to_sentence` uses format settings as given in the [support.array](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml#L33) scope. How to Store your Custom Translations ------------------------------------- diff --git a/guides/source/kindle/rails_guides.opf.erb b/guides/source/kindle/rails_guides.opf.erb index 1882ec100538b..83d00cfc2eef4 100644 --- a/guides/source/kindle/rails_guides.opf.erb +++ b/guides/source/kindle/rails_guides.opf.erb @@ -5,7 +5,7 @@ - Ruby on Rails Guides (<%= @version || "master@#{@edge[0, 7]}" %>) + Ruby on Rails Guides (<%= @version || "main@#{@edge[0, 7]}" %>) en-us Ruby on Rails diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb index 087be91344b40..477be76ebc039 100644 --- a/guides/source/layout.html.erb +++ b/guides/source/layout.html.erb @@ -105,9 +105,9 @@

    You may also find incomplete content or stuff that is not up to date. - Please do add any missing documentation for master. Make sure to check + Please do add any missing documentation for main. Make sure to check <%= link_to 'Edge Guides', 'https://edgeguides.rubyonrails.org' %> first to verify - if the issues are already fixed or not on the master branch. + if the issues are already fixed or not on the main branch. Check the <%= link_to 'Ruby on Rails Guides Guidelines', 'ruby_on_rails_guides_guidelines.html' %> for style and conventions.

    diff --git a/guides/source/maintenance_policy.md b/guides/source/maintenance_policy.md index bd732deefde44..863afe71239e8 100644 --- a/guides/source/maintenance_policy.md +++ b/guides/source/maintenance_policy.md @@ -31,7 +31,7 @@ reserved for special occasions. New Features ------------ -New features are only added to the master branch and will not be made available +New features are only added to the main branch and will not be made available in point releases. Bug Fixes diff --git a/guides/source/security.md b/guides/source/security.md index 0ad1640588d43..7004014979a4b 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -298,7 +298,7 @@ protect_from_forgery with: :exception This will automatically include a security token in all forms and Ajax requests generated by Rails. If the security token doesn't match what was expected, an exception will be thrown. -NOTE: By default, Rails includes an [unobtrusive scripting adapter](https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts), +NOTE: By default, Rails includes an [unobtrusive scripting adapter](https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts), which adds a header called `X-CSRF-Token` with the security token on every non-GET Ajax call. Without this header, non-GET Ajax requests won't be accepted by Rails. When using another library to make Ajax calls, it is necessary to add the security diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md index b740e933ba3ef..8cddb33ad9933 100644 --- a/guides/source/working_with_javascript_in_rails.md +++ b/guides/source/working_with_javascript_in_rails.md @@ -152,7 +152,7 @@ Because of Unobtrusive JavaScript, the Rails "Ajax helpers" are actually in two parts: the JavaScript half and the Ruby half. Unless you have disabled the Asset Pipeline, -[rails-ujs](https://github.com/rails/rails/tree/master/actionview/app/assets/javascripts) +[rails-ujs](https://github.com/rails/rails/tree/main/actionview/app/assets/javascripts) provides the JavaScript half, and the regular Ruby view helpers add appropriate tags to your DOM. @@ -537,7 +537,7 @@ var token = document.getElementsByName('csrf-token')[0].content ``` You can then submit this token as a X-CSRF-Token in your header for your -Ajax requst. You do not need to add a CSRF for GET requests, only non-GET +Ajax requst. You do not need to add a CSRF for GET requests, only non-GET requests. You can read more about about Cross-Site Request Forgery in [Security](https://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf) diff --git a/railties/README.rdoc b/railties/README.rdoc index 26404743c420a..13270dd4249e8 100644 --- a/railties/README.rdoc +++ b/railties/README.rdoc @@ -17,7 +17,7 @@ The latest version of Railties can be installed with RubyGems: Source code can be downloaded as part of the Rails project on GitHub -* https://github.com/rails/rails/tree/master/railties +* https://github.com/rails/rails/tree/main/railties == License diff --git a/railties/lib/rails/api/task.rb b/railties/lib/rails/api/task.rb index 489820f600327..6f30eda23cd15 100644 --- a/railties/lib/rails/api/task.rb +++ b/railties/lib/rails/api/task.rb @@ -189,7 +189,7 @@ def api_dir class EdgeTask < RepoTask def rails_version - "master@#{`git rev-parse HEAD`[0, 7]}" + "main@#{`git rev-parse HEAD`[0, 7]}" end end diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index dd03baaaa5206..e88ceb79a3877 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -286,7 +286,7 @@ def rails_gemfile_entry else [GemfileEntry.version("rails", rails_version_specifier, - "Bundle edge Rails instead: gem 'rails', github: 'rails/rails'")] + "Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'")] end end From 01c9cd6b568f0b6734fe376feb070a9168bdcf49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Wed, 20 Jan 2021 14:16:52 -0500 Subject: [PATCH 137/244] Merge pull request #41142 from bencgreenberg/main [ci skip] Update Guides to refer to main branch --- guides/source/contributing_to_ruby_on_rails.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md index 957eb524ee581..a43f49afbdd2f 100644 --- a/guides/source/contributing_to_ruby_on_rails.md +++ b/guides/source/contributing_to_ruby_on_rails.md @@ -8,7 +8,7 @@ This guide covers ways in which _you_ can become a part of the ongoing developme After reading this guide, you will know: * How to use GitHub to report issues. -* How to clone master and run the test suite. +* How to clone main and run the test suite. * How to help resolve existing issues. * How to contribute to the Ruby on Rails documentation. * How to contribute to the Ruby on Rails code. @@ -16,7 +16,7 @@ After reading this guide, you will know: Ruby on Rails is not "someone else's framework." Over the years, thousands of people have contributed to Ruby on Rails ranging from a single character to massive architectural changes or significant documentation - all with the goal of making Ruby on Rails better for everyone. Even if you don't feel up to writing code or documentation yet, there are a variety of other ways that you can contribute, from reporting issues to testing patches. As mentioned in [Rails' -README](https://github.com/rails/rails/blob/master/README.md), everyone interacting in Rails and its sub-projects' codebases, issue trackers, chat rooms, and mailing lists is expected to follow the Rails [code of conduct](https://rubyonrails.org/conduct/). +README](https://github.com/rails/rails/blob/main/README.md), everyone interacting in Rails and its sub-projects' codebases, issue trackers, chat rooms, and mailing lists is expected to follow the Rails [code of conduct](https://rubyonrails.org/conduct/). -------------------------------------------------------------------------------- @@ -134,8 +134,7 @@ learn about Ruby on Rails, and the API, which serves as a reference. You can help improve the Rails guides by making them more coherent, consistent, or readable, adding missing information, correcting factual errors, fixing typos, or bringing them up to date with the latest edge Rails. -To do so, make changes to Rails guides source files (located [here](https://github.com/rails/rails/tree/main/guides/source) on GitHub). Then open a pull request to apply your -changes to the main branch. +To do so, make changes to Rails guides source files (located [here](https://github.com/rails/rails/tree/main/guides/source) on GitHub). Then open a pull request to apply your changes to the main branch. When working with documentation, please take into account the [API Documentation Guidelines](api_documentation_guidelines.html) and the [Ruby on Rails Guides Guidelines](ruby_on_rails_guides_guidelines.html). From 2256a39b3425d0973f2f4a8eebed568efc178e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Thu, 21 Jan 2021 16:15:58 -0500 Subject: [PATCH 138/244] Merge pull request #41205 from jonathanhefner/notes-command-resolve-default-annotations Resolve default annotation tags after config loads --- railties/lib/rails/commands/notes/notes_command.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/commands/notes/notes_command.rb b/railties/lib/rails/commands/notes/notes_command.rb index 94cf183855af7..8a1912d400904 100644 --- a/railties/lib/rails/commands/notes/notes_command.rb +++ b/railties/lib/rails/commands/notes/notes_command.rb @@ -5,7 +5,7 @@ module Rails module Command class NotesCommand < Base # :nodoc: - class_option :annotations, aliases: "-a", desc: "Filter by specific annotations, e.g. Foobar TODO", type: :array, default: Rails::SourceAnnotationExtractor::Annotation.tags + class_option :annotations, aliases: "-a", desc: "Filter by specific annotations, e.g. Foobar TODO", type: :array def perform(*) require_application_and_environment! @@ -16,7 +16,7 @@ def perform(*) private def display_annotations - annotations = options[:annotations] + annotations = options[:annotations] || Rails::SourceAnnotationExtractor::Annotation.tags tag = (annotations.length > 1) Rails::SourceAnnotationExtractor.enumerate annotations.join("|"), tag: tag, dirs: directories From f25b1f28ad4a6422ee70e2c76399873240c996d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Thu, 21 Jan 2021 15:13:42 -0500 Subject: [PATCH 139/244] Merge pull request #41203 from jonathanhefner/generator-test-stub-thor-apply Avoid testing Thor internals --- .../test/generators/shared_generator_tests.rb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index c639b185a0bc3..e86f9aab3dc07 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -82,20 +82,17 @@ def test_template_raises_an_error_with_invalid_path end def test_template_is_executed_when_supplied_an_https_path - path = "https://gist.github.com/josevalim/103208/raw/" - template = +%{ say "It works!" } - template.instance_eval "def read; self; end" # Make the string respond to read + url = "https://gist.github.com/josevalim/103208/raw/" + generator([destination_root], template: url, skip_webpack_install: true) - check_open = -> *args do - assert_equal [ path, "Accept" => "application/x-thor-template" ], args - template - end + applied = nil + apply_stub = -> (path, *) { applied = path } - generator([destination_root], template: path, skip_webpack_install: true).stub(:open, check_open, template) do - generator.stub :bundle_command, nil do - quietly { assert_match(/It works!/, capture(:stdout) { generator.invoke_all }) } - end + generator.stub(:apply, apply_stub) do + quietly { generator.invoke_all } end + + assert_equal url, applied end def test_skip_gemfile From 4b6b98432b8b1fad3757dd4441ee8ad3fd626edd Mon Sep 17 00:00:00 2001 From: "Eileen M. Uchitelle" Date: Wed, 3 Feb 2021 16:17:32 -0500 Subject: [PATCH 140/244] Merge pull request #41324 from eileencodes/fix-timestamp-type-for-sqlite3 Fix timestamp type for sqlite3 --- .../abstract/schema_definitions.rb | 4 ++++ .../connection_adapters/sqlite3_adapter.rb | 3 ++- .../cases/migration/change_schema_test.rb | 22 +++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 2ada383ba4b58..4a560e05bddf3 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -63,6 +63,10 @@ def #{option_name}=(value) end CODE end + + def aliased_types(name, fallback) + "timestamp" == name ? :datetime : fallback + end end AddColumnDefinition = Struct.new(:column) # :nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index ca911a1771477..c03d8a35e4e1a 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -283,13 +283,14 @@ def change_column_null(table_name, column_name, null, default = nil) #:nodoc: def change_column(table_name, column_name, type, options = {}) #:nodoc: alter_table(table_name) do |definition| definition[column_name].instance_eval do - self.type = type + self.type = aliased_types(type.to_s, type) self.limit = options[:limit] if options.include?(:limit) self.default = options[:default] if options.include?(:default) self.null = options[:null] if options.include?(:null) self.precision = options[:precision] if options.include?(:precision) self.scale = options[:scale] if options.include?(:scale) self.collation = options[:collation] if options.include?(:collation) + self.options.merge!(options) end end end diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb index e6e6951562861..6f6f5c8c47d10 100644 --- a/activerecord/test/cases/migration/change_schema_test.rb +++ b/activerecord/test/cases/migration/change_schema_test.rb @@ -290,6 +290,28 @@ def test_add_column_with_timestamp_type end end + def test_change_column_with_timestamp_type + connection.create_table :testings do |t| + t.column :foo, :datetime, null: false + end + + connection.change_column :testings, :foo, :timestamp + + column = connection.columns(:testings).find { |c| c.name == "foo" } + + assert_equal :datetime, column.type + + if current_adapter?(:PostgreSQLAdapter) + assert_equal "timestamp without time zone", column.sql_type + elsif current_adapter?(:Mysql2Adapter) + assert_equal "timestamp", column.sql_type + elsif current_adapter?(:OracleAdapter) + assert_equal "TIMESTAMP(6)", column.sql_type + else + assert_equal connection.type_to_sql("datetime"), column.sql_type + end + end + def test_change_column_quotes_column_names connection.create_table :testings do |t| t.column :select, :string From 879d02107b5b3eb7aeaad1cd1f259bb41f17286b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 10 Feb 2021 09:36:15 -0800 Subject: [PATCH 141/244] Fix possible DoS vector in PostgreSQL money type Carefully crafted input can cause a DoS via the regular expressions used for validating the money format in the PostgreSQL adapter. This patch fixes the regexp. Thanks to @dee-see from Hackerone for this patch! [CVE-2021-22880] --- .../connection_adapters/postgresql/oid/money.rb | 4 ++-- activerecord/test/cases/adapters/postgresql/money_test.rb | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb index 357493dfc0d52..3703e9a646dfc 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb @@ -26,9 +26,9 @@ def cast_value(value) value = value.sub(/^\((.+)\)$/, '-\1') # (4) case value - when /^-?\D*[\d,]+\.\d{2}$/ # (1) + when /^-?\D*+[\d,]+\.\d{2}$/ # (1) value.gsub!(/[^-\d.]/, "") - when /^-?\D*[\d.]+,\d{2}$/ # (2) + when /^-?\D*+[\d.]+,\d{2}$/ # (2) value.gsub!(/[^-\d,]/, "").sub!(/,/, ".") end diff --git a/activerecord/test/cases/adapters/postgresql/money_test.rb b/activerecord/test/cases/adapters/postgresql/money_test.rb index ff2ab22a80188..a442ce6d8cbde 100644 --- a/activerecord/test/cases/adapters/postgresql/money_test.rb +++ b/activerecord/test/cases/adapters/postgresql/money_test.rb @@ -62,6 +62,14 @@ def test_money_type_cast assert_equal(-2.25, type.cast(+"(2.25)")) end + def test_money_regex_backtracking + type = PostgresqlMoney.type_for_attribute("wealth") + Timeout.timeout(0.1) do + assert_equal(0.0, type.cast("$" + "," * 100000 + ".11!")) + assert_equal(0.0, type.cast("$" + "." * 100000 + ",11!")) + end + end + def test_schema_dumping output = dump_table_schema("postgresql_moneys") assert_match %r{t\.money\s+"wealth",\s+scale: 2$}, output From e33092740b3cc05f5abee197a5982eac31947e92 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 10 Feb 2021 11:38:17 -0800 Subject: [PATCH 142/244] Prevent open redirect when allowed host starts with a dot [CVE-2021-22881] Thanks to @tktech (https://hackerone.com/tktech) for reporting this issue and the patch! --- .../middleware/host_authorization.rb | 19 ++++++++++++++----- .../test/dispatch/host_authorization_test.rb | 11 +++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index de7739b9b6807..ebfaa61e38d79 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -87,11 +87,20 @@ def call(env) private def authorized?(request) - origin_host = request.get_header("HTTP_HOST").to_s.sub(/:\d+\z/, "") - forwarded_host = request.x_forwarded_host.to_s.split(/,\s?/).last.to_s.sub(/:\d+\z/, "") - - @permissions.allows?(origin_host) && - (forwarded_host.blank? || @permissions.allows?(forwarded_host)) + valid_host = / + \A + (?[a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9\.:]+\]) + (:\d+)? + \z + /x + + origin_host = valid_host.match( + request.get_header("HTTP_HOST").to_s.downcase) + forwarded_host = valid_host.match( + request.x_forwarded_host.to_s.split(/,\s?/).last) + + origin_host && @permissions.allows?(origin_host[:host]) && ( + forwarded_host.nil? || @permissions.allows?(forwarded_host[:host])) end def mark_as_authorized(request) diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb index 5263dd2597f28..027a6749f041f 100644 --- a/actionpack/test/dispatch/host_authorization_test.rb +++ b/actionpack/test/dispatch/host_authorization_test.rb @@ -158,4 +158,15 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_response :ok assert_equal "Success", body end + + test "only compare to valid hostnames" do + @app = ActionDispatch::HostAuthorization.new(App, ".example.com") + + get "/", env: { + "HOST" => "example.com#sub.example.com", + } + + assert_response :forbidden + assert_match "Blocked host: example.com#sub.example.com", response.body + end end From c5929d5eb55b749bc124b3ccc2d79323d015701f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 10 Feb 2021 20:30:10 +0000 Subject: [PATCH 143/244] Preparing for 6.0.3.5 release --- Gemfile.lock | 108 +++++++++--------- RAILS_VERSION | 2 +- actioncable/CHANGELOG.md | 5 + actioncable/lib/action_cable/gem_version.rb | 2 +- actioncable/package.json | 2 +- actionmailbox/CHANGELOG.md | 5 + .../lib/action_mailbox/gem_version.rb | 2 +- actionmailer/CHANGELOG.md | 5 + actionmailer/lib/action_mailer/gem_version.rb | 2 +- actionpack/CHANGELOG.md | 12 ++ actionpack/lib/action_pack/gem_version.rb | 2 +- actiontext/CHANGELOG.md | 5 + actiontext/lib/action_text/gem_version.rb | 2 +- actiontext/package.json | 2 +- actionview/CHANGELOG.md | 5 + actionview/lib/action_view/gem_version.rb | 2 +- actionview/package.json | 2 +- activejob/CHANGELOG.md | 5 + activejob/lib/active_job/gem_version.rb | 2 +- activemodel/CHANGELOG.md | 5 + activemodel/lib/active_model/gem_version.rb | 2 +- activerecord/CHANGELOG.md | 15 +++ activerecord/lib/active_record/gem_version.rb | 2 +- activestorage/CHANGELOG.md | 5 + .../lib/active_storage/gem_version.rb | 2 +- activestorage/package.json | 2 +- activesupport/CHANGELOG.md | 5 + .../lib/active_support/gem_version.rb | 2 +- guides/CHANGELOG.md | 5 + railties/CHANGELOG.md | 5 + railties/lib/rails/gem_version.rb | 2 +- version.rb | 2 +- 32 files changed, 154 insertions(+), 72 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 140f4071a3d9b..3374ef7626fe6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,79 +17,79 @@ GIT PATH remote: . specs: - actioncable (6.0.3.4) - actionpack (= 6.0.3.4) + actioncable (6.0.3.5) + actionpack (= 6.0.3.5) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.3.4) - actionpack (= 6.0.3.4) - activejob (= 6.0.3.4) - activerecord (= 6.0.3.4) - activestorage (= 6.0.3.4) - activesupport (= 6.0.3.4) + actionmailbox (6.0.3.5) + actionpack (= 6.0.3.5) + activejob (= 6.0.3.5) + activerecord (= 6.0.3.5) + activestorage (= 6.0.3.5) + activesupport (= 6.0.3.5) mail (>= 2.7.1) - actionmailer (6.0.3.4) - actionpack (= 6.0.3.4) - actionview (= 6.0.3.4) - activejob (= 6.0.3.4) + actionmailer (6.0.3.5) + actionpack (= 6.0.3.5) + actionview (= 6.0.3.5) + activejob (= 6.0.3.5) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.3.4) - actionview (= 6.0.3.4) - activesupport (= 6.0.3.4) + actionpack (6.0.3.5) + actionview (= 6.0.3.5) + activesupport (= 6.0.3.5) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.3.4) - actionpack (= 6.0.3.4) - activerecord (= 6.0.3.4) - activestorage (= 6.0.3.4) - activesupport (= 6.0.3.4) + actiontext (6.0.3.5) + actionpack (= 6.0.3.5) + activerecord (= 6.0.3.5) + activestorage (= 6.0.3.5) + activesupport (= 6.0.3.5) nokogiri (>= 1.8.5) - actionview (6.0.3.4) - activesupport (= 6.0.3.4) + actionview (6.0.3.5) + activesupport (= 6.0.3.5) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.3.4) - activesupport (= 6.0.3.4) + activejob (6.0.3.5) + activesupport (= 6.0.3.5) globalid (>= 0.3.6) - activemodel (6.0.3.4) - activesupport (= 6.0.3.4) - activerecord (6.0.3.4) - activemodel (= 6.0.3.4) - activesupport (= 6.0.3.4) - activestorage (6.0.3.4) - actionpack (= 6.0.3.4) - activejob (= 6.0.3.4) - activerecord (= 6.0.3.4) + activemodel (6.0.3.5) + activesupport (= 6.0.3.5) + activerecord (6.0.3.5) + activemodel (= 6.0.3.5) + activesupport (= 6.0.3.5) + activestorage (6.0.3.5) + actionpack (= 6.0.3.5) + activejob (= 6.0.3.5) + activerecord (= 6.0.3.5) marcel (~> 0.3.1) - activesupport (6.0.3.4) + activesupport (6.0.3.5) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.3.4) - actioncable (= 6.0.3.4) - actionmailbox (= 6.0.3.4) - actionmailer (= 6.0.3.4) - actionpack (= 6.0.3.4) - actiontext (= 6.0.3.4) - actionview (= 6.0.3.4) - activejob (= 6.0.3.4) - activemodel (= 6.0.3.4) - activerecord (= 6.0.3.4) - activestorage (= 6.0.3.4) - activesupport (= 6.0.3.4) + rails (6.0.3.5) + actioncable (= 6.0.3.5) + actionmailbox (= 6.0.3.5) + actionmailer (= 6.0.3.5) + actionpack (= 6.0.3.5) + actiontext (= 6.0.3.5) + actionview (= 6.0.3.5) + activejob (= 6.0.3.5) + activemodel (= 6.0.3.5) + activerecord (= 6.0.3.5) + activestorage (= 6.0.3.5) + activesupport (= 6.0.3.5) bundler (>= 1.3.0) - railties (= 6.0.3.4) + railties (= 6.0.3.5) sprockets-rails (>= 2.0.0) - railties (6.0.3.4) - actionpack (= 6.0.3.4) - activesupport (= 6.0.3.4) + railties (6.0.3.5) + actionpack (= 6.0.3.5) + activesupport (= 6.0.3.5) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -213,7 +213,7 @@ GEM http_parser.rb (>= 0.6.0) em-socksify (0.3.2) eventmachine (>= 1.0.0.beta.4) - erubi (1.9.0) + erubi (1.10.0) et-orbi (1.2.2) tzinfo event_emitter (0.2.6) @@ -274,7 +274,7 @@ GEM hiredis (0.6.3-java) http_parser.rb (0.6.0) httpclient (2.8.3) - i18n (1.8.5) + i18n (1.8.8) concurrent-ruby (~> 1.0) image_processing (1.10.0) mini_magick (>= 4.9.5, < 5) @@ -295,7 +295,7 @@ GEM listen (3.2.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.7.0) + loofah (2.9.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -525,7 +525,7 @@ GEM websocket-extensions (0.1.4) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.4.0) + zeitwerk (2.4.2) PLATFORMS java diff --git a/RAILS_VERSION b/RAILS_VERSION index 7340754a215aa..71586130f29b8 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.3.4 +6.0.3.5 diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 58c7c17da55ed..959a2f6ad985e 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index 6984a8a208e33..47b74720ab1e4 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index 0cd7753a5bd30..8ec68cf93c869 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.3-4", + "version": "6.0.3-5", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index 1447196502669..15ecdb8b967ac 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index 2290fd9b53921..7fac413d8b8f4 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 17778d22c6675..4cd6b95f8f1dd 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index 3bc01ca9c9172..42e66e144b827 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index e07e13cfdaf84..1ad8a84fa30c6 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,15 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* Prevent open redirect when allowed host starts with a dot + + [CVE-2021-22881] + + Thanks to @tktech (https://hackerone.com/tktech) for reporting this + issue and the patch! + + *Aaron Patterson* + + ## Rails 6.0.3.4 (October 07, 2020) ## * [CVE-2020-8264] Prevent XSS in Actionable Exceptions diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index 14939dc23b46e..368e3235b4292 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 6e85c1f449390..0e58d1db9114d 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index c523b3127e2b7..33ae63b2f1a4d 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index 6b32510ade88a..b5ca5b65e66fe 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.3-4", + "version": "6.0.3-5", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 0eed66805efb5..9909161a43ffa 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 2ef7413e53a5b..830be520529c0 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 4ad4a7b36f198..bcf806c2cbb7f 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.3-4", + "version": "6.0.3-5", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 77ba625be177e..6381fd0f36f6e 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index 968a3dfc59b64..510228b34cf53 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 34d91e4449021..0bfe4b6690e31 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index 73a8a61115e2f..e897350343e76 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 45cb7492c8622..6380572015df6 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,18 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* Fix possible DoS vector in PostgreSQL money type + + Carefully crafted input can cause a DoS via the regular expressions used + for validating the money format in the PostgreSQL adapter. This patch + fixes the regexp. + + Thanks to @dee-see from Hackerone for this patch! + + [CVE-2021-22880] + + *Aaron Patterson* + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index 8ff780b53ec89..8df0a7bee4df2 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 18a74102b52e8..129d1ec603959 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index f451216c87820..d8e26a381531f 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index d0f738cb9ac8c..828cb296a6e09 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.3-4", + "version": "6.0.3-5", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 25661e1983e3c..1672196f6318e 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 62fec91674c45..80a9b4e139f31 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index 65205fddc1f86..2eb6a0cbc8607 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index b1011ce08ed45..7a69f95b3abd2 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.5 (February 10, 2021) ## + +* No changes. + + ## Rails 6.0.3.4 (October 07, 2020) ## * No changes. diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index a81462170f9a4..75dc882e8b679 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index a81462170f9a4..75dc882e8b679 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "4" + PRE = "5" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From 676b0730fbc4bd3e2dd2ec6b7d1d568c9ec1487c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 10 Feb 2021 22:59:17 +0000 Subject: [PATCH 144/244] Remove unnessary escape char in Regexp Fix the test by defining a valid host on the mocked requests. --- .../lib/action_dispatch/middleware/host_authorization.rb | 2 +- railties/test/application/middleware/remote_ip_test.rb | 3 ++- railties/test/isolation/abstract_unit.rb | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index 32ad590dd98da..19562f0100591 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -89,7 +89,7 @@ def call(env) def authorized?(request) valid_host = / \A - (?[a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9\.:]+\]) + (?[a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9.:]+\]) (:\d+)? \z /x diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb index 515b32080e2e7..0dc3dc3979307 100644 --- a/railties/test/application/middleware/remote_ip_test.rb +++ b/railties/test/application/middleware/remote_ip_test.rb @@ -11,8 +11,9 @@ class RemoteIpTest < ActiveSupport::TestCase def remote_ip(env = {}) remote_ip = nil env = Rack::MockRequest.env_for("/").merge(env).merge!( + "HTTP_HOST" => "example.com", "action_dispatch.show_exceptions" => false, - "action_dispatch.key_generator" => ActiveSupport::CachingKeyGenerator.new( + "action_dispatch.key_generator" => ActiveSupport::CachingKeyGenerator.new( ActiveSupport::KeyGenerator.new("b3c631c314c0bbca50c1b2843150fe33", iterations: 1000) ) ) diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 584d30769005a..1d102386833ac 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -82,7 +82,7 @@ def extract_body(response) end def get(path) - @app.call(::Rack::MockRequest.env_for(path)) + @app.call(::Rack::MockRequest.env_for(path, "HTTP_HOST" => "example.com")) end def assert_welcome(resp) From 1a7580fd2a34ba23cf3a6553290e59ca26122c9d Mon Sep 17 00:00:00 2001 From: Chris Stainthorpe Date: Fri, 12 Feb 2021 14:12:31 +0000 Subject: [PATCH 145/244] Mention that speed boost on Hash also changes behaviour --- activesupport/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 3437c0e5c8c4e..4c7d8f0715de4 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -201,6 +201,12 @@ ## Rails 6.0.0.rc1 (April 24, 2019) ## +* Speed improvements to `Hash.except` and `HashWithIndifferentAccess#except`. + + These methods now unset the `default`/`default_proc` on the returned Hash, compatible with Ruby 3.0’s native implementation. + + *Timo Schilling* + * Introduce `ActiveSupport::ActionableError`. Actionable errors let's you dispatch actions from Rails' error pages. This From eb9e3cb642eb64469c3cd9b39fb3108a13414c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 9 Feb 2021 19:19:54 +0000 Subject: [PATCH 146/244] Don't test the bug report template for main in old Rubies --- guides/Rakefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/guides/Rakefile b/guides/Rakefile index b7425f6de46e6..6877eb8426e79 100644 --- a/guides/Rakefile +++ b/guides/Rakefile @@ -92,8 +92,13 @@ task :test do templates = Dir.glob("bug_report_templates/*.rb") counter = templates.count do |file| puts "--- Running #{file}" - Bundler.clean_system(Gem.ruby, "-w", file) || - puts("+++ 💥 FAILED (exit #{$?.exitstatus})") + + if RUBY_VERSION < "2.7.0" && file.end_with?("_main.rb", "benchmark.rb") + 1 + else + Bundler.clean_system(Gem.ruby, "-w", file) || + puts("+++ 💥 FAILED (exit #{$?.exitstatus})") + end end puts "+++ #{counter} / #{templates.size} templates executed successfully" exit 1 if counter < templates.size From e8180f8498a316009c1d093223e1b1c7593acd61 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Sat, 20 Jun 2020 18:00:10 -0500 Subject: [PATCH 147/244] Rewrite test_after_bundle_callback The previous version of the test was fragile due to over-specificity. --- .../test/generators/app_generator_test.rb | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 51f93c29ccd2e..d774d827d0179 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -1045,33 +1045,22 @@ def test_psych_gem end def test_after_bundle_callback - path = "http://example.org/rails_template" - template = +%{ after_bundle { run 'echo ran after_bundle' } } - template.instance_eval "def read; self; end" # Make the string respond to read + sequence = [] - check_open = -> *args do - assert_equal [ path, "Accept" => "application/x-thor-template" ], args - template + bundle_command_stub = -> *args do + sequence << [:bundle_command, *args] end - sequence = ["git init", "install", "binstubs bundler", "exec spring binstub --all", "webpacker:install", "echo ran after_bundle"] - @sequence_step ||= 0 - ensure_bundler_first = -> command, options = nil do - assert_equal sequence[@sequence_step], command, "commands should be called in sequence #{sequence}" - @sequence_step += 1 + generator([destination_root], skip_webpack_install: true).send(:after_bundle) do + sequence << [:after_bundle_callback] end - generator([destination_root], template: path).stub(:open, check_open, template) do - generator.stub(:bundle_command, ensure_bundler_first) do - generator.stub(:run, ensure_bundler_first) do - generator.stub(:rails_command, ensure_bundler_first) do - quietly { generator.invoke_all } - end - end - end + generator.stub(:bundle_command, bundle_command_stub) do + quietly { generator.invoke_all } end - assert_equal 6, @sequence_step + assert_operator sequence.length, :>, 1 + assert_equal [:after_bundle_callback], sequence.last end def test_gitignore From 4c78cc8b04861f02d660aefc37979eb2244db6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 17 Feb 2021 21:31:24 +0000 Subject: [PATCH 148/244] Keep behavior of numericality validator the same on Ruby 3.0 Float#to_d changed the precision on Ruby 3.0. To keep the behavior consistent between ruby version let be explict which precision we want. See https://github.com/ruby/ruby/commit/e1424c35012ccf1f3822c9046081b225aef4142e --- activemodel/lib/active_model/validations/numericality.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index cae82527f7381..ac6682daadcef 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -89,7 +89,7 @@ def is_number?(raw_value) def parse_as_number(raw_value) if raw_value.is_a?(Float) - raw_value.to_d + raw_value.to_d(Float::DIG) elsif raw_value.is_a?(Numeric) raw_value elsif is_integer?(raw_value) From d918be6e7f61fa6a6fea081ca23f17cecd657c3f Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 24 Feb 2021 09:04:13 -0500 Subject: [PATCH 149/244] Fix documentation for joins across clusters We weren't able to get our gem for splitting across clusters into Rails for 6.1. We're hoping to have that work completed for 7.0 but I should have never promised in the docs to get it done by a specific time. Ref #41537 --- guides/source/active_record_multiple_databases.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/guides/source/active_record_multiple_databases.md b/guides/source/active_record_multiple_databases.md index fc86d7696da2a..99ac6fa8f0208 100644 --- a/guides/source/active_record_multiple_databases.md +++ b/guides/source/active_record_multiple_databases.md @@ -265,9 +265,9 @@ handles outside of Rails. ### Joining Across Databases -Applications cannot join across databases. Rails 6.1 will support using `has_many` -relationships and creating 2 queries instead of joining, but Rails 6.0 will require -you to split the joins into 2 selects manually. +Applications cannot join across databases. At the moment applications will need to +manually write two selects and split the joins themselves. In a future version Rails +will split the joins for you. ### Schema Cache From 03950ac91c642d8b19e19a42b6bebe3f71805054 Mon Sep 17 00:00:00 2001 From: Abhay Nikam Date: Sun, 21 Feb 2021 12:49:11 +0530 Subject: [PATCH 150/244] @rails/actiontext: depend on released @rails/activestorage --- actiontext/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actiontext/package.json b/actiontext/package.json index b5ca5b65e66fe..dc71e053410c7 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -21,7 +21,7 @@ ], "license": "MIT", "dependencies": { - "@rails/activestorage": "^6.0.0-alpha" + "@rails/activestorage": "^6.0.0" }, "peerDependencies": { "trix": "^1.2.0" From 6a1649c5ce78bf4d4733f14df9118b8848808d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 24 Mar 2021 22:53:27 +0000 Subject: [PATCH 151/244] Fix handling of ParseError in controllers It regressed in #34894, which moved the rescue to the wrong method. `_wrapper_enabled?` can access the parameters and the exception will raise there before even entering `_perfomr_parameter_wrapping`. Closes #38285. --- actionpack/lib/action_controller/metal/params_wrapper.rb | 5 +++-- actionpack/test/controller/rescue_test.rb | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index ba10dfd6baae2..38d81f9b4edc2 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -275,7 +275,10 @@ def _wrapper_enabled? return false unless request.has_content_type? ref = request.content_mime_type.ref + _wrapper_formats.include?(ref) && _wrapper_key && !request.parameters.key?(_wrapper_key) + rescue ActionDispatch::Http::Parameters::ParseError + false end def _perform_parameter_wrapping @@ -289,8 +292,6 @@ def _perform_parameter_wrapping # This will display the wrapped hash in the log file. request.filtered_parameters.merge! wrapped_filtered_hash - rescue ActionDispatch::Http::Parameters::ParseError - # swallow parse error exception end end end diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index 538bc15fc9ea9..fe691af2aedef 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -33,6 +33,8 @@ class ResourceUnavailable < StandardError class ResourceUnavailableToRescueAsString < StandardError end + wrap_parameters format: :json + # We use a fully qualified name in some strings, and a relative constant # name in some other to test correct handling of both cases. From bd217a406c62b2dda3248c94ba3c5bbf88479f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 24 Mar 2021 23:05:53 +0000 Subject: [PATCH 152/244] Fix indentation --- actionpack/lib/action_controller/metal/params_wrapper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index 38d81f9b4edc2..5cf2e7fee285c 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -278,7 +278,7 @@ def _wrapper_enabled? _wrapper_formats.include?(ref) && _wrapper_key && !request.parameters.key?(_wrapper_key) rescue ActionDispatch::Http::Parameters::ParseError - false + false end def _perform_parameter_wrapping From 0c5b836b22c58abdc199cd6c15e2a29a528207c5 Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Fri, 26 Mar 2021 08:55:39 -0400 Subject: [PATCH 153/244] Upgrade to Marcel 1.0.0 --- Gemfile.lock | 6 ++---- activestorage/activestorage.gemspec | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3374ef7626fe6..9f09a074dd6cf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -65,7 +65,7 @@ PATH actionpack (= 6.0.3.5) activejob (= 6.0.3.5) activerecord (= 6.0.3.5) - marcel (~> 0.3.1) + marcel (~> 1.0.0) activesupport (6.0.3.5) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) @@ -300,11 +300,9 @@ GEM nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (0.3.3) - mimemagic (~> 0.3.2) + marcel (1.0.0) memoist (0.16.2) method_source (1.0.0) - mimemagic (0.3.5) mini_magick (4.9.5) mini_mime (1.0.2) mini_portile2 (2.4.0) diff --git a/activestorage/activestorage.gemspec b/activestorage/activestorage.gemspec index a3fdc130a8511..f5e64922b229c 100644 --- a/activestorage/activestorage.gemspec +++ b/activestorage/activestorage.gemspec @@ -35,5 +35,5 @@ Gem::Specification.new do |s| s.add_dependency "activejob", version s.add_dependency "activerecord", version - s.add_dependency "marcel", "~> 0.3.1" + s.add_dependency "marcel", "~> 1.0.0" end From 0073c7b29339b2ee1e11aa5c9622ea452d0633fc Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Fri, 26 Mar 2021 13:31:15 -0400 Subject: [PATCH 154/244] v6.0.3.6 --- Gemfile.lock | 102 +++++++++--------- RAILS_VERSION | 2 +- actioncable/CHANGELOG.md | 5 + actioncable/lib/action_cable/gem_version.rb | 2 +- actioncable/package.json | 2 +- actionmailbox/CHANGELOG.md | 5 + .../lib/action_mailbox/gem_version.rb | 2 +- actionmailer/CHANGELOG.md | 5 + actionmailer/lib/action_mailer/gem_version.rb | 2 +- actionpack/CHANGELOG.md | 5 + actionpack/lib/action_pack/gem_version.rb | 2 +- actiontext/CHANGELOG.md | 5 + actiontext/lib/action_text/gem_version.rb | 2 +- actiontext/package.json | 2 +- actionview/CHANGELOG.md | 5 + actionview/lib/action_view/gem_version.rb | 2 +- actionview/package.json | 2 +- activejob/CHANGELOG.md | 5 + activejob/lib/active_job/gem_version.rb | 2 +- activemodel/CHANGELOG.md | 5 + activemodel/lib/active_model/gem_version.rb | 2 +- activerecord/CHANGELOG.md | 5 + activerecord/lib/active_record/gem_version.rb | 2 +- activestorage/CHANGELOG.md | 8 ++ .../lib/active_storage/gem_version.rb | 2 +- activestorage/package.json | 2 +- activesupport/CHANGELOG.md | 5 + .../lib/active_support/gem_version.rb | 2 +- guides/CHANGELOG.md | 5 + railties/CHANGELOG.md | 5 + railties/lib/rails/gem_version.rb | 2 +- version.rb | 2 +- 32 files changed, 136 insertions(+), 70 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9f09a074dd6cf..42f301a89118c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,79 +17,79 @@ GIT PATH remote: . specs: - actioncable (6.0.3.5) - actionpack (= 6.0.3.5) + actioncable (6.0.3.6) + actionpack (= 6.0.3.6) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.3.5) - actionpack (= 6.0.3.5) - activejob (= 6.0.3.5) - activerecord (= 6.0.3.5) - activestorage (= 6.0.3.5) - activesupport (= 6.0.3.5) + actionmailbox (6.0.3.6) + actionpack (= 6.0.3.6) + activejob (= 6.0.3.6) + activerecord (= 6.0.3.6) + activestorage (= 6.0.3.6) + activesupport (= 6.0.3.6) mail (>= 2.7.1) - actionmailer (6.0.3.5) - actionpack (= 6.0.3.5) - actionview (= 6.0.3.5) - activejob (= 6.0.3.5) + actionmailer (6.0.3.6) + actionpack (= 6.0.3.6) + actionview (= 6.0.3.6) + activejob (= 6.0.3.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.3.5) - actionview (= 6.0.3.5) - activesupport (= 6.0.3.5) + actionpack (6.0.3.6) + actionview (= 6.0.3.6) + activesupport (= 6.0.3.6) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.3.5) - actionpack (= 6.0.3.5) - activerecord (= 6.0.3.5) - activestorage (= 6.0.3.5) - activesupport (= 6.0.3.5) + actiontext (6.0.3.6) + actionpack (= 6.0.3.6) + activerecord (= 6.0.3.6) + activestorage (= 6.0.3.6) + activesupport (= 6.0.3.6) nokogiri (>= 1.8.5) - actionview (6.0.3.5) - activesupport (= 6.0.3.5) + actionview (6.0.3.6) + activesupport (= 6.0.3.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.3.5) - activesupport (= 6.0.3.5) + activejob (6.0.3.6) + activesupport (= 6.0.3.6) globalid (>= 0.3.6) - activemodel (6.0.3.5) - activesupport (= 6.0.3.5) - activerecord (6.0.3.5) - activemodel (= 6.0.3.5) - activesupport (= 6.0.3.5) - activestorage (6.0.3.5) - actionpack (= 6.0.3.5) - activejob (= 6.0.3.5) - activerecord (= 6.0.3.5) + activemodel (6.0.3.6) + activesupport (= 6.0.3.6) + activerecord (6.0.3.6) + activemodel (= 6.0.3.6) + activesupport (= 6.0.3.6) + activestorage (6.0.3.6) + actionpack (= 6.0.3.6) + activejob (= 6.0.3.6) + activerecord (= 6.0.3.6) marcel (~> 1.0.0) - activesupport (6.0.3.5) + activesupport (6.0.3.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.3.5) - actioncable (= 6.0.3.5) - actionmailbox (= 6.0.3.5) - actionmailer (= 6.0.3.5) - actionpack (= 6.0.3.5) - actiontext (= 6.0.3.5) - actionview (= 6.0.3.5) - activejob (= 6.0.3.5) - activemodel (= 6.0.3.5) - activerecord (= 6.0.3.5) - activestorage (= 6.0.3.5) - activesupport (= 6.0.3.5) + rails (6.0.3.6) + actioncable (= 6.0.3.6) + actionmailbox (= 6.0.3.6) + actionmailer (= 6.0.3.6) + actionpack (= 6.0.3.6) + actiontext (= 6.0.3.6) + actionview (= 6.0.3.6) + activejob (= 6.0.3.6) + activemodel (= 6.0.3.6) + activerecord (= 6.0.3.6) + activestorage (= 6.0.3.6) + activesupport (= 6.0.3.6) bundler (>= 1.3.0) - railties (= 6.0.3.5) + railties (= 6.0.3.6) sprockets-rails (>= 2.0.0) - railties (6.0.3.5) - actionpack (= 6.0.3.5) - activesupport (= 6.0.3.5) + railties (6.0.3.6) + actionpack (= 6.0.3.6) + activesupport (= 6.0.3.6) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -518,8 +518,6 @@ GEM websocket (1.2.8) websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) - websocket-driver (0.7.1-java) - websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) xpath (3.2.0) nokogiri (~> 1.8) diff --git a/RAILS_VERSION b/RAILS_VERSION index 71586130f29b8..1acaa6c773b67 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.3.5 +6.0.3.6 diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 959a2f6ad985e..d98edcd24fb1a 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index 47b74720ab1e4..aecff2e6e1eb6 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index 8ec68cf93c869..39fb130749d15 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.3-5", + "version": "6.0.3-6", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index 15ecdb8b967ac..29c90dac487db 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index 7fac413d8b8f4..71e9844a89ecc 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 4cd6b95f8f1dd..a13858bd35166 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index 42e66e144b827..7963aa49e658a 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 1ad8a84fa30c6..351edd929faeb 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * Prevent open redirect when allowed host starts with a dot diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index 368e3235b4292..9a8a0b87e8de5 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 0e58d1db9114d..5b1972b72fb4d 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index 33ae63b2f1a4d..2407f4fb9f92a 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index b5ca5b65e66fe..c92ce54f3e8f0 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.3-5", + "version": "6.0.3-6", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 9909161a43ffa..3381c199c221f 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 830be520529c0..e08d84b48131b 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index bcf806c2cbb7f..318f6d72c4cb6 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.3-5", + "version": "6.0.3-6", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 6381fd0f36f6e..bbde6ec43ace2 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index 510228b34cf53..f445536eb5314 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 0bfe4b6690e31..51559f4083dd4 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index e897350343e76..4df3adfd4212e 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 6380572015df6..47739dae0e3d6 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * Fix possible DoS vector in PostgreSQL money type diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index 8df0a7bee4df2..8027676474a38 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 129d1ec603959..635f42868cbd1 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,11 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* Marcel is upgraded to version 1.0.0 to avoid a dependency on GPL-licensed + mime types data. + + *George Claghorn* + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index d8e26a381531f..28d4b33ab6376 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index 828cb296a6e09..7a6ef965264eb 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.3-5", + "version": "6.0.3-6", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 1672196f6318e..598c90aec3308 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 80a9b4e139f31..3b247c0c305e3 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index 2eb6a0cbc8607..ee168ed404fd0 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 7a69f95b3abd2..dd39e306d10df 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.6 (March 26, 2021) ## + +* No changes. + + ## Rails 6.0.3.5 (February 10, 2021) ## * No changes. diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index 75dc882e8b679..aa12023425413 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index 75dc882e8b679..aa12023425413 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "5" + PRE = "6" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From 64bb514358d01106ddfcb20849581dc8da344e30 Mon Sep 17 00:00:00 2001 From: Scott Blum Date: Sun, 29 Mar 2020 00:07:09 -0400 Subject: [PATCH 155/244] Accept and default to base64_urlsafe CSRF tokens (#18496) Base64 strict-encoded CSRF tokens are not inherently websafe, which makes them difficult to deal with. For example, the common practice of sending the CSRF token to a browser in a client-readable cookie does not work properly out of the box: the value has to be url-encoded and decoded to survive transport. Now, we generate Base64 urlsafe-encoded CSRF tokens, which are inherently safe to transport. Validation accepts both urlsafe tokens, and strict-encoded tokens for backwards compatibility. --- actionpack/CHANGELOG.md | 13 ++++++++++++ .../metal/request_forgery_protection.rb | 8 +++---- .../request_forgery_protection_test.rb | 21 ++++++++++++------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 8e2751aedb358..3f85e095c63e0 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,16 @@ +* Accept and default to base64_urlsafe CSRF tokens. + + Base64 strict-encoded CSRF tokens are not inherently websafe, which makes + them difficult to deal with. For example, the common practice of sending + the CSRF token to a browser in a client-readable cookie does not work properly + out of the box: the value has to be url-encoded and decoded to survive transport. + + Now, we generate Base64 urlsafe-encoded CSRF tokens, which are inherently safe + to transport. Validation accepts both urlsafe tokens, and strict-encoded tokens + for backwards compatibility. + + *Scott Blum* + * Signed and encrypted cookies can now store `false` as their value when `action_dispatch.use_cookies_with_metadata` is enabled. diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 8123170533346..a78b1f7154743 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -329,7 +329,7 @@ def valid_authenticity_token?(session, encoded_masked_token) # :doc: end begin - masked_token = Base64.strict_decode64(encoded_masked_token) + masked_token = Base64.urlsafe_decode64(encoded_masked_token) rescue ArgumentError # encoded_masked_token is invalid Base64 return false end @@ -367,7 +367,7 @@ def mask_token(raw_token) # :doc: one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH) encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token) masked_token = one_time_pad + encrypted_csrf_token - Base64.strict_encode64(masked_token) + Base64.urlsafe_encode64(masked_token, padding: false) end def compare_with_real_token(token, session) # :doc: @@ -393,8 +393,8 @@ def valid_per_form_csrf_token?(token, session) # :doc: end def real_csrf_token(session) # :doc: - session[:_csrf_token] ||= SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH) - Base64.strict_decode64(session[:_csrf_token]) + session[:_csrf_token] ||= SecureRandom.urlsafe_base64(AUTHENTICITY_TOKEN_LENGTH, padding: false) + Base64.urlsafe_decode64(session[:_csrf_token]) end def per_form_csrf_token(session, action_path, method) # :doc: diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 10de9bcc3e533..dbb2caa3b2e58 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -175,7 +175,7 @@ class SkipProtectionController < ActionController::Base # common test methods module RequestForgeryProtectionTests def setup - @token = Base64.strict_encode64("railstestrailstestrailstestrails") + @token = Base64.urlsafe_encode64("railstestrailstestrailstestrails") @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token ActionController::Base.request_forgery_protection_token = :custom_authenticity_token end @@ -377,6 +377,13 @@ def test_should_allow_post_with_token end end + def test_should_allow_post_with_strict_encoded_token + session[:_csrf_token] = Base64.strict_encode64("railstestrailstestrailstestrails") + @controller.stub :form_authenticity_token, @token do + assert_not_blocked { post :index, params: { custom_authenticity_token: @token } } + end + end + def test_should_allow_patch_with_token session[:_csrf_token] = @token @controller.stub :form_authenticity_token, @token do @@ -735,21 +742,21 @@ def setup end def test_should_not_render_form_with_token_tag - SecureRandom.stub :base64, @token do + SecureRandom.stub :urlsafe_base64, @token do get :index assert_select "form>div>input[name=?][value=?]", "authenticity_token", @token, false end end def test_should_not_render_button_to_with_token_tag - SecureRandom.stub :base64, @token do + SecureRandom.stub :urlsafe_base64, @token do get :show_button assert_select "form>div>input[name=?][value=?]", "authenticity_token", @token, false end end def test_should_allow_all_methods_without_token - SecureRandom.stub :base64, @token do + SecureRandom.stub :urlsafe_base64, @token do [:post, :patch, :put, :delete].each do |method| assert_nothing_raised { send(method, :index) } end @@ -757,7 +764,7 @@ def test_should_allow_all_methods_without_token end test "should not emit a csrf-token meta tag" do - SecureRandom.stub :base64, @token do + SecureRandom.stub :urlsafe_base64, @token do get :meta assert_predicate @response.body, :blank? end @@ -769,7 +776,7 @@ def setup super @old_logger = ActionController::Base.logger @logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new - @token = Base64.strict_encode64(SecureRandom.random_bytes(32)) + @token = Base64.urlsafe_encode64(SecureRandom.random_bytes(32)) @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token ActionController::Base.request_forgery_protection_token = @token end @@ -1029,7 +1036,7 @@ def assert_presence_and_fetch_form_csrf_token end def assert_matches_session_token_on_server(form_token, method = "post") - actual = @controller.send(:unmask_token, Base64.strict_decode64(form_token)) + actual = @controller.send(:unmask_token, Base64.urlsafe_decode64(form_token)) expected = @controller.send(:per_form_csrf_token, session, "/per_form_tokens/post_one", method) assert_equal expected, actual end From f35b4ae90ce45b85f5a2a839b91a710d092f61d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Thu, 11 Jun 2020 11:40:32 -0400 Subject: [PATCH 156/244] Merge pull request #39076 from etiennebarrie/upgrade-safe-urlsafe-csrf-tokens Upgrade-safe URL-safe CSRF tokens --- actionpack/CHANGELOG.md | 2 +- .../metal/request_forgery_protection.rb | 40 +++++++++++++++++-- .../request_forgery_protection_test.rb | 24 +++++++++-- guides/source/configuring.md | 2 + 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 3f85e095c63e0..fdacb35c03394 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -6,7 +6,7 @@ out of the box: the value has to be url-encoded and decoded to survive transport. Now, we generate Base64 urlsafe-encoded CSRF tokens, which are inherently safe - to transport. Validation accepts both urlsafe tokens, and strict-encoded tokens + to transport. Validation accepts both urlsafe tokens, and strict-encoded tokens for backwards compatibility. *Scott Blum* diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index a78b1f7154743..3c7faaf1d1c94 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -90,6 +90,10 @@ module RequestForgeryProtection config_accessor :default_protect_from_forgery self.default_protect_from_forgery = false + # Controls whether URL-safe CSRF tokens are generated. + config_accessor :urlsafe_csrf_tokens, instance_writer: false + self.urlsafe_csrf_tokens = false + helper_method :form_authenticity_token helper_method :protect_against_forgery? end @@ -329,7 +333,7 @@ def valid_authenticity_token?(session, encoded_masked_token) # :doc: end begin - masked_token = Base64.urlsafe_decode64(encoded_masked_token) + masked_token = decode_csrf_token(encoded_masked_token) rescue ArgumentError # encoded_masked_token is invalid Base64 return false end @@ -367,7 +371,7 @@ def mask_token(raw_token) # :doc: one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH) encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token) masked_token = one_time_pad + encrypted_csrf_token - Base64.urlsafe_encode64(masked_token, padding: false) + encode_csrf_token(masked_token) end def compare_with_real_token(token, session) # :doc: @@ -393,8 +397,8 @@ def valid_per_form_csrf_token?(token, session) # :doc: end def real_csrf_token(session) # :doc: - session[:_csrf_token] ||= SecureRandom.urlsafe_base64(AUTHENTICITY_TOKEN_LENGTH, padding: false) - Base64.urlsafe_decode64(session[:_csrf_token]) + session[:_csrf_token] ||= generate_csrf_token + decode_csrf_token(session[:_csrf_token]) end def per_form_csrf_token(session, action_path, method) # :doc: @@ -462,5 +466,33 @@ def normalize_action_path(action_path) # :doc: uri = URI.parse(action_path) uri.path.chomp("/") end + + def generate_csrf_token # :nodoc: + if urlsafe_csrf_tokens + SecureRandom.urlsafe_base64(AUTHENTICITY_TOKEN_LENGTH, padding: false) + else + SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH) + end + end + + def encode_csrf_token(csrf_token) # :nodoc: + if urlsafe_csrf_tokens + Base64.urlsafe_encode64(csrf_token, padding: false) + else + Base64.strict_encode64(csrf_token) + end + end + + def decode_csrf_token(encoded_csrf_token) # :nodoc: + if urlsafe_csrf_tokens + Base64.urlsafe_decode64(encoded_csrf_token) + else + begin + Base64.strict_decode64(encoded_csrf_token) + rescue ArgumentError + Base64.urlsafe_decode64(encoded_csrf_token) + end + end + end end end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index dbb2caa3b2e58..1ad48b5cf69f3 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -175,12 +175,15 @@ class SkipProtectionController < ActionController::Base # common test methods module RequestForgeryProtectionTests def setup + @old_urlsafe_csrf_tokens = ActionController::Base.urlsafe_csrf_tokens + ActionController::Base.urlsafe_csrf_tokens = true @token = Base64.urlsafe_encode64("railstestrailstestrailstestrails") @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token ActionController::Base.request_forgery_protection_token = :custom_authenticity_token end def teardown + ActionController::Base.urlsafe_csrf_tokens = @old_urlsafe_csrf_tokens ActionController::Base.request_forgery_protection_token = @old_request_forgery_protection_token end @@ -378,10 +381,25 @@ def test_should_allow_post_with_token end def test_should_allow_post_with_strict_encoded_token - session[:_csrf_token] = Base64.strict_encode64("railstestrailstestrailstestrails") - @controller.stub :form_authenticity_token, @token do - assert_not_blocked { post :index, params: { custom_authenticity_token: @token } } + token_length = (ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH * 4.0 / 3).ceil + token_including_url_unsafe_chars = "+/".ljust(token_length, "A") + session[:_csrf_token] = token_including_url_unsafe_chars + @controller.stub :form_authenticity_token, token_including_url_unsafe_chars do + assert_not_blocked { post :index, params: { custom_authenticity_token: token_including_url_unsafe_chars } } + end + end + + def test_should_allow_post_with_urlsafe_token_when_migrating + config_before = ActionController::Base.urlsafe_csrf_tokens + ActionController::Base.urlsafe_csrf_tokens = false + token_length = (ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH * 4.0 / 3).ceil + token_including_url_safe_chars = "-_".ljust(token_length, "A") + session[:_csrf_token] = token_including_url_safe_chars + @controller.stub :form_authenticity_token, token_including_url_safe_chars do + assert_not_blocked { post :index, params: { custom_authenticity_token: token_including_url_safe_chars } } end + ensure + ActionController::Base.urlsafe_csrf_tokens = config_before end def test_should_allow_patch_with_token diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 61da951ab8805..29750bc97701d 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -486,6 +486,8 @@ The schema dumper adds two additional configuration options: * `config.action_controller.default_protect_from_forgery` determines whether forgery protection is added on `ActionController:Base`. This is false by default. +* `config.action_controller.urlsafe_csrf_tokens` configures whether generated CSRF tokens are URL-safe. Defaults to `false`. + * `config.action_controller.relative_url_root` can be used to tell Rails that you are [deploying to a subdirectory](configuring.html#deploy-to-a-subdirectory-relative-url-root). The default is `ENV['RAILS_RELATIVE_URL_ROOT']`. * `config.action_controller.permit_all_parameters` sets all the parameters for mass assignment to be permitted by default. The default value is `false`. From ef808bf1aad7a6d4d25afa3ed88f057c75c90b50 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 31 Mar 2021 12:59:19 +0900 Subject: [PATCH 157/244] Clarify how to upgrade apps from Rails 5.2.5 [ci skip] --- actionpack/CHANGELOG.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index fdacb35c03394..2d91ba1f8ba65 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,15 +1,22 @@ -* Accept and default to base64_urlsafe CSRF tokens. +* Accept base64_urlsafe CSRF tokens to make forward compatible. Base64 strict-encoded CSRF tokens are not inherently websafe, which makes them difficult to deal with. For example, the common practice of sending the CSRF token to a browser in a client-readable cookie does not work properly out of the box: the value has to be url-encoded and decoded to survive transport. - Now, we generate Base64 urlsafe-encoded CSRF tokens, which are inherently safe - to transport. Validation accepts both urlsafe tokens, and strict-encoded tokens - for backwards compatibility. + In Rails 6.1, we generate Base64 urlsafe-encoded CSRF tokens, which are inherently + safe to transport. Validation accepts both urlsafe tokens, and strict-encoded + tokens for backwards compatibility. - *Scott Blum* + In Rails 5.2.5, the CSRF token format is accidentally changed to urlsafe-encoded. + If you upgrade apps from 5.2.5, set the config `urlsafe_csrf_tokens = true`. + + ```ruby + Rails.application.config.action_controller.urlsafe_csrf_tokens = true + ``` + + *Scott Blum*, *Étienne Barrié* * Signed and encrypted cookies can now store `false` as their value when `action_dispatch.use_cookies_with_metadata` is enabled. From bd48a0e3d1061d35815a517b764e4a21ae87749f Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Thu, 26 Mar 2020 22:52:43 +0000 Subject: [PATCH 158/244] Merge pull request #38814 from eugeneius/test_runner_trailing_slash Handle paths with trailing slashes in rails test --- railties/CHANGELOG.md | 4 ++++ railties/lib/rails/test_unit/runner.rb | 10 +++++++++- railties/test/application/test_runner_test.rb | 10 ++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index a646bb2e11cd4..e6ce7fdec8019 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,7 @@ +* Allow relative paths with trailing slashes to be passed to `rails test`. + + *Eugene Kenny* + * Return a 405 Method Not Allowed response when a request uses an unknown HTTP method. Fixes #38998. diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb index d38952bb309b9..8c6467b22c310 100644 --- a/railties/lib/rails/test_unit/runner.rb +++ b/railties/lib/rails/test_unit/runner.rb @@ -61,7 +61,7 @@ def compose_filter(runnable, filter) private def extract_filters(argv) # Extract absolute and relative paths but skip -n /.*/ regexp filters. - argv.select { |arg| arg =~ %r%^/?\w+/% && !arg.end_with?("/") }.map do |path| + argv.select { |arg| path_argument?(arg) && !regexp_filter?(arg) }.map do |path| case when /(:\d+)+$/.match?(path) file, *lines = path.split(":") @@ -75,6 +75,14 @@ def extract_filters(argv) end end end + + def regexp_filter?(arg) + arg.start_with?("/") && arg.end_with?("/") + end + + def path_argument?(arg) + %r%^/?\w+/%.match?(arg) + end end end diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb index 7fc918898bd24..26b5b1a2f22f2 100644 --- a/railties/test/application/test_runner_test.rb +++ b/railties/test/application/test_runner_test.rb @@ -310,6 +310,16 @@ def test_run_multiple_folders_with_absolute_paths end end + def test_run_relative_path_with_trailing_slash + create_test_file :models, "account" + create_test_file :controllers, "accounts_controller" + + run_test_command("test/models/").tap do |output| + assert_match "AccountTest", output + assert_match "1 runs, 1 assertions, 0 failures, 0 errors, 0 skips", output + end + end + def test_run_with_ruby_command app_file "test/models/post_test.rb", <<-RUBY require 'test_helper' From 72719a923be68c33680f83e71d5f630461a3abb9 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Mon, 3 Aug 2020 21:21:10 +0100 Subject: [PATCH 159/244] Merge pull request #39948 from victorperez/fix-variant-test fix misleading variant test Marcel 1.0 correctly identifies the test file as a BMP image, which causes Active Storage to convert it to the fallback PNG format. --- activestorage/test/models/variant_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activestorage/test/models/variant_test.rb b/activestorage/test/models/variant_test.rb index 6b43923159348..1d462b2294127 100644 --- a/activestorage/test/models/variant_test.rb +++ b/activestorage/test/models/variant_test.rb @@ -155,10 +155,10 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase test "resized variation of BMP blob" do blob = create_file_blob(filename: "colors.bmp") variant = blob.variant(resize: "15x15").processed - assert_match(/colors\.bmp/, variant.service_url) + assert_match(/colors\.png/, variant.service_url) image = read_image(variant) - assert_equal "BMP", image.type + assert_equal "PNG", image.type assert_equal 15, image.width assert_equal 8, image.height end From 93173953e3b34e0faced2f28828c51f9dd4527f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Mon, 12 Apr 2021 15:53:35 -0400 Subject: [PATCH 160/244] Merge pull request #41931 from MarcelEeken/deep-merge-changing-original-hash Deep duplicate in `deep_merge` so no references remain to the original hash in the result --- activesupport/CHANGELOG.md | 4 ++++ .../lib/active_support/core_ext/hash/deep_merge.rb | 2 +- activesupport/test/core_ext/hash_ext_test.rb | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 92497f94932c9..58b22516827a4 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,7 @@ +* Fix issue in `Hash#deep_merge` where it did not properly duplicate a nested `Hash` + + *Marcel Eeken* + * Fixed issue in `ActiveSupport::Cache::RedisCacheStore` not passing options to `read_multi` causing `fetch_multi` to not work properly. diff --git a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb index 9bc50b7bc63bf..020eb78f035b2 100644 --- a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb +++ b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb @@ -16,7 +16,7 @@ class Hash # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val } # # => { a: 100, b: 450, c: { c1: 300 } } def deep_merge(other_hash, &block) - dup.deep_merge!(other_hash, &block) + deep_dup.deep_merge!(other_hash, &block) end # Same as +deep_merge+, but modifies +self+. diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 8572d56722d09..0bd5caf5c0602 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -299,6 +299,16 @@ def test_deep_merge_with_falsey_values assert_equal expected, hash_1 end + def test_deep_merge_with_nested_hash_returning_full_new_hash + hash_1 = { a: { b: "foo" } } + hash_2 = { d: "bar" } + + new_hash = hash_1.deep_merge(hash_2) + new_hash[:a][:b] = "baz" + + assert_equal("foo", hash_1[:a][:b]) + end + def test_reverse_merge defaults = { d: 0, a: "x", b: "y", c: 10 }.freeze options = { a: 1, b: 2 } From edc70648b3044a785c710e97c50c8042ca8c313d Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Tue, 13 Apr 2021 12:29:40 +0200 Subject: [PATCH 161/244] Revert "Merge pull request #41931 from MarcelEeken/deep-merge-changing-original-hash" This reverts commit 93173953e3b34e0faced2f28828c51f9dd4527f2. --- activesupport/CHANGELOG.md | 4 ---- .../lib/active_support/core_ext/hash/deep_merge.rb | 2 +- activesupport/test/core_ext/hash_ext_test.rb | 10 ---------- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 58b22516827a4..92497f94932c9 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,7 +1,3 @@ -* Fix issue in `Hash#deep_merge` where it did not properly duplicate a nested `Hash` - - *Marcel Eeken* - * Fixed issue in `ActiveSupport::Cache::RedisCacheStore` not passing options to `read_multi` causing `fetch_multi` to not work properly. diff --git a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb index 020eb78f035b2..9bc50b7bc63bf 100644 --- a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb +++ b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb @@ -16,7 +16,7 @@ class Hash # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val } # # => { a: 100, b: 450, c: { c1: 300 } } def deep_merge(other_hash, &block) - deep_dup.deep_merge!(other_hash, &block) + dup.deep_merge!(other_hash, &block) end # Same as +deep_merge+, but modifies +self+. diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 0bd5caf5c0602..8572d56722d09 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -299,16 +299,6 @@ def test_deep_merge_with_falsey_values assert_equal expected, hash_1 end - def test_deep_merge_with_nested_hash_returning_full_new_hash - hash_1 = { a: { b: "foo" } } - hash_2 = { d: "bar" } - - new_hash = hash_1.deep_merge(hash_2) - new_hash[:a][:b] = "baz" - - assert_equal("foo", hash_1[:a][:b]) - end - def test_reverse_merge defaults = { d: 0, a: "x", b: "y", c: 10 }.freeze options = { a: 1, b: 2 } From 3574a1be6c4f02e28beae201160ff13537dc4172 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Wed, 21 Apr 2021 22:03:19 +0100 Subject: [PATCH 162/244] Merge pull request #40384 from eugeneius/teardown_shared_connection_pool Restore connection pools after transactional tests --- .../lib/active_record/test_fixtures.rb | 18 +++++++++++++++++ activerecord/test/cases/fixtures_test.rb | 20 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/activerecord/lib/active_record/test_fixtures.rb b/activerecord/lib/active_record/test_fixtures.rb index c374368662512..05c00ba92530e 100644 --- a/activerecord/lib/active_record/test_fixtures.rb +++ b/activerecord/lib/active_record/test_fixtures.rb @@ -112,6 +112,8 @@ def setup_fixtures(config = ActiveRecord::Base) # Load fixtures once and begin transaction. if run_in_transaction? + @saved_pool_configs = Hash.new { |hash, key| hash[key] = {} } + if @@already_loaded_fixtures[self.class] @loaded_fixtures = @@already_loaded_fixtures[self.class] else @@ -166,6 +168,7 @@ def teardown_fixtures connection.pool.lock_thread = false end @fixture_connections.clear + teardown_shared_connection_pool else ActiveRecord::FixtureSet.reset_cache end @@ -195,12 +198,27 @@ def setup_shared_connection_pool name = pool.spec.name writing_connection = writing_handler.retrieve_connection_pool(name) return unless writing_connection + + reading_connection = handler.send(:owner_to_pool)[name] + next if reading_connection == writing_connection + + @saved_pool_configs[handler][name] = reading_connection handler.send(:owner_to_pool)[name] = writing_connection end end end end + def teardown_shared_connection_pool + @saved_pool_configs.each_pair do |handler, pools| + pools.each_pair do |name, pool| + handler.send(:owner_to_pool)[name] = pool + end + end + + @saved_pool_configs.clear + end + def load_fixtures(config) fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config) Hash[fixtures.map { |f| [f.name, f] }] diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index bf3a1e76af728..6a1cd61d0fb7e 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -1369,6 +1369,8 @@ def setup ActiveRecord::Base.connection_handlers = {} ActiveRecord::Base.connection_handler = handler ActiveRecord::Base.connects_to(database: { writing: :default, reading: :readonly }) + + setup_shared_connection_pool end def teardown @@ -1392,6 +1394,24 @@ def test_writing_and_reading_connections_are_the_same ro_conn = ActiveRecord::Base.connection_handlers[:reading].connection_pool_list.first.connection assert_equal rw_conn, ro_conn + + teardown_shared_connection_pool + + rw_conn = ActiveRecord::Base.connection_handlers[:writing].connection_pool_list.first.connection + ro_conn = ActiveRecord::Base.connection_handlers[:reading].connection_pool_list.first.connection + + assert_not_equal rw_conn, ro_conn + end + + def test_only_existing_connections_are_restored + ActiveRecord::Base.connection_handlers = { writing: ActiveRecord::Base.default_connection_handler } + teardown_shared_connection_pool + + assert_raises(ActiveRecord::ConnectionNotEstablished) do + ActiveRecord::Base.connected_to(role: :reading) do + ActiveRecord::Base.retrieve_connection + end + end end private From fa473ec9dc2bbdbfb6f8ac742a5a523b1b99f900 Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Sun, 25 Apr 2021 01:27:06 +0100 Subject: [PATCH 163/244] Fix fixture tests that replace connection handler These tests have been failing intermittently since 3574a1be6c4f02e28beae201160ff13537dc4172 was merged. They replace the connection handler during setup, but before that can happen the existing handler's pool configuration has already been saved by `setup_shared_connection_pool`. Later when the test calls `teardown_shared_connection_pool`, it tries to restore connection pools that do not exist in the new handler and blows up. We can avoid this problem by calling `teardown_shared_connection_pool` to clear the saved pools before replacing the connection handler. --- activerecord/test/cases/fixtures_test.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 6a1cd61d0fb7e..0ea4dca5d65ce 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -1364,10 +1364,12 @@ def setup @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(ENV["RAILS_ENV"], "readonly", readonly_config) + teardown_shared_connection_pool + handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new - handler.establish_connection(db_config.config) ActiveRecord::Base.connection_handlers = {} ActiveRecord::Base.connection_handler = handler + handler.establish_connection(db_config.config) ActiveRecord::Base.connects_to(database: { writing: :default, reading: :readonly }) setup_shared_connection_pool From add3d4e9979a36a3ba072e2ef23772bbb819956a Mon Sep 17 00:00:00 2001 From: Gannon McGibbon Date: Sat, 12 Oct 2019 21:39:00 -0400 Subject: [PATCH 164/244] Merge pull request #37448 from gmcgibbon/fix_flaky_activestorage_tests Fix flaky activestorage tests --- activestorage/app/models/active_storage/blob.rb | 2 -- activestorage/lib/active_storage/service.rb | 1 + activestorage/test/models/attached/many_test.rb | 4 +++- activestorage/test/models/attached/one_test.rb | 4 +++- activestorage/test/test_helper.rb | 2 ++ 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb index 9e51ac3c81006..6634e45822b2d 100644 --- a/activestorage/app/models/active_storage/blob.rb +++ b/activestorage/app/models/active_storage/blob.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "active_storage/downloader" - # A blob is a record that contains the metadata about a file and a key for where that file resides on the service. # Blobs can be created in two ways: # diff --git a/activestorage/lib/active_storage/service.rb b/activestorage/lib/active_storage/service.rb index f93ce21897210..9fb03cb827227 100644 --- a/activestorage/lib/active_storage/service.rb +++ b/activestorage/lib/active_storage/service.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "active_storage/log_subscriber" +require "active_storage/downloader" require "action_dispatch" require "action_dispatch/http/content_disposition" diff --git a/activestorage/test/models/attached/many_test.rb b/activestorage/test/models/attached/many_test.rb index 21cfb26b4ffb7..f01b09d4d217d 100644 --- a/activestorage/test/models/attached/many_test.rb +++ b/activestorage/test/models/attached/many_test.rb @@ -10,7 +10,9 @@ class ActiveStorage::ManyAttachedTest < ActiveSupport::TestCase @user = User.create!(name: "Josh") end - teardown { ActiveStorage::Blob.all.each(&:delete) } + teardown do + ActiveStorage::Blob.all.each(&:delete) + end test "attaching existing blobs to an existing record" do @user.highlights.attach create_blob(filename: "funky.jpg"), create_blob(filename: "town.jpg") diff --git a/activestorage/test/models/attached/one_test.rb b/activestorage/test/models/attached/one_test.rb index 0034e9d6d9fda..73da7559f482a 100644 --- a/activestorage/test/models/attached/one_test.rb +++ b/activestorage/test/models/attached/one_test.rb @@ -10,7 +10,9 @@ class ActiveStorage::OneAttachedTest < ActiveSupport::TestCase @user = User.create!(name: "Josh") end - teardown { ActiveStorage::Blob.all.each(&:delete) } + teardown do + ActiveStorage::Blob.all.each(&:delete) + end test "attaching an existing blob to an existing record" do @user.avatar.attach create_blob(filename: "funky.jpg") diff --git a/activestorage/test/test_helper.rb b/activestorage/test/test_helper.rb index 6734f73ab1c53..a41224104f823 100644 --- a/activestorage/test/test_helper.rb +++ b/activestorage/test/test_helper.rb @@ -40,6 +40,8 @@ class ActiveSupport::TestCase self.file_fixture_path = File.expand_path("fixtures/files", __dir__) + include ActiveRecord::TestFixtures + setup do ActiveStorage::Current.host = "https://example.com" end From 446afbd15360a347c923ca775b21a286dcb5297a Mon Sep 17 00:00:00 2001 From: Security Curious Date: Sat, 27 Mar 2021 16:06:59 -0400 Subject: [PATCH 165/244] Prevent catastrophic backtracking during mime parsing The regular expression used to parse the mime type can results in catastrophic backtracking[1] allowing for a ReDOS attack[2]. This commit uses atomic grouping[3] to prevent backtracking. 1. https://www.regular-expressions.info/catastrophic.html 2. https://en.wikipedia.org/wiki/ReDoS 3. https://www.regular-expressions.info/atomic.html [CVE-2021-22902] --- actionpack/lib/action_dispatch/http/mime_type.rb | 2 +- actionpack/test/dispatch/mime_type_test.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 6719f0c3d9351..a5816924de36b 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -226,7 +226,7 @@ def unregister(symbol) MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}" MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?" MIME_PARAMETER = "\s*\;\s*#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?" - MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?:\s*#{MIME_PARAMETER}\s*)*)\z/ + MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>\s*#{MIME_PARAMETER}\s*)*)\z/ class InvalidMimeType < StandardError; end diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 2df973e44d59a..23a5b7f338ed6 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -225,5 +225,11 @@ class MimeTypeTest < ActiveSupport::TestCase assert_raises Mime::Type::InvalidMimeType do Mime::Type.new(nil) end + + assert_raises Mime::Type::InvalidMimeType do + Timeout.timeout(1) do # Shouldn't take more than 1s + Mime::Type.new("text/html ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0;") + end + end end end From f202249bdd701f908a57d733e633d366a982f8ce Mon Sep 17 00:00:00 2001 From: Gannon McGibbon Date: Thu, 18 Feb 2021 13:17:08 -0500 Subject: [PATCH 166/244] Prevent string polymorphic route arguments url_for supports building polymorphic URLs via an array of arguments (usually symbols and records). If an array is passed, strings can result in unwanted route helper calls. CVE-2021-22885 --- actionpack/CHANGELOG.md | 10 +++++ .../routing/polymorphic_routes.rb | 12 +++-- actionpack/test/controller/redirect_test.rb | 45 +++++++++++++++++++ .../activerecord/polymorphic_routes_test.rb | 22 ++++++--- 4 files changed, 79 insertions(+), 10 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 351edd929faeb..d2cca9cade02b 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,13 @@ +* Prevent string polymorphic route arguments. + + `url_for` supports building polymorphic URLs via an array + of arguments (usually symbols and records). If a developer passes a + user input array, strings can result in unwanted route helper calls. + + CVE-2021-22885 + + *Gannon McGibbon* + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index e3322e99ab8fb..6f0f5c45110a4 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -286,10 +286,12 @@ def handle_list(list) args = [] - route = record_list.map { |parent| + route = record_list.map do |parent| case parent - when Symbol, String + when Symbol parent.to_s + when String + raise(ArgumentError, "Please use symbols for polymorphic route arguments.") when Class args << parent parent.model_name.singular_route_key @@ -297,12 +299,14 @@ def handle_list(list) args << parent.to_model parent.to_model.model_name.singular_route_key end - } + end route << case record - when Symbol, String + when Symbol record.to_s + when String + raise(ArgumentError, "Please use symbols for polymorphic route arguments.") when Class @key_strategy.call record.model_name else diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 7f1c41787ab94..e218ef35e483b 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -116,6 +116,14 @@ def redirect_to_nil redirect_to nil end + def redirect_to_polymorphic + redirect_to [:internal, Workshop.new(5)] + end + + def redirect_to_polymorphic_string_args + redirect_to ["internal", Workshop.new(5)] + end + def redirect_to_params redirect_to ActionController::Parameters.new(status: 200, protocol: "javascript", f: "%0Aeval(name)") end @@ -346,6 +354,43 @@ def test_redirect_to_record end end + def test_polymorphic_redirect + with_routing do |set| + set.draw do + namespace :internal do + resources :workshops + end + + ActiveSupport::Deprecation.silence do + get ":controller/:action" + end + end + + get :redirect_to_polymorphic + assert_equal "http://test.host/internal/workshops/5", redirect_to_url + assert_redirected_to [:internal, Workshop.new(5)] + end + end + + def test_polymorphic_redirect_with_string_args + with_routing do |set| + set.draw do + namespace :internal do + resources :workshops + end + + ActiveSupport::Deprecation.silence do + get ":controller/:action" + end + end + + error = assert_raises(ArgumentError) do + get :redirect_to_polymorphic_string_args + end + assert_equal("Please use symbols for polymorphic route arguments.", error.message) + end + end + def test_redirect_to_nil error = assert_raise(ActionController::ActionControllerError) do get :redirect_to_nil diff --git a/actionview/test/activerecord/polymorphic_routes_test.rb b/actionview/test/activerecord/polymorphic_routes_test.rb index 724129a7d92e2..3ae3c26ecda31 100644 --- a/actionview/test/activerecord/polymorphic_routes_test.rb +++ b/actionview/test/activerecord/polymorphic_routes_test.rb @@ -464,12 +464,6 @@ def test_with_array_containing_single_name end end - def test_with_array_containing_single_string_name - with_test_routes do - assert_url "http://example.com/projects", ["projects"] - end - end - def test_with_array_containing_symbols with_test_routes do assert_url "http://example.com/series/new", [:new, :series] @@ -624,6 +618,22 @@ def test_nested_routing_to_a_model_delegate end end + def test_string_route_arguments + with_admin_test_routes do + error = assert_raises(ArgumentError) do + polymorphic_url(["admin", @project]) + end + + assert_equal("Please use symbols for polymorphic route arguments.", error.message) + + error = assert_raises(ArgumentError) do + polymorphic_url([@project, "bid"]) + end + + assert_equal("Please use symbols for polymorphic route arguments.", error.message) + end + end + def with_namespaced_routes(name) with_routing do |set| set.draw do From d861fa8ade353390c4419b53a6c6b41f3005b1f2 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 4 May 2021 15:49:21 -0700 Subject: [PATCH 167/244] Prevent slow regex when parsing host authorization header The old regex could take too long when parsing an authorization header, and this could potentially cause a DoS vulnerability [CVE-2021-22904] --- .../lib/action_controller/metal/http_authentication.rb | 2 +- .../test/controller/http_token_authentication_test.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 6a274d35cb64d..97cafbe46fa47 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -405,7 +405,7 @@ def opaque(secret_key) module Token TOKEN_KEY = "token=" TOKEN_REGEX = /^(Token|Bearer)\s+/ - AUTHN_PAIR_DELIMITERS = /(?:,|;|\t+)/ + AUTHN_PAIR_DELIMITERS = /(?:,|;|\t)/ extend self module ControllerMethods diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb index 57b78154bc54e..23d83609b92ad 100644 --- a/actionpack/test/controller/http_token_authentication_test.rb +++ b/actionpack/test/controller/http_token_authentication_test.rb @@ -88,6 +88,16 @@ def authenticate_long_credentials assert_equal "HTTP Token: Access denied.\n", @response.body, "Authentication header was not properly parsed" end + test "authentication request with evil header" do + @request.env["HTTP_AUTHORIZATION"] = "Token ." + " " * (1024*80-8) + "." + Timeout.timeout(1) do + get :index + end + + assert_response :unauthorized + assert_equal "HTTP Token: Access denied.\n", @response.body, "Authentication header was not properly parsed" + end + test "successful authentication request with Bearer instead of Token" do @request.env["HTTP_AUTHORIZATION"] = "Bearer lifo" get :index From 59b45665c05f2f1824dccaafea96423edd7b0018 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 4 May 2021 16:40:42 -0700 Subject: [PATCH 168/244] update changelog --- RAILS_VERSION | 2 +- actioncable/CHANGELOG.md | 10 ++++++++++ actionmailbox/CHANGELOG.md | 5 +++++ actionmailer/CHANGELOG.md | 5 +++++ actionpack/CHANGELOG.md | 8 ++++++++ actiontext/CHANGELOG.md | 5 +++++ actionview/CHANGELOG.md | 5 +++++ activejob/CHANGELOG.md | 5 +++++ activemodel/CHANGELOG.md | 5 +++++ activerecord/CHANGELOG.md | 5 +++++ activestorage/CHANGELOG.md | 5 +++++ activesupport/CHANGELOG.md | 5 +++++ guides/CHANGELOG.md | 5 +++++ railties/CHANGELOG.md | 5 +++++ 14 files changed, 74 insertions(+), 1 deletion(-) diff --git a/RAILS_VERSION b/RAILS_VERSION index 1acaa6c773b67..9e9b283f592cd 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.3.6 +6.0.3.7 diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index d98edcd24fb1a..deab859183f53 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,13 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + +## Rails 6.0.3.6 (May 04, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index 29c90dac487db..2a4da6c94ced5 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index a13858bd35166..6ddfe98faaf13 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index d2cca9cade02b..2f2772597362c 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,11 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* Prevent catastrophic backtracking during mime parsing + CVE-2021-22902 + +* Prevent regex DoS in HTTP token authentication + CVE-2021-22904 + * Prevent string polymorphic route arguments. `url_for` supports building polymorphic URLs via an array diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 5b1972b72fb4d..89a74a3d434c5 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 3381c199c221f..8758d4729549b 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index bbde6ec43ace2..b2f338cf2de98 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 51559f4083dd4..0c4038ac7109c 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 47739dae0e3d6..3b18892c6aff7 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 635f42868cbd1..0497bb8e54878 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * Marcel is upgraded to version 1.0.0 to avoid a dependency on GPL-licensed diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 598c90aec3308..29ecc72b96b83 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index ee168ed404fd0..42d1b2558b7a9 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index dd39e306d10df..b3d03f838e3c4 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.3.7 (May 05, 2021) ## + +* No changes. + + ## Rails 6.0.3.6 (March 26, 2021) ## * No changes. From c04aff675d4cd3e8a54e0008dbfca10a8832a414 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 5 May 2021 09:01:04 -0700 Subject: [PATCH 169/244] Preparing for 6.0.3.7 release --- Gemfile.lock | 108 +++++++++--------- actioncable/lib/action_cable/gem_version.rb | 2 +- actioncable/package.json | 2 +- .../lib/action_mailbox/gem_version.rb | 2 +- actionmailer/lib/action_mailer/gem_version.rb | 2 +- actionpack/lib/action_pack/gem_version.rb | 2 +- actiontext/lib/action_text/gem_version.rb | 2 +- actiontext/package.json | 2 +- actionview/lib/action_view/gem_version.rb | 2 +- actionview/package.json | 2 +- activejob/lib/active_job/gem_version.rb | 2 +- activemodel/lib/active_model/gem_version.rb | 2 +- activerecord/lib/active_record/gem_version.rb | 2 +- .../lib/active_storage/gem_version.rb | 2 +- activestorage/package.json | 2 +- .../lib/active_support/gem_version.rb | 2 +- railties/lib/rails/gem_version.rb | 2 +- version.rb | 2 +- 18 files changed, 72 insertions(+), 70 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 42f301a89118c..a54b260fa640e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,79 +17,79 @@ GIT PATH remote: . specs: - actioncable (6.0.3.6) - actionpack (= 6.0.3.6) + actioncable (6.0.3.7) + actionpack (= 6.0.3.7) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.3.6) - actionpack (= 6.0.3.6) - activejob (= 6.0.3.6) - activerecord (= 6.0.3.6) - activestorage (= 6.0.3.6) - activesupport (= 6.0.3.6) + actionmailbox (6.0.3.7) + actionpack (= 6.0.3.7) + activejob (= 6.0.3.7) + activerecord (= 6.0.3.7) + activestorage (= 6.0.3.7) + activesupport (= 6.0.3.7) mail (>= 2.7.1) - actionmailer (6.0.3.6) - actionpack (= 6.0.3.6) - actionview (= 6.0.3.6) - activejob (= 6.0.3.6) + actionmailer (6.0.3.7) + actionpack (= 6.0.3.7) + actionview (= 6.0.3.7) + activejob (= 6.0.3.7) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.3.6) - actionview (= 6.0.3.6) - activesupport (= 6.0.3.6) + actionpack (6.0.3.7) + actionview (= 6.0.3.7) + activesupport (= 6.0.3.7) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.3.6) - actionpack (= 6.0.3.6) - activerecord (= 6.0.3.6) - activestorage (= 6.0.3.6) - activesupport (= 6.0.3.6) + actiontext (6.0.3.7) + actionpack (= 6.0.3.7) + activerecord (= 6.0.3.7) + activestorage (= 6.0.3.7) + activesupport (= 6.0.3.7) nokogiri (>= 1.8.5) - actionview (6.0.3.6) - activesupport (= 6.0.3.6) + actionview (6.0.3.7) + activesupport (= 6.0.3.7) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.3.6) - activesupport (= 6.0.3.6) + activejob (6.0.3.7) + activesupport (= 6.0.3.7) globalid (>= 0.3.6) - activemodel (6.0.3.6) - activesupport (= 6.0.3.6) - activerecord (6.0.3.6) - activemodel (= 6.0.3.6) - activesupport (= 6.0.3.6) - activestorage (6.0.3.6) - actionpack (= 6.0.3.6) - activejob (= 6.0.3.6) - activerecord (= 6.0.3.6) + activemodel (6.0.3.7) + activesupport (= 6.0.3.7) + activerecord (6.0.3.7) + activemodel (= 6.0.3.7) + activesupport (= 6.0.3.7) + activestorage (6.0.3.7) + actionpack (= 6.0.3.7) + activejob (= 6.0.3.7) + activerecord (= 6.0.3.7) marcel (~> 1.0.0) - activesupport (6.0.3.6) + activesupport (6.0.3.7) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.3.6) - actioncable (= 6.0.3.6) - actionmailbox (= 6.0.3.6) - actionmailer (= 6.0.3.6) - actionpack (= 6.0.3.6) - actiontext (= 6.0.3.6) - actionview (= 6.0.3.6) - activejob (= 6.0.3.6) - activemodel (= 6.0.3.6) - activerecord (= 6.0.3.6) - activestorage (= 6.0.3.6) - activesupport (= 6.0.3.6) + rails (6.0.3.7) + actioncable (= 6.0.3.7) + actionmailbox (= 6.0.3.7) + actionmailer (= 6.0.3.7) + actionpack (= 6.0.3.7) + actiontext (= 6.0.3.7) + actionview (= 6.0.3.7) + activejob (= 6.0.3.7) + activemodel (= 6.0.3.7) + activerecord (= 6.0.3.7) + activestorage (= 6.0.3.7) + activesupport (= 6.0.3.7) bundler (>= 1.3.0) - railties (= 6.0.3.6) + railties (= 6.0.3.7) sprockets-rails (>= 2.0.0) - railties (6.0.3.6) - actionpack (= 6.0.3.6) - activesupport (= 6.0.3.6) + railties (6.0.3.7) + actionpack (= 6.0.3.7) + activesupport (= 6.0.3.7) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -274,7 +274,7 @@ GEM hiredis (0.6.3-java) http_parser.rb (0.6.0) httpclient (2.8.3) - i18n (1.8.8) + i18n (1.8.10) concurrent-ruby (~> 1.0) image_processing (1.10.0) mini_magick (>= 4.9.5, < 5) @@ -295,12 +295,12 @@ GEM listen (3.2.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.9.0) + loofah (2.9.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (1.0.0) + marcel (1.0.1) memoist (0.16.2) method_source (1.0.0) mini_magick (4.9.5) @@ -518,6 +518,8 @@ GEM websocket (1.2.8) websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) + websocket-driver (0.7.1-java) + websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) xpath (3.2.0) nokogiri (~> 1.8) diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index aecff2e6e1eb6..aab198eb5ccdd 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index 39fb130749d15..e77894f9053a1 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.3-6", + "version": "6.0.3-7", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index 71e9844a89ecc..3da8d3d89da38 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index 7963aa49e658a..50922fb389c40 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index 9a8a0b87e8de5..c0116b1e2aa80 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index 2407f4fb9f92a..65bbb2bed1814 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index c92ce54f3e8f0..bf3aec606871a 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.3-6", + "version": "6.0.3-7", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index e08d84b48131b..2a919e1922b95 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 318f6d72c4cb6..cd95349497afc 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.3-6", + "version": "6.0.3-7", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index f445536eb5314..54ed2cdd15006 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index 4df3adfd4212e..9b6f6ce496aa3 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index 8027676474a38..a70f951166383 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index 28d4b33ab6376..11038732196fe 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index 7a6ef965264eb..596dfa36353f2 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.3-6", + "version": "6.0.3-7", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 3b247c0c305e3..391dd6926a6d9 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index aa12023425413..98617cf6b7ca5 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index aa12023425413..98617cf6b7ca5 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 3 - PRE = "6" + PRE = "7" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From ef97441036e0ebbe1aa2108d59c408707f998ffd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 4 May 2021 15:23:36 -0700 Subject: [PATCH 170/244] Escape allow list hosts correctly [CVE-2021-22903] --- .../action_dispatch/middleware/host_authorization.rb | 2 +- actionpack/test/dispatch/host_authorization_test.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index 19562f0100591..ad209c2669bca 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -48,7 +48,7 @@ def sanitize_string(host) if host.start_with?(".") /\A(.+\.)?#{Regexp.escape(host[1..-1])}\z/i else - /\A#{host}\z/i + /\A#{Regexp.escape host}\z/i end end end diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb index 784b06eb3c0c0..4a39747f8d695 100644 --- a/actionpack/test/dispatch/host_authorization_test.rb +++ b/actionpack/test/dispatch/host_authorization_test.rb @@ -213,4 +213,15 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_response :forbidden assert_match "Blocked host: example.com#sub.example.com", response.body end + + test "blocks requests to similar host" do + @app = ActionDispatch::HostAuthorization.new(App, "sub.example.com") + + get "/", env: { + "HOST" => "sub-example.com", + } + + assert_response :forbidden + assert_match "Blocked host: sub-example.com", response.body + end end From 72a0eea37223a71b9695fd75f82fdf60ec99764e Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Fri, 28 May 2021 12:14:52 +0200 Subject: [PATCH 171/244] Merge pull request #42308 from Shopify/fix-ruby-head-builds Add net-smtp and matrix to the Gemfile to fix the ruby-head build --- Gemfile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Gemfile b/Gemfile index d5ae76288b8f6..c41d6d0b37735 100644 --- a/Gemfile +++ b/Gemfile @@ -165,3 +165,15 @@ end gem "ibm_db" if ENV["IBM_DB"] gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] gem "wdm", ">= 0.1.0", platforms: [:mingw, :mswin, :x64_mingw, :mswin64] + +if RUBY_VERSION >= "3.1" + # net-smtp, net-imap and net-pop were removed from default gems in Ruby 3.1, but is used by the `mail` gem. + # So we need to add them as dependencies until `mail` is fixed: https://github.com/mikel/mail/pull/1439 + gem "net-smtp", require: false + gem "net-imap", require: false + gem "net-pop", require: false + + # matrix was removed from default gems in Ruby 3.1, but is used by the `capybara` gem. + # So we need to add it as a dependency until `capybara` is fixed: https://github.com/teamcapybara/capybara/pull/2468 + gem "matrix", require: false +end From 7b5d0b9c057d346e259ec3df9bdc7369376c0005 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 23 Feb 2021 21:13:55 +0900 Subject: [PATCH 172/244] Merge pull request #41528 from yahonda/pg_where_with_set Address CI failure due to non-determined sort order --- activerecord/test/cases/relations_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index a3cca5972b380..950e5d40867ac 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -2134,7 +2134,7 @@ def test_find_by_with_take_memoization mary = authors(:mary) authors = Author.where(name: ["David", "Mary"].to_set) - assert_equal [david, mary], authors + assert_equal [david, mary], authors.order(:id) end test "#where with empty set" do From b869a4e3a6e06c8d741ebf48faecfed6afb550a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Wed, 9 Jun 2021 22:24:30 -0400 Subject: [PATCH 173/244] Merge pull request #42244 from hahmed/fix-invalid-statement-compile-error Fix invalid statement template compile error --- .../rescues/invalid_statement.text.erb | 1 + .../application/middleware/exceptions_test.rb | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb index 16c3ecc331d04..99260e54a7497 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb @@ -6,6 +6,7 @@ <%= @exception.message %> <% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %> To resolve this issue run: rails active_storage:install +<% end %> <% if defined?(ActionMailbox) && @exception.message.match?(%r{#{ActionMailbox::InboundEmail.table_name}}) %> To resolve this issue run: rails action_mailbox:install <% end %> diff --git a/railties/test/application/middleware/exceptions_test.rb b/railties/test/application/middleware/exceptions_test.rb index 87529c951c0a7..201cd40c90013 100644 --- a/railties/test/application/middleware/exceptions_test.rb +++ b/railties/test/application/middleware/exceptions_test.rb @@ -157,5 +157,28 @@ def index assert_equal 400, last_response.status assert_match "Invalid query parameters", last_response.body end + + test "displays statement invalid template correctly" do + controller :foo, <<-RUBY + class FooController < ActionController::Base + def index + raise ActiveRecord::StatementInvalid + end + end + RUBY + app.config.action_dispatch.show_exceptions = true + app.config.consider_all_requests_local = true + app.config.action_dispatch.ignore_accept_header = false + + get "/foo" + assert_equal 500, last_response.status + assert_match "Action Controller: Exception caught", last_response.body + assert_match "ActiveRecord::StatementInvalid", last_response.body + + get "/foo", {}, { "HTTP_ACCEPT" => "text/plain", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest" } + assert_equal 500, last_response.status + assert_equal "text/plain", last_response.media_type + assert_match "ActiveRecord::StatementInvalid", last_response.body + end end end From 11a35e396faa640d8cbc9f75feb297794b91c1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 15 Jun 2021 19:06:49 +0000 Subject: [PATCH 174/244] Update CHANGELOG --- activerecord/CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 6a4645701d3a0..a3cca6b101163 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -16,6 +16,10 @@ *Ryuta Kamizono* +* Type cast extra select for eager loading. + + *Ryuta Kamizono* + * Prevent collection associations from being autosaved multiple times. Fixes #39173. @@ -43,6 +47,14 @@ *Austen Madden* +* Fix preloading for polymorphic association with custom scope. + + *Ryuta Kamizono* + +* Allow relations with different SQL comments in the `or` method. + + *Takumi Shotoku* + * Resolve conflict between counter cache and optimistic locking. Bump an Active Record instance's lock version after updating its counter @@ -54,10 +66,43 @@ *Aaron Lipman* +* Fix through association with source/through scope which has joins. + + *Ryuta Kamizono* + +* Fix through association to respect source scope for includes/preload. + + *Ryuta Kamizono* + +* Fix eager load with Arel joins to maintain the original joins order. + + *Ryuta Kamizono* + +* Fix group by count with eager loading + order + limit/offset. + + *Ryuta Kamizono* + +* Fix left joins order when merging multiple left joins from different associations. + + *Ryuta Kamizono* + * Fix index creation to preserve index comment in bulk change table on MySQL. *Ryuta Kamizono* +* Change `remove_foreign_key` to not check `:validate` option if database + doesn't support the feature. + + *Ryuta Kamizono* + +* Fix the result of aggregations to maintain duplicated "group by" fields. + + *Ryuta Kamizono* + +* Do not return duplicated records when using preload. + + *Bogdan Gusiev* + ## Rails 6.0.3.7 (May 05, 2021) ## From 6e721d79ba9458317c93bb02590bbaa25c5a3649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 15 Jun 2021 20:14:03 +0000 Subject: [PATCH 175/244] Preparing for 6.0.4 release --- Gemfile.lock | 107 +++++++++--------- RAILS_VERSION | 2 +- actioncable/CHANGELOG.md | 5 + actioncable/lib/action_cable/gem_version.rb | 4 +- actioncable/package.json | 2 +- actionmailbox/CHANGELOG.md | 5 + .../lib/action_mailbox/gem_version.rb | 4 +- actionmailer/CHANGELOG.md | 5 + actionmailer/lib/action_mailer/gem_version.rb | 4 +- actionpack/CHANGELOG.md | 2 + actionpack/lib/action_pack/gem_version.rb | 4 +- actiontext/CHANGELOG.md | 5 + actiontext/lib/action_text/gem_version.rb | 4 +- actiontext/package.json | 2 +- actionview/CHANGELOG.md | 2 + actionview/lib/action_view/gem_version.rb | 4 +- actionview/package.json | 2 +- activejob/CHANGELOG.md | 5 + activejob/lib/active_job/gem_version.rb | 4 +- activemodel/CHANGELOG.md | 5 + activemodel/lib/active_model/gem_version.rb | 4 +- activerecord/CHANGELOG.md | 2 + activerecord/lib/active_record/gem_version.rb | 4 +- activestorage/CHANGELOG.md | 2 + .../lib/active_storage/gem_version.rb | 4 +- activestorage/package.json | 2 +- activesupport/CHANGELOG.md | 2 + .../lib/active_support/gem_version.rb | 4 +- guides/CHANGELOG.md | 5 + railties/CHANGELOG.md | 2 + railties/lib/rails/gem_version.rb | 4 +- version.rb | 4 +- 32 files changed, 134 insertions(+), 82 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6bd3034fc52e6..618f8782394fc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,79 +32,79 @@ GIT PATH remote: . specs: - actioncable (6.0.3.7) - actionpack (= 6.0.3.7) + actioncable (6.0.4) + actionpack (= 6.0.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.3.7) - actionpack (= 6.0.3.7) - activejob (= 6.0.3.7) - activerecord (= 6.0.3.7) - activestorage (= 6.0.3.7) - activesupport (= 6.0.3.7) + actionmailbox (6.0.4) + actionpack (= 6.0.4) + activejob (= 6.0.4) + activerecord (= 6.0.4) + activestorage (= 6.0.4) + activesupport (= 6.0.4) mail (>= 2.7.1) - actionmailer (6.0.3.7) - actionpack (= 6.0.3.7) - actionview (= 6.0.3.7) - activejob (= 6.0.3.7) + actionmailer (6.0.4) + actionpack (= 6.0.4) + actionview (= 6.0.4) + activejob (= 6.0.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.3.7) - actionview (= 6.0.3.7) - activesupport (= 6.0.3.7) + actionpack (6.0.4) + actionview (= 6.0.4) + activesupport (= 6.0.4) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.3.7) - actionpack (= 6.0.3.7) - activerecord (= 6.0.3.7) - activestorage (= 6.0.3.7) - activesupport (= 6.0.3.7) + actiontext (6.0.4) + actionpack (= 6.0.4) + activerecord (= 6.0.4) + activestorage (= 6.0.4) + activesupport (= 6.0.4) nokogiri (>= 1.8.5) - actionview (6.0.3.7) - activesupport (= 6.0.3.7) + actionview (6.0.4) + activesupport (= 6.0.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.3.7) - activesupport (= 6.0.3.7) + activejob (6.0.4) + activesupport (= 6.0.4) globalid (>= 0.3.6) - activemodel (6.0.3.7) - activesupport (= 6.0.3.7) - activerecord (6.0.3.7) - activemodel (= 6.0.3.7) - activesupport (= 6.0.3.7) - activestorage (6.0.3.7) - actionpack (= 6.0.3.7) - activejob (= 6.0.3.7) - activerecord (= 6.0.3.7) + activemodel (6.0.4) + activesupport (= 6.0.4) + activerecord (6.0.4) + activemodel (= 6.0.4) + activesupport (= 6.0.4) + activestorage (6.0.4) + actionpack (= 6.0.4) + activejob (= 6.0.4) + activerecord (= 6.0.4) marcel (~> 1.0.0) - activesupport (6.0.3.7) + activesupport (6.0.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.3.7) - actioncable (= 6.0.3.7) - actionmailbox (= 6.0.3.7) - actionmailer (= 6.0.3.7) - actionpack (= 6.0.3.7) - actiontext (= 6.0.3.7) - actionview (= 6.0.3.7) - activejob (= 6.0.3.7) - activemodel (= 6.0.3.7) - activerecord (= 6.0.3.7) - activestorage (= 6.0.3.7) - activesupport (= 6.0.3.7) + rails (6.0.4) + actioncable (= 6.0.4) + actionmailbox (= 6.0.4) + actionmailer (= 6.0.4) + actionpack (= 6.0.4) + actiontext (= 6.0.4) + actionview (= 6.0.4) + activejob (= 6.0.4) + activemodel (= 6.0.4) + activerecord (= 6.0.4) + activestorage (= 6.0.4) + activesupport (= 6.0.4) bundler (>= 1.3.0) - railties (= 6.0.3.7) + railties (= 6.0.4) sprockets-rails (>= 2.0.0) - railties (6.0.3.7) - actionpack (= 6.0.3.7) - activesupport (= 6.0.3.7) + railties (6.0.4) + actionpack (= 6.0.4) + activesupport (= 6.0.4) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -292,7 +292,7 @@ GEM mustache nokogiri libxml-ruby (3.2.1) - loofah (2.9.1) + loofah (2.10.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -302,6 +302,7 @@ GEM method_source (1.0.0) mini_magick (4.11.0) mini_mime (1.1.0) + mini_portile2 (2.5.3) minitest (5.14.4) minitest-bisect (1.5.1) minitest-server (~> 1.0) @@ -324,6 +325,9 @@ GEM ruby2_keywords (~> 0.0.1) mysql2 (0.5.3) nio4r (2.5.7) + nokogiri (1.11.3) + mini_portile2 (~> 2.5.0) + racc (~> 1.4) nokogiri (1.11.3-x86_64-darwin) racc (~> 1.4) os (1.1.1) @@ -506,6 +510,7 @@ GEM zeitwerk (2.4.2) PLATFORMS + ruby x86_64-darwin-19 DEPENDENCIES diff --git a/RAILS_VERSION b/RAILS_VERSION index 9e9b283f592cd..1aa5e414fd3ab 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.3.7 +6.0.4 diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index deab859183f53..765a1838c50ea 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4 (June 15, 2021) ## + +* No changes. + + ## Rails 6.0.3.7 (May 05, 2021) ## * No changes. diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index aab198eb5ccdd..e33ab30a47ff1 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index e77894f9053a1..04178e1b9e3c3 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.3-7", + "version": "6.0.4", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index 2a4da6c94ced5..b2765850d232a 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4 (June 15, 2021) ## + +* No changes. + + ## Rails 6.0.3.7 (May 05, 2021) ## * No changes. diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index 3da8d3d89da38..1c744791054e9 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 6ddfe98faaf13..cc02c73fc77aa 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4 (June 15, 2021) ## + +* No changes. + + ## Rails 6.0.3.7 (May 05, 2021) ## * No changes. diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index 50922fb389c40..6c6a90fbf5124 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 824e0799680ee..016ecc4b78265 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 6.0.4 (June 15, 2021) ## + * Accept base64_urlsafe CSRF tokens to make forward compatible. Base64 strict-encoded CSRF tokens are not inherently websafe, which makes diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index c0116b1e2aa80..c9c71ef934d5d 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 89a74a3d434c5..dd7d3962118ce 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4 (June 15, 2021) ## + +* No changes. + + ## Rails 6.0.3.7 (May 05, 2021) ## * No changes. diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index 65bbb2bed1814..e2ac85e7cf446 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index 8fd3d878dc012..9156639bbb4a4 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.3-7", + "version": "6.0.4", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 967676b708100..b5172afd57e65 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 6.0.4 (June 15, 2021) ## + * SanitizeHelper.sanitized_allowed_attributes and SanitizeHelper.sanitized_allowed_tags call safe_list_sanitizer's class method diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 2a919e1922b95..832d02d90e83e 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 52df48f4d8bf1..5256b6e677768 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.3-7", + "version": "6.0.4", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index b2f338cf2de98..2a2c9049d0f98 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4 (June 15, 2021) ## + +* No changes. + + ## Rails 6.0.3.7 (May 05, 2021) ## * No changes. diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index 54ed2cdd15006..ba6226992ad75 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 0c4038ac7109c..0b1cfa7aeebbf 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4 (June 15, 2021) ## + +* No changes. + + ## Rails 6.0.3.7 (May 05, 2021) ## * No changes. diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index 9b6f6ce496aa3..afeb94f5d685b 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index a3cca6b101163..e00429ce1cbfc 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 6.0.4 (June 15, 2021) ## + * Only warn about negative enums if a positive form that would cause conflicts exists. Fixes #39065. diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index a70f951166383..a8116e3590b0f 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 595b0ddbf55c4..2feefc3d73910 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 6.0.4 (June 15, 2021) ## + * The Poppler PDF previewer renders a preview image using the original document's crop box rather than its media box, hiding print margins. This matches the behavior of the MuPDF previewer. diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index 11038732196fe..aca30742bb78e 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index 596dfa36353f2..bacc1732bc5ba 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.3-7", + "version": "6.0.4", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index a9e0b35178447..0a780d6d228c1 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 6.0.4 (June 15, 2021) ## + * Fixed issue in `ActiveSupport::Cache::RedisCacheStore` not passing options to `read_multi` causing `fetch_multi` to not work properly. diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 391dd6926a6d9..45099914a675d 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index 42d1b2558b7a9..412dbe29a6044 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4 (June 15, 2021) ## + +* No changes. + + ## Rails 6.0.3.7 (May 05, 2021) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 1a77f93a0c4bc..d2ebd0cae626e 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 6.0.4 (June 15, 2021) ## + * Allow relative paths with trailing slashes to be passed to `rails test`. *Eugene Kenny* diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index 98617cf6b7ca5..acf9ef48d8d13 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index 98617cf6b7ca5..acf9ef48d8d13 100644 --- a/version.rb +++ b/version.rb @@ -9,8 +9,8 @@ def self.gem_version module VERSION MAJOR = 6 MINOR = 0 - TINY = 3 - PRE = "7" + TINY = 4 + PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From 3e6ac87136ef2ff6766af2ab468da48dbae6ae9e Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Fri, 11 Sep 2020 11:43:27 -0500 Subject: [PATCH 176/244] Backport: Disentangle Action Text from ApplicationController The original commit was merged to the 6.1-stable branch. It also fixes #36810 on the 6.0-stable branch. Original commit message: This commit allows Action Text to be used without having an ApplicationController defined. In doing so, it also fixes Action Text attachments to render the correct URL host in mailers. It also avoids allocating an ActionController::Renderer per request. Co-authored-by: Jeremy Daer --- actionpack/lib/action_controller/renderer.rb | 1 + actiontext/CHANGELOG.md | 11 +++++++ .../app/helpers/action_text/content_helper.rb | 1 + actiontext/lib/action_text.rb | 1 + .../attachments/trix_conversion.rb | 2 +- actiontext/lib/action_text/content.rb | 8 ++--- actiontext/lib/action_text/engine.rb | 21 ++++++++------ actiontext/lib/action_text/rendering.rb | 29 +++++++++++++++++++ .../controllers/admin/messages_controller.rb | 5 ++++ .../app/controllers/application_controller.rb | 2 -- .../app/controllers/messages_controller.rb | 2 +- .../test/dummy/app/mailers/messages_mailer.rb | 6 ++++ .../app/views/admin/messages/show.html.erb | 16 ++++++++++ .../app/views/layouts/application.html.erb | 3 -- .../dummy/app/views/messages/show.html.erb | 9 ++---- .../messages_mailer/notification.html.erb | 1 + actiontext/test/dummy/config/routes.rb | 5 +++- .../integration/controller_render_test.rb | 24 +++++++++++++++ .../test/integration/mailer_render_test.rb | 23 +++++++++++++++ actiontext/test/unit/content_test.rb | 9 ++++++ actionview/lib/action_view/base.rb | 2 +- 21 files changed, 150 insertions(+), 31 deletions(-) create mode 100644 actiontext/lib/action_text/rendering.rb create mode 100644 actiontext/test/dummy/app/controllers/admin/messages_controller.rb delete mode 100644 actiontext/test/dummy/app/controllers/application_controller.rb create mode 100644 actiontext/test/dummy/app/mailers/messages_mailer.rb create mode 100644 actiontext/test/dummy/app/views/admin/messages/show.html.erb create mode 100644 actiontext/test/dummy/app/views/messages_mailer/notification.html.erb create mode 100644 actiontext/test/integration/controller_render_test.rb create mode 100644 actiontext/test/integration/mailer_render_test.rb diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb index dadf6d3445ea8..43762cdcbd4b5 100644 --- a/actionpack/lib/action_controller/renderer.rb +++ b/actionpack/lib/action_controller/renderer.rb @@ -95,6 +95,7 @@ def render(*args) instance.set_response! controller.make_response!(request) instance.render_to_string(*args) end + alias_method :render_to_string, :render # :nodoc: private def normalize_keys(env) diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index dd7d3962118ce..6ea7a901b030a 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,14 @@ +* Disentangle Action Text from ApplicationController + + Allow Action Text to be used without having an ApplicationController + defined. + This makes sure: + * Action Text attachments render the correct URL host in mailers. + * an ActionController::Renderer isn't allocated per request. + * Sidekiq doesn't hang with the "classic" autoloader. + + *Jonathan Hefner* + ## Rails 6.0.4 (June 15, 2021) ## * No changes. diff --git a/actiontext/app/helpers/action_text/content_helper.rb b/actiontext/app/helpers/action_text/content_helper.rb index 1e05f572f7262..7040fe4e48d6d 100644 --- a/actiontext/app/helpers/action_text/content_helper.rb +++ b/actiontext/app/helpers/action_text/content_helper.rb @@ -10,6 +10,7 @@ module ContentHelper mattr_accessor(:scrubber) def render_action_text_content(content) + self.prefix_partial_path_with_controller_namespace = false sanitize_action_text_content(render_action_text_attachments(content)) end diff --git a/actiontext/lib/action_text.rb b/actiontext/lib/action_text.rb index 0dd6318f89e02..15fdf70b3bae2 100644 --- a/actiontext/lib/action_text.rb +++ b/actiontext/lib/action_text.rb @@ -16,6 +16,7 @@ module ActionText autoload :Fragment autoload :HtmlConversion autoload :PlainTextConversion + autoload :Rendering autoload :Serialization autoload :TrixAttachment diff --git a/actiontext/lib/action_text/attachments/trix_conversion.rb b/actiontext/lib/action_text/attachments/trix_conversion.rb index 24937d6c2276d..a95843a641228 100644 --- a/actiontext/lib/action_text/attachments/trix_conversion.rb +++ b/actiontext/lib/action_text/attachments/trix_conversion.rb @@ -26,7 +26,7 @@ def to_trix_attachment(content = trix_attachment_content) private def trix_attachment_content if partial_path = attachable.try(:to_trix_content_attachment_partial_path) - ActionText::Content.renderer.render(partial: partial_path, object: self, as: model_name.element) + ActionText::Content.render(partial: partial_path, object: self, as: model_name.element) end end end diff --git a/actiontext/lib/action_text/content.rb b/actiontext/lib/action_text/content.rb index 16bc6fe03102c..6126a4de49d50 100644 --- a/actiontext/lib/action_text/content.rb +++ b/actiontext/lib/action_text/content.rb @@ -1,12 +1,8 @@ # frozen_string_literal: true -require "active_support/core_ext/module/attribute_accessors_per_thread" - module ActionText class Content - include Serialization - - thread_cattr_accessor :renderer + include Rendering, Serialization attr_reader :fragment @@ -88,7 +84,7 @@ def to_html end def to_rendered_html_with_layout - renderer.render(partial: "action_text/content/layout", locals: { content: self }) + render partial: "action_text/content/layout", locals: { content: self } end def to_s diff --git a/actiontext/lib/action_text/engine.rb b/actiontext/lib/action_text/engine.rb index 7ac953e6ec28f..4c8a65c6a5bec 100644 --- a/actiontext/lib/action_text/engine.rb +++ b/actiontext/lib/action_text/engine.rb @@ -37,21 +37,24 @@ def to_trix_content_attachment_partial_path end initializer "action_text.helper" do - ActiveSupport.on_load(:action_controller_base) do - helper ActionText::Engine.helpers + %i[action_controller_base action_mailer].each do |abstract_controller| + ActiveSupport.on_load(abstract_controller) do + helper ActionText::Engine.helpers + end end end - initializer "action_text.renderer" do |app| - app.executor.to_run { ActionText::Content.renderer = ApplicationController.renderer } - app.executor.to_complete { ActionText::Content.renderer = ApplicationController.renderer } - + initializer "action_text.renderer" do ActiveSupport.on_load(:action_text_content) do - self.renderer = ApplicationController.renderer + self.renderer = Class.new(ActionController::Base).renderer end - ActiveSupport.on_load(:action_controller_base) do - before_action { ActionText::Content.renderer = ApplicationController.renderer.new(request.env) } + %i[action_controller_base action_mailer].each do |abstract_controller| + ActiveSupport.on_load(abstract_controller) do + around_action do |controller, action| + ActionText::Content.with_renderer(controller, &action) + end + end end end end diff --git a/actiontext/lib/action_text/rendering.rb b/actiontext/lib/action_text/rendering.rb new file mode 100644 index 0000000000000..caef71c6b4838 --- /dev/null +++ b/actiontext/lib/action_text/rendering.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require "active_support/concern" +require "active_support/core_ext/module/attribute_accessors_per_thread" + +module ActionText + module Rendering #:nodoc: + extend ActiveSupport::Concern + + included do + thread_cattr_accessor :renderer, instance_accessor: false + delegate :render, to: :class + end + + class_methods do + def with_renderer(renderer) + previous_renderer = self.renderer + self.renderer = renderer + yield + ensure + self.renderer = previous_renderer + end + + def render(*args, &block) + renderer.render_to_string(*args, &block) + end + end + end +end diff --git a/actiontext/test/dummy/app/controllers/admin/messages_controller.rb b/actiontext/test/dummy/app/controllers/admin/messages_controller.rb new file mode 100644 index 0000000000000..7c3316324b514 --- /dev/null +++ b/actiontext/test/dummy/app/controllers/admin/messages_controller.rb @@ -0,0 +1,5 @@ +class Admin::MessagesController < ActionController::Base + def show + @message = Message.find(params[:id]) + end +end diff --git a/actiontext/test/dummy/app/controllers/application_controller.rb b/actiontext/test/dummy/app/controllers/application_controller.rb deleted file mode 100644 index 09705d12ab4df..0000000000000 --- a/actiontext/test/dummy/app/controllers/application_controller.rb +++ /dev/null @@ -1,2 +0,0 @@ -class ApplicationController < ActionController::Base -end diff --git a/actiontext/test/dummy/app/controllers/messages_controller.rb b/actiontext/test/dummy/app/controllers/messages_controller.rb index 81c79a2d1e304..539468a3599b0 100644 --- a/actiontext/test/dummy/app/controllers/messages_controller.rb +++ b/actiontext/test/dummy/app/controllers/messages_controller.rb @@ -1,4 +1,4 @@ -class MessagesController < ApplicationController +class MessagesController < ActionController::Base before_action :set_message, only: [:show, :edit, :update, :destroy] # GET /messages diff --git a/actiontext/test/dummy/app/mailers/messages_mailer.rb b/actiontext/test/dummy/app/mailers/messages_mailer.rb new file mode 100644 index 0000000000000..ce0af3b3cac45 --- /dev/null +++ b/actiontext/test/dummy/app/mailers/messages_mailer.rb @@ -0,0 +1,6 @@ +class MessagesMailer < ApplicationMailer + def notification + @message = params[:message] + mail to: params[:recipient], subject: "NEW MESSAGE: #{@message.subject}" + end +end diff --git a/actiontext/test/dummy/app/views/admin/messages/show.html.erb b/actiontext/test/dummy/app/views/admin/messages/show.html.erb new file mode 100644 index 0000000000000..ba9067f2018dc --- /dev/null +++ b/actiontext/test/dummy/app/views/admin/messages/show.html.erb @@ -0,0 +1,16 @@ +
    +
    Subject
    +
    + <%= @message.subject %> +
    + +
    Content (Plain Text)
    +
    +
    <%= @message.content.to_plain_text %>
    +
    + +
    Content (HTML)
    +
    +
    <%= @message.content %>
    +
    +
    diff --git a/actiontext/test/dummy/app/views/layouts/application.html.erb b/actiontext/test/dummy/app/views/layouts/application.html.erb index f221f512b7c59..281e4e3063c61 100644 --- a/actiontext/test/dummy/app/views/layouts/application.html.erb +++ b/actiontext/test/dummy/app/views/layouts/application.html.erb @@ -3,9 +3,6 @@ Dummy <%= csrf_meta_tags %> - - <%= stylesheet_link_tag 'application', media: 'all' %> - <%= javascript_pack_tag 'application' %> diff --git a/actiontext/test/dummy/app/views/messages/show.html.erb b/actiontext/test/dummy/app/views/messages/show.html.erb index 25fad1efbaba3..50fa9534212bd 100644 --- a/actiontext/test/dummy/app/views/messages/show.html.erb +++ b/actiontext/test/dummy/app/views/messages/show.html.erb @@ -1,13 +1,8 @@

    <%= notice %>

    -

    - Subject: - <%= @message.subject %> -

    +

    <%= @message.subject %>

    -
    - <%= @message.content.html_safe %> -
    +
    <%= @message.content %>
    <%= link_to 'Edit', edit_message_path(@message) %> | <%= link_to 'Back', messages_path %> diff --git a/actiontext/test/dummy/app/views/messages_mailer/notification.html.erb b/actiontext/test/dummy/app/views/messages_mailer/notification.html.erb new file mode 100644 index 0000000000000..e65604cecf967 --- /dev/null +++ b/actiontext/test/dummy/app/views/messages_mailer/notification.html.erb @@ -0,0 +1 @@ +
    <%= @message.content %>
    diff --git a/actiontext/test/dummy/config/routes.rb b/actiontext/test/dummy/config/routes.rb index 1fc667e2425de..e7b45701e14e2 100644 --- a/actiontext/test/dummy/config/routes.rb +++ b/actiontext/test/dummy/config/routes.rb @@ -1,4 +1,7 @@ Rails.application.routes.draw do resources :messages - # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html + + namespace :admin do + resources :messages, only: [:show] + end end diff --git a/actiontext/test/integration/controller_render_test.rb b/actiontext/test/integration/controller_render_test.rb new file mode 100644 index 0000000000000..2e8812ed88b70 --- /dev/null +++ b/actiontext/test/integration/controller_render_test.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require "test_helper" + +class ActionText::ControllerRenderTest < ActionDispatch::IntegrationTest + test "uses current request environment" do + blob = create_file_blob(filename: "racecar.jpg", content_type: "image/jpg") + message = Message.create!(content: ActionText::Content.new.append_attachables(blob)) + + host! "loocalhoost" + get message_path(message) + assert_select "#content img" do |imgs| + imgs.each { |img| assert_match %r"//loocalhoost/", img["src"] } + end + end + + test "resolves partials when controller is namespaced" do + blob = create_file_blob(filename: "racecar.jpg", content_type: "image/jpg") + message = Message.create!(content: ActionText::Content.new.append_attachables(blob)) + + get admin_message_path(message) + assert_select "#content-html .trix-content .attachment--jpg" + end +end diff --git a/actiontext/test/integration/mailer_render_test.rb b/actiontext/test/integration/mailer_render_test.rb new file mode 100644 index 0000000000000..e787379445025 --- /dev/null +++ b/actiontext/test/integration/mailer_render_test.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require "test_helper" + +class ActionText::MailerRenderTest < ActionMailer::TestCase + test "uses default_url_options" do + original_default_url_options = ActionMailer::Base.default_url_options + ActionMailer::Base.default_url_options = { host: "hoost" } + + blob = create_file_blob(filename: "racecar.jpg", content_type: "image/jpg") + message = Message.new(content: ActionText::Content.new.append_attachables(blob)) + + MessagesMailer.with(recipient: "test", message: message).notification.deliver_now + + assert_select_email do + assert_select "#message-content img" do |imgs| + imgs.each { |img| assert_match %r"//hoost/", img["src"] } + end + end + ensure + ActionMailer::Base.default_url_options = original_default_url_options + end +end diff --git a/actiontext/test/unit/content_test.rb b/actiontext/test/unit/content_test.rb index f77f48df14cb2..c00ad181a5974 100644 --- a/actiontext/test/unit/content_test.rb +++ b/actiontext/test/unit/content_test.rb @@ -107,6 +107,15 @@ class ActionText::ContentTest < ActiveSupport::TestCase assert_equal "
    #{attachment_html}
    ", content_from_html(html).to_html end + test "renders with layout when ApplicationController is not defined" do + html = "

    Hello world

    " + rendered = content_from_html(html).to_rendered_html_with_layout + + assert_includes rendered, html + assert_match %r/\A#{Regexp.escape '
    '}/, rendered + assert_not defined?(::ApplicationController) + end + private def content_from_html(html) ActionText::Content.new(html).tap do |content| diff --git a/actionview/lib/action_view/base.rb b/actionview/lib/action_view/base.rb index e21e7350bca65..e93ce28de23f6 100644 --- a/actionview/lib/action_view/base.rb +++ b/actionview/lib/action_view/base.rb @@ -152,7 +152,7 @@ class Base # Specify whether rendering within namespaced controllers should prefix # the partial paths for ActiveModel objects with the namespace. # (e.g., an Admin::PostsController would render @post using /admin/posts/_post.erb) - cattr_accessor :prefix_partial_path_with_controller_namespace, default: true + class_attribute :prefix_partial_path_with_controller_namespace, default: true # Specify default_formats that can be rendered. cattr_accessor :default_formats From 5c535912d810847334bc7509acb5e60c18386b5c Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Tue, 6 Jul 2021 15:39:10 +0800 Subject: [PATCH 177/244] setup tidb testing --- activerecord/Rakefile | 4 +-- activerecord/test/config.example.yml | 8 +++-- .../test/schema/mysql2_specific_schema.rb | 34 +++++++++++-------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/activerecord/Rakefile b/activerecord/Rakefile index f259ae7e12bc3..e74f2c306e1a8 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -170,7 +170,7 @@ namespace :db do namespace :mysql do connection_arguments = lambda do |connection_name| config = ARTest.config["connections"]["mysql2"][connection_name] - ["--user=#{config["username"]}", "--password=#{config["password"]}", ("--host=#{config["host"]}" if config["host"])].join(" ") + ["--user=#{config["username"]}", "--password=#{config["password"]}", "--port=#{config['port']}", ("--host=#{config["host"]}" if config["host"])].join(" ") end desc "Build the MySQL test databases" @@ -223,4 +223,4 @@ task :lines do load File.expand_path("../tools/line_statistics", __dir__) files = FileList["lib/active_record/**/*.rb"] CodeTools::LineStatistics.new(files).print_loc -end +end \ No newline at end of file diff --git a/activerecord/test/config.example.yml b/activerecord/test/config.example.yml index f5e3ac3c19c59..b43235d4b0a9f 100644 --- a/activerecord/test/config.example.yml +++ b/activerecord/test/config.example.yml @@ -51,14 +51,16 @@ connections: mysql2: arunit: - username: rails + username: <%= ENV["MYSQL_USER"] || 'rails' %> + port: <%= ENV["MYSQL_PORT"] || 3306 %> encoding: utf8mb4 collation: utf8mb4_unicode_ci <% if ENV['MYSQL_HOST'] %> host: <%= ENV['MYSQL_HOST'] %> <% end %> arunit2: - username: rails + username: <%= ENV["MYSQL_USER"] || 'rails' %> + port: <%= ENV["MYSQL_PORT"] || 3306 %> encoding: utf8mb4 collation: utf8mb4_general_ci <% if ENV['MYSQL_HOST'] %> @@ -102,4 +104,4 @@ connections: database: ':memory:' arunit2: adapter: sqlite3 - database: ':memory:' + database: ':memory:' \ No newline at end of file diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb index 911ac808c6a62..04479a6c13ea0 100644 --- a/activerecord/test/schema/mysql2_specific_schema.rb +++ b/activerecord/test/schema/mysql2_specific_schema.rb @@ -62,21 +62,25 @@ t.binary :binary_column, limit: 1 end - execute "DROP PROCEDURE IF EXISTS ten" + if ENV['tidb'] + puts "Skip PROCEDURE test" + else + execute "DROP PROCEDURE IF EXISTS ten" - execute <<~SQL - CREATE PROCEDURE ten() SQL SECURITY INVOKER - BEGIN - SELECT 10; - END - SQL + execute <<~SQL + CREATE PROCEDURE ten() SQL SECURITY INVOKER + BEGIN + SELECT 10; + END + SQL - execute "DROP PROCEDURE IF EXISTS topics" + execute "DROP PROCEDURE IF EXISTS topics" - execute <<~SQL - CREATE PROCEDURE topics(IN num INT) SQL SECURITY INVOKER - BEGIN - SELECT * FROM topics LIMIT num; - END - SQL -end + execute <<~SQL + CREATE PROCEDURE topics(IN num INT) SQL SECURITY INVOKER + BEGIN + SELECT * FROM topics LIMIT num; + END + SQL + end +end \ No newline at end of file From eb5918fd0a700a2186503340f39a184e35a83abc Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Tue, 6 Jul 2021 17:03:29 +0800 Subject: [PATCH 178/244] setup buildkite pipeline --- .buildkite/hooks/pre-command | 10 ++++++++++ .buildkite/pipeline.yml | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100755 .buildkite/hooks/pre-command create mode 100644 .buildkite/pipeline.yml diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command new file mode 100755 index 0000000000000..267c9f333d6a2 --- /dev/null +++ b/.buildkite/hooks/pre-command @@ -0,0 +1,10 @@ +#!/bin/bash + +# Place this in /etc/buildkite-agent/hooks/pre-command +# +# Needs to be `chown buildkite-agent` and `chmod +x` + +# RVM uses unbound variables and will fail without this +set +u + +source /var/lib/buildkite-agent/.rvm/scripts/rvm \ No newline at end of file diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml new file mode 100644 index 0000000000000..c6d360a9cb6d5 --- /dev/null +++ b/.buildkite/pipeline.yml @@ -0,0 +1,19 @@ +env: + tidb: 1 + MYSQL_HOST: 127.0.0.1 + MYSQL_USER: root + MYSQL_PORT: 4000 + +steps: + - command: "bundle config set --local path '.bundle' && bundle config mirror.https://rubygems.org https://gems.ruby-china.com && bundle install" + label: "bundle install" + + - wait + + - command: "bundle config set --local path '.bundle' && bundle config mirror.https://rubygems.org https://gems.ruby-china.com && bundle install && cd activerecord && bundle exec rake db:mysql:build" + label: "build database" + + - wait + + - command: "bundle config set --local path '.bundle' && bundle config mirror.https://rubygems.org https://gems.ruby-china.com && bundle install && cd activerecord && bundle exec rake test:mysql2" + label: "run mysql2 test" \ No newline at end of file From 24812c6eb6918fa44380842b99048dcca812ab0e Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Tue, 6 Jul 2021 18:01:47 +0800 Subject: [PATCH 179/244] use bash for speed --- .buildkite/pipeline.yml | 14 ++------------ tidb_activerecord_testing.sh | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 12 deletions(-) create mode 100755 tidb_activerecord_testing.sh diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index c6d360a9cb6d5..865bb00bdd16c 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -5,15 +5,5 @@ env: MYSQL_PORT: 4000 steps: - - command: "bundle config set --local path '.bundle' && bundle config mirror.https://rubygems.org https://gems.ruby-china.com && bundle install" - label: "bundle install" - - - wait - - - command: "bundle config set --local path '.bundle' && bundle config mirror.https://rubygems.org https://gems.ruby-china.com && bundle install && cd activerecord && bundle exec rake db:mysql:build" - label: "build database" - - - wait - - - command: "bundle config set --local path '.bundle' && bundle config mirror.https://rubygems.org https://gems.ruby-china.com && bundle install && cd activerecord && bundle exec rake test:mysql2" - label: "run mysql2 test" \ No newline at end of file + - command: "tidb_activerecord_testing.sh" + label: "Run TiDB ActiveRecord testing" \ No newline at end of file diff --git a/tidb_activerecord_testing.sh b/tidb_activerecord_testing.sh new file mode 100755 index 0000000000000..6df3e030cd231 --- /dev/null +++ b/tidb_activerecord_testing.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -eo pipefail + +bundle config set --local path '.bundle' + +echo "Setup gem mirror" +bundle config mirror.https://rubygems.org https://gems.ruby-china.com + +echo "Bundle install" +bundle install + +echo "Setup database for testing" +cd activerecord && bundle exec rake db:mysql:build && bundle exec rake test:mysql2 From c19ac892c18a86ee2dec84615726e88a82830e51 Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Tue, 6 Jul 2021 19:34:26 +0800 Subject: [PATCH 180/244] config mysql port --- .buildkite/pipeline.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 865bb00bdd16c..4fcc373e4624f 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -2,7 +2,6 @@ env: tidb: 1 MYSQL_HOST: 127.0.0.1 MYSQL_USER: root - MYSQL_PORT: 4000 steps: - command: "tidb_activerecord_testing.sh" From 9f4087abf07d70f2077c90fc6f39da61edc6cb69 Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Wed, 7 Jul 2021 12:36:38 +0800 Subject: [PATCH 181/244] rebuild database for every testing --- tidb_activerecord_testing.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tidb_activerecord_testing.sh b/tidb_activerecord_testing.sh index 6df3e030cd231..87b6d9e55e764 100755 --- a/tidb_activerecord_testing.sh +++ b/tidb_activerecord_testing.sh @@ -11,4 +11,4 @@ echo "Bundle install" bundle install echo "Setup database for testing" -cd activerecord && bundle exec rake db:mysql:build && bundle exec rake test:mysql2 +cd activerecord && bundle exec rake db:mysql:rebuild && bundle exec rake test:mysql2 From 1858758c5bb7175ba203c32dbbac3a8628f7d88d Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Wed, 7 Jul 2021 12:49:49 +0800 Subject: [PATCH 182/244] [tidb] use buildkite cache --- tidb_activerecord_testing.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tidb_activerecord_testing.sh b/tidb_activerecord_testing.sh index 87b6d9e55e764..a51ce1b8b37c2 100755 --- a/tidb_activerecord_testing.sh +++ b/tidb_activerecord_testing.sh @@ -2,7 +2,7 @@ set -eo pipefail -bundle config set --local path '.bundle' +bundle config set --local path '/tmp/buildkite-cache' echo "Setup gem mirror" bundle config mirror.https://rubygems.org https://gems.ruby-china.com From a3d2a98afa79d503d3a8a7cdad521fbcbeea1d58 Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Wed, 7 Jul 2021 18:58:55 +0800 Subject: [PATCH 183/244] [tidb] skip fail foreign_key test --- .../migration/references_foreign_key_test.rb | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb index 43bb63389eef9..0f10760ba20c6 100644 --- a/activerecord/test/cases/migration/references_foreign_key_test.rb +++ b/activerecord/test/cases/migration/references_foreign_key_test.rb @@ -20,7 +20,7 @@ class ReferencesForeignKeyInCreateTest < ActiveRecord::TestCase @connection.create_table :testings do |t| t.references :testing_parent, foreign_key: true end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" fk = @connection.foreign_keys("testings").first assert_equal "testings", fk.from_table assert_equal "testing_parents", fk.to_table @@ -49,7 +49,7 @@ class ReferencesForeignKeyInCreateTest < ActiveRecord::TestCase @connection.create_table :testings do |t| t.references :testing_parent, foreign_key: { primary_key: :other_id } end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" fk = @connection.foreign_keys("testings").find { |k| k.to_table == "testing_parents" } assert_equal "other_id", fk.primary_key end @@ -58,6 +58,7 @@ class ReferencesForeignKeyInCreateTest < ActiveRecord::TestCase @connection.create_table :testings do |t| t.references :parent, foreign_key: { to_table: :testing_parents } end + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" fks = @connection.foreign_keys("testings") assert_equal([["testings", "testing_parents", "parent_id"]], fks.map { |fk| [fk.from_table, fk.to_table, fk.column] }) @@ -92,7 +93,7 @@ class ReferencesForeignKeyTest < ActiveRecord::TestCase @connection.change_table :testings do |t| t.references :testing_parent, foreign_key: true end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" fk = @connection.foreign_keys("testings").first assert_equal "testings", fk.from_table assert_equal "testing_parents", fk.to_table @@ -115,7 +116,7 @@ class ReferencesForeignKeyTest < ActiveRecord::TestCase @connection.change_table :testings do |t| t.references :testing_parent, foreign_key: { primary_key: :other_id } end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" fk = @connection.foreign_keys("testings").find { |k| k.to_table == "testing_parents" } assert_equal "other_id", fk.primary_key end @@ -133,7 +134,7 @@ class ReferencesForeignKeyTest < ActiveRecord::TestCase @connection.create_table :testings do |t| t.references :testing_parent, index: true, foreign_key: true end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" assert_difference "@connection.foreign_keys('testings').size", -1 do @connection.remove_reference :testings, :testing_parent, foreign_key: true end @@ -143,7 +144,7 @@ class ReferencesForeignKeyTest < ActiveRecord::TestCase @connection.create_table :testings do |t| t.references :testing_parent, index: true, foreign_key: true end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" assert_difference "@connection.foreign_keys('testings').size", -1 do @connection.remove_column :testings, :testing_parent_id end @@ -156,7 +157,7 @@ class ReferencesForeignKeyTest < ActiveRecord::TestCase @connection.change_table :testing_parents do |t| t.references :testing, foreign_key: true end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" fk = @connection.foreign_keys("testing_parents").first assert_equal "testing_parents", fk.from_table assert_equal "testing", fk.to_table @@ -183,6 +184,7 @@ def test_references_foreign_key_with_prefix ActiveRecord::Base.table_name_prefix = "p_" migration = CreateDogsMigration.new silence_stream($stdout) { migration.migrate(:up) } + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" assert_equal 1, @connection.foreign_keys("p_dogs").size ensure silence_stream($stdout) { migration.migrate(:down) } @@ -193,6 +195,7 @@ def test_references_foreign_key_with_suffix ActiveRecord::Base.table_name_suffix = "_s" migration = CreateDogsMigration.new silence_stream($stdout) { migration.migrate(:up) } + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" assert_equal 1, @connection.foreign_keys("dogs_s").size ensure silence_stream($stdout) { migration.migrate(:down) } @@ -204,7 +207,7 @@ def test_references_foreign_key_with_suffix t.references :parent1, foreign_key: { to_table: :testing_parents } t.references :parent2, foreign_key: { to_table: :testing_parents } end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" fks = @connection.foreign_keys("testings").sort_by(&:column) fk_definitions = fks.map { |fk| [fk.from_table, fk.to_table, fk.column] } @@ -217,11 +220,11 @@ def test_references_foreign_key_with_suffix t.references :parent1, foreign_key: { to_table: :testing_parents } t.references :parent2, foreign_key: { to_table: :testing_parents } end - + skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" assert_difference "@connection.foreign_keys('testings').size", -1 do @connection.remove_reference :testings, :parent1, foreign_key: { to_table: :testing_parents } end - + fks = @connection.foreign_keys("testings").sort_by(&:column) fk_definitions = fks.map { |fk| [fk.from_table, fk.to_table, fk.column] } From e28fd24654c40ede146abb35832f8773fe629340 Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Thu, 8 Jul 2021 16:56:43 +0800 Subject: [PATCH 184/244] [tidb] skip stored procedures --- activerecord/test/cases/adapters/mysql2/sp_test.rb | 3 +++ .../test/cases/migration/references_foreign_key_test.rb | 1 + 2 files changed, 4 insertions(+) diff --git a/activerecord/test/cases/adapters/mysql2/sp_test.rb b/activerecord/test/cases/adapters/mysql2/sp_test.rb index 626ef595709d5..3dcc085d97d33 100644 --- a/activerecord/test/cases/adapters/mysql2/sp_test.rb +++ b/activerecord/test/cases/adapters/mysql2/sp_test.rb @@ -19,18 +19,21 @@ def setup # In MySQL 5.6, CLIENT_MULTI_RESULTS is enabled by default. # https://dev.mysql.com/doc/refman/5.6/en/call.html def test_multi_results + skip 'TiDB Issue procedure not support: https://docs.pingcap.com/tidb/stable/mysql-compatibility#unsupported-features' rows = @connection.select_rows("CALL ten();") assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}" assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select_rows'" end def test_multi_results_from_select_one + skip 'TiDB Issue procedure not support: https://docs.pingcap.com/tidb/stable/mysql-compatibility#unsupported-features' row = @connection.select_one("CALL topics(1);") assert_equal "David", row["author_name"] assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select_one'" end def test_multi_results_from_find_by_sql + skip 'TiDB Issue procedure not support: https://docs.pingcap.com/tidb/stable/mysql-compatibility#unsupported-features' topics = Topic.find_by_sql "CALL topics(3);" assert_equal 3, topics.size assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select'" diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb index 0f10760ba20c6..70dd26c6ce7dd 100644 --- a/activerecord/test/cases/migration/references_foreign_key_test.rb +++ b/activerecord/test/cases/migration/references_foreign_key_test.rb @@ -157,6 +157,7 @@ class ReferencesForeignKeyTest < ActiveRecord::TestCase @connection.change_table :testing_parents do |t| t.references :testing, foreign_key: true end + @connection.remove_reference :testing_parents, :testing, foreign_key: true skip "TiDB Issue: https://docs.pingcap.com/tidb/stable/constraints#notes" fk = @connection.foreign_keys("testing_parents").first assert_equal "testing_parents", fk.from_table From b308dd19677d6ae4a3c6a6c87cfde7738168480e Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Fri, 9 Jul 2021 12:13:27 +0800 Subject: [PATCH 185/244] [tidb] use localhost --- .buildkite/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 4fcc373e4624f..3d5589e7600dd 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,6 +1,6 @@ env: tidb: 1 - MYSQL_HOST: 127.0.0.1 + MYSQL_HOST: localhost MYSQL_USER: root steps: From 8aacd92bb8c7e0034a9ecf41752c71f306db7745 Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Fri, 9 Jul 2021 14:19:21 +0800 Subject: [PATCH 186/244] Revert "[tidb] use localhost" This reverts commit b308dd19677d6ae4a3c6a6c87cfde7738168480e. --- .buildkite/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 3d5589e7600dd..4fcc373e4624f 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,6 +1,6 @@ env: tidb: 1 - MYSQL_HOST: localhost + MYSQL_HOST: 127.0.0.1 MYSQL_USER: root steps: From 170506e1db35b107fe5ad299ba83ea70ee5e983f Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Fri, 9 Jul 2021 22:57:46 +0800 Subject: [PATCH 187/244] [tidb] tidb_enable_noop_functions => ON --- activerecord/test/config.example.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/activerecord/test/config.example.yml b/activerecord/test/config.example.yml index b43235d4b0a9f..9a5b9ca57568c 100644 --- a/activerecord/test/config.example.yml +++ b/activerecord/test/config.example.yml @@ -57,6 +57,10 @@ connections: collation: utf8mb4_unicode_ci <% if ENV['MYSQL_HOST'] %> host: <%= ENV['MYSQL_HOST'] %> +<% end %> +<% if ENV['tidb'] %> + variables: + tidb_enable_noop_functions: ON <% end %> arunit2: username: <%= ENV["MYSQL_USER"] || 'rails' %> @@ -66,6 +70,10 @@ connections: <% if ENV['MYSQL_HOST'] %> host: <%= ENV['MYSQL_HOST'] %> <% end %> +<% if ENV['tidb'] %> + variables: + tidb_enable_noop_functions: ON +<% end %> oracle: arunit: From c98e42ac52715ab60dc2761eb6c41e9509ab98b6 Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Sat, 10 Jul 2021 15:18:59 +0800 Subject: [PATCH 188/244] [tidb] fix pipeline --- .buildkite/pipeline.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 4fcc373e4624f..2c2ac0913ca95 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,5 +1,4 @@ env: - tidb: 1 MYSQL_HOST: 127.0.0.1 MYSQL_USER: root From c1e70e926f24838951b848e4a7b5160d2ec7d66a Mon Sep 17 00:00:00 2001 From: Hooopo Wang Date: Sat, 10 Jul 2021 15:21:14 +0800 Subject: [PATCH 189/244] [tidb] use_transactional_tests => false --- activerecord/test/cases/test_case.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb index 3504a91ff5218..efe94e3e08090 100644 --- a/activerecord/test/cases/test_case.rb +++ b/activerecord/test/cases/test_case.rb @@ -20,7 +20,7 @@ class TestCase < ActiveSupport::TestCase #:nodoc: self.fixture_path = FIXTURES_ROOT self.use_instantiated_fixtures = false - self.use_transactional_tests = true + self.use_transactional_tests = false def create_fixtures(*fixture_set_names, &block) ActiveRecord::FixtureSet.create_fixtures(ActiveRecord::TestCase.fixture_path, fixture_set_names, fixture_class_names, &block) From 7e8946c4da8b69e3b33a3f16cdfd8923c8756000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fran=C3=A7a?= Date: Wed, 28 Jul 2021 15:21:47 -0400 Subject: [PATCH 190/244] Merge pull request #42896 from ghiculescu/patch-2 Add more detail about what hosts are allowed --- .../middleware/templates/rescues/blocked_host.html.erb | 2 +- .../middleware/templates/rescues/blocked_host.text.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb index 1fbc107e288bf..0eed0f9749238 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb @@ -2,6 +2,6 @@

    Blocked host: <%= @host %>

    -

    To allow requests to <%= @host %>, add the following to your environment configuration:

    +

    To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:

    config.hosts << "<%= @host %>"
    diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb index a94dd982a7078..75483ac8c829c 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb @@ -1,5 +1,5 @@ Blocked host: <%= @host %> -To allow requests to <%= @host %>, add the following to your environment configuration: +To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration: config.hosts << "<%= @host %>" From 9fe57c0fc5561088a2df42e4438992591e9d917e Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Fri, 12 Feb 2021 12:59:54 -0600 Subject: [PATCH 191/244] Refactor CVE-2021-22881 fix Follow-up to 83a6ac3fee8fd538ce7e0088913ff54f0f9bcb6f. This allows `HTTP_HOST` to be omitted as before, and reduces the number of object allocations per request. Benchmark: ```ruby # frozen_string_literal: true require "benchmark/memory" HOST = "example.com:80" BEFORE_REGEXP = /\A(?[a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9.:]+\])(:\d+)?\z/ AFTER_REGEXP = /(?:\A|,[ ]?)([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9.:]+\])(?::\d+)?\z/i Benchmark.memory do |x| x.report("BEFORE (non-nil X-Forwarded-Host)") do origin_host = BEFORE_REGEXP.match(HOST.to_s.downcase)[:host] forwarded_host = BEFORE_REGEXP.match(HOST.to_s.split(/,\s?/).last)[:host] end x.report("BEFORE (nil X-Forwarded-Host)") do origin_host = BEFORE_REGEXP.match(HOST.to_s.downcase)[:host] forwarded_host = BEFORE_REGEXP.match(nil.to_s.split(/,\s?/).last) end x.report("AFTER (non-nil X-Forwarded-Host)") do origin_host = HOST&.slice(AFTER_REGEXP, 1) || "" forwarded_host = HOST&.slice(AFTER_REGEXP, 1) || "" end x.report("AFTER (nil X-Forwarded-Host)") do origin_host = HOST&.slice(AFTER_REGEXP, 1) || "" forwarded_host = nil&.slice(AFTER_REGEXP, 1) || "" end end ``` Results: ``` BEFORE (non-nil X-Forwarded-Host) 616.000 memsize ( 208.000 retained) 9.000 objects ( 2.000 retained) 2.000 strings ( 1.000 retained) BEFORE (nil X-Forwarded-Host) 328.000 memsize ( 0.000 retained) 5.000 objects ( 0.000 retained) 2.000 strings ( 0.000 retained) AFTER (non-nil X-Forwarded-Host) 248.000 memsize ( 168.000 retained) 3.000 objects ( 1.000 retained) 1.000 strings ( 0.000 retained) AFTER (nil X-Forwarded-Host) 40.000 memsize ( 0.000 retained) 1.000 objects ( 0.000 retained) 1.000 strings ( 0.000 retained) ``` [CVE-2021-22942] --- .../middleware/host_authorization.rb | 22 +++++++------------ .../test/dispatch/host_authorization_test.rb | 4 ++-- .../application/middleware/remote_ip_test.rb | 1 - railties/test/isolation/abstract_unit.rb | 2 +- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index ad209c2669bca..8e39aee87dc70 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -86,21 +86,15 @@ def call(env) end private + HOSTNAME = /[a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9.:]+\]/i + VALID_ORIGIN_HOST = /\A(#{HOSTNAME})(?::\d+)?\z/ + VALID_FORWARDED_HOST = /(?:\A|,[ ]?)(#{HOSTNAME})(?::\d+)?\z/ + def authorized?(request) - valid_host = / - \A - (?[a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9.:]+\]) - (:\d+)? - \z - /x - - origin_host = valid_host.match( - request.get_header("HTTP_HOST").to_s.downcase) - forwarded_host = valid_host.match( - request.x_forwarded_host.to_s.split(/,\s?/).last) - - origin_host && @permissions.allows?(origin_host[:host]) && ( - forwarded_host.nil? || @permissions.allows?(forwarded_host[:host])) + origin_host = request.get_header("HTTP_HOST")&.slice(VALID_ORIGIN_HOST, 1) || "" + forwarded_host = request.x_forwarded_host&.slice(VALID_FORWARDED_HOST, 1) || "" + + @permissions.allows?(origin_host) && (forwarded_host.blank? || @permissions.allows?(forwarded_host)) end def mark_as_authorized(request) diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb index 4a39747f8d695..63562c9046a3f 100644 --- a/actionpack/test/dispatch/host_authorization_test.rb +++ b/actionpack/test/dispatch/host_authorization_test.rb @@ -207,11 +207,11 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest @app = ActionDispatch::HostAuthorization.new(App, ".example.com") get "/", env: { - "HOST" => "example.com#sub.example.com", + "HOST" => "attacker.com#x.example.com", } assert_response :forbidden - assert_match "Blocked host: example.com#sub.example.com", response.body + assert_match "Blocked host: attacker.com#x.example.com", response.body end test "blocks requests to similar host" do diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb index 0dc3dc3979307..4c6fa1b371143 100644 --- a/railties/test/application/middleware/remote_ip_test.rb +++ b/railties/test/application/middleware/remote_ip_test.rb @@ -11,7 +11,6 @@ class RemoteIpTest < ActiveSupport::TestCase def remote_ip(env = {}) remote_ip = nil env = Rack::MockRequest.env_for("/").merge(env).merge!( - "HTTP_HOST" => "example.com", "action_dispatch.show_exceptions" => false, "action_dispatch.key_generator" => ActiveSupport::CachingKeyGenerator.new( ActiveSupport::KeyGenerator.new("b3c631c314c0bbca50c1b2843150fe33", iterations: 1000) diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 1d102386833ac..584d30769005a 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -82,7 +82,7 @@ def extract_body(response) end def get(path) - @app.call(::Rack::MockRequest.env_for(path, "HTTP_HOST" => "example.com")) + @app.call(::Rack::MockRequest.env_for(path)) end def assert_welcome(resp) From 3838481a1a98e3fcd14906ea1f301fc1b2418f0d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 19 Aug 2021 09:09:42 -0700 Subject: [PATCH 192/244] Bumping version for release / update changelog --- Gemfile.lock | 110 ++++++++++++++++++------------------- RAILS_VERSION | 2 +- actioncable/CHANGELOG.md | 5 ++ actionmailbox/CHANGELOG.md | 5 ++ actionmailer/CHANGELOG.md | 5 ++ actionpack/CHANGELOG.md | 8 +++ actiontext/CHANGELOG.md | 5 ++ actionview/CHANGELOG.md | 5 ++ activejob/CHANGELOG.md | 5 ++ activemodel/CHANGELOG.md | 5 ++ activerecord/CHANGELOG.md | 5 ++ activestorage/CHANGELOG.md | 5 ++ activesupport/CHANGELOG.md | 5 ++ guides/CHANGELOG.md | 5 ++ railties/CHANGELOG.md | 5 ++ 15 files changed, 124 insertions(+), 56 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 618f8782394fc..654eadb1ace6f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,79 +32,79 @@ GIT PATH remote: . specs: - actioncable (6.0.4) - actionpack (= 6.0.4) + actioncable (6.0.4.1) + actionpack (= 6.0.4.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4) - actionpack (= 6.0.4) - activejob (= 6.0.4) - activerecord (= 6.0.4) - activestorage (= 6.0.4) - activesupport (= 6.0.4) + actionmailbox (6.0.4.1) + actionpack (= 6.0.4.1) + activejob (= 6.0.4.1) + activerecord (= 6.0.4.1) + activestorage (= 6.0.4.1) + activesupport (= 6.0.4.1) mail (>= 2.7.1) - actionmailer (6.0.4) - actionpack (= 6.0.4) - actionview (= 6.0.4) - activejob (= 6.0.4) + actionmailer (6.0.4.1) + actionpack (= 6.0.4.1) + actionview (= 6.0.4.1) + activejob (= 6.0.4.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4) - actionview (= 6.0.4) - activesupport (= 6.0.4) + actionpack (6.0.4.1) + actionview (= 6.0.4.1) + activesupport (= 6.0.4.1) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4) - actionpack (= 6.0.4) - activerecord (= 6.0.4) - activestorage (= 6.0.4) - activesupport (= 6.0.4) + actiontext (6.0.4.1) + actionpack (= 6.0.4.1) + activerecord (= 6.0.4.1) + activestorage (= 6.0.4.1) + activesupport (= 6.0.4.1) nokogiri (>= 1.8.5) - actionview (6.0.4) - activesupport (= 6.0.4) + actionview (6.0.4.1) + activesupport (= 6.0.4.1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4) - activesupport (= 6.0.4) + activejob (6.0.4.1) + activesupport (= 6.0.4.1) globalid (>= 0.3.6) - activemodel (6.0.4) - activesupport (= 6.0.4) - activerecord (6.0.4) - activemodel (= 6.0.4) - activesupport (= 6.0.4) - activestorage (6.0.4) - actionpack (= 6.0.4) - activejob (= 6.0.4) - activerecord (= 6.0.4) + activemodel (6.0.4.1) + activesupport (= 6.0.4.1) + activerecord (6.0.4.1) + activemodel (= 6.0.4.1) + activesupport (= 6.0.4.1) + activestorage (6.0.4.1) + actionpack (= 6.0.4.1) + activejob (= 6.0.4.1) + activerecord (= 6.0.4.1) marcel (~> 1.0.0) - activesupport (6.0.4) + activesupport (6.0.4.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.4) - actioncable (= 6.0.4) - actionmailbox (= 6.0.4) - actionmailer (= 6.0.4) - actionpack (= 6.0.4) - actiontext (= 6.0.4) - actionview (= 6.0.4) - activejob (= 6.0.4) - activemodel (= 6.0.4) - activerecord (= 6.0.4) - activestorage (= 6.0.4) - activesupport (= 6.0.4) + rails (6.0.4.1) + actioncable (= 6.0.4.1) + actionmailbox (= 6.0.4.1) + actionmailer (= 6.0.4.1) + actionpack (= 6.0.4.1) + actiontext (= 6.0.4.1) + actionview (= 6.0.4.1) + activejob (= 6.0.4.1) + activemodel (= 6.0.4.1) + activerecord (= 6.0.4.1) + activestorage (= 6.0.4.1) + activesupport (= 6.0.4.1) bundler (>= 1.3.0) - railties (= 6.0.4) + railties (= 6.0.4.1) sprockets-rails (>= 2.0.0) - railties (6.0.4) - actionpack (= 6.0.4) - activesupport (= 6.0.4) + railties (6.0.4.1) + actionpack (= 6.0.4.1) + activesupport (= 6.0.4.1) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -239,8 +239,8 @@ GEM fugit (1.4.5) et-orbi (~> 1.1, >= 1.1.8) raabro (~> 1.4) - globalid (0.4.2) - activesupport (>= 4.2.0) + globalid (0.5.2) + activesupport (>= 5.0) google-apis-core (0.3.0) addressable (~> 2.5, >= 2.5.1) googleauth (~> 0.14) @@ -292,7 +292,7 @@ GEM mustache nokogiri libxml-ruby (3.2.1) - loofah (2.10.0) + loofah (2.12.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -358,7 +358,7 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) + rails-html-sanitizer (1.4.1) loofah (~> 2.3) rainbow (3.0.0) rake (13.0.3) @@ -585,4 +585,4 @@ DEPENDENCIES websocket-client-simple! BUNDLED WITH - 2.2.3 + 2.2.15 diff --git a/RAILS_VERSION b/RAILS_VERSION index 1aa5e414fd3ab..b46fe9019d8f3 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.4 +6.0.4.1 diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 765a1838c50ea..5810b99b278d0 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * No changes. diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index b2765850d232a..f68d914fa7240 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * No changes. diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index cc02c73fc77aa..6ea1d657bdb6d 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * No changes. diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 016ecc4b78265..205d53dcda6cd 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,11 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* [CVE-2021-22942] Fix possible open redirect in Host Authorization middleware. + + Specially crafted "X-Forwarded-Host" headers in combination with certain + "allowed host" formats can cause the Host Authorization middleware in Action + Pack to redirect users to a malicious website. + ## Rails 6.0.4 (June 15, 2021) ## * Accept base64_urlsafe CSRF tokens to make forward compatible. diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index dd7d3962118ce..d66ca08300a35 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * No changes. diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index b5172afd57e65..873dafcac8141 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * SanitizeHelper.sanitized_allowed_attributes and SanitizeHelper.sanitized_allowed_tags diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 2a2c9049d0f98..09b3ad6a72400 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * No changes. diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 0b1cfa7aeebbf..a492723936154 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * No changes. diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index e00429ce1cbfc..231dff1fd0b73 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * Only warn about negative enums if a positive form that would cause conflicts exists. diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 2feefc3d73910..389c64c57233e 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * The Poppler PDF previewer renders a preview image using the original diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 0a780d6d228c1..7815de0166f8c 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * Fixed issue in `ActiveSupport::Cache::RedisCacheStore` not passing options diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index 412dbe29a6044..2dc1370dcaf3b 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index d2ebd0cae626e..2d5f81bd0ca5f 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.1 (August 19, 2021) ## + +* No changes. + + ## Rails 6.0.4 (June 15, 2021) ## * Allow relative paths with trailing slashes to be passed to `rails test`. From 0d304eae601f085274b2e2c04316e025b443da62 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 19 Aug 2021 09:15:43 -0700 Subject: [PATCH 193/244] Preparing for 6.0.4.1 release --- actioncable/lib/action_cable/gem_version.rb | 2 +- actioncable/package.json | 2 +- actionmailbox/lib/action_mailbox/gem_version.rb | 2 +- actionmailer/lib/action_mailer/gem_version.rb | 2 +- actionpack/lib/action_pack/gem_version.rb | 2 +- actiontext/lib/action_text/gem_version.rb | 2 +- actiontext/package.json | 2 +- actionview/lib/action_view/gem_version.rb | 2 +- actionview/package.json | 2 +- activejob/lib/active_job/gem_version.rb | 2 +- activemodel/lib/active_model/gem_version.rb | 2 +- activerecord/lib/active_record/gem_version.rb | 2 +- activestorage/lib/active_storage/gem_version.rb | 2 +- activestorage/package.json | 2 +- activesupport/lib/active_support/gem_version.rb | 2 +- railties/lib/rails/gem_version.rb | 2 +- version.rb | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index e33ab30a47ff1..d8bc149ff9516 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index 04178e1b9e3c3..b1459a22b8b31 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.4", + "version": "6.0.4-1", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index 1c744791054e9..b004e1f467220 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index 6c6a90fbf5124..91e667af7a8f8 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index c9c71ef934d5d..533f586a9a18f 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index e2ac85e7cf446..9a20dcb83ce99 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index 9156639bbb4a4..e024d4aa7a8ec 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.4", + "version": "6.0.4-1", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 832d02d90e83e..4327ad7cf8ceb 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 5256b6e677768..3edc99cec130d 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.4", + "version": "6.0.4-1", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index ba6226992ad75..20982d7f1bd4f 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index afeb94f5d685b..af2d181b0f4d4 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index a8116e3590b0f..54eb585e14121 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index aca30742bb78e..bd9cae4164ba6 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index bacc1732bc5ba..5403705f7ea70 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.4", + "version": "6.0.4-1", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 45099914a675d..555a67a83c24b 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index acf9ef48d8d13..7df4e84201cdf 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index acf9ef48d8d13..7df4e84201cdf 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = nil + PRE = "1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From 3136f2646a366fbc663e44dc4b2d1f8c087301a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 20 Sep 2021 17:19:28 -0400 Subject: [PATCH 194/244] Allow Marcel to be released following semver --- Gemfile.lock | 4 ++-- activestorage/activestorage.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 654eadb1ace6f..0648495d0a877 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -80,7 +80,7 @@ PATH actionpack (= 6.0.4.1) activejob (= 6.0.4.1) activerecord (= 6.0.4.1) - marcel (~> 1.0.0) + marcel (~> 1.0) activesupport (6.0.4.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) @@ -585,4 +585,4 @@ DEPENDENCIES websocket-client-simple! BUNDLED WITH - 2.2.15 + 2.2.25 diff --git a/activestorage/activestorage.gemspec b/activestorage/activestorage.gemspec index f5e64922b229c..dcef84a067932 100644 --- a/activestorage/activestorage.gemspec +++ b/activestorage/activestorage.gemspec @@ -35,5 +35,5 @@ Gem::Specification.new do |s| s.add_dependency "activejob", version s.add_dependency "activerecord", version - s.add_dependency "marcel", "~> 1.0.0" + s.add_dependency "marcel", "~> 1.0" end From 1b5658b562b29f8aab7e80cbab8adbd2ddea5447 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Wed, 25 Aug 2021 11:22:39 +0200 Subject: [PATCH 195/244] Temporarily disable Azure service tests (#43091) The Azure service tests are currently failing on the main branch, probably because of configuration. We can temporarily disable them while we get things working again. --- activestorage/test/test_helper.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/activestorage/test/test_helper.rb b/activestorage/test/test_helper.rb index a41224104f823..00fbdf61df940 100644 --- a/activestorage/test/test_helper.rb +++ b/activestorage/test/test_helper.rb @@ -30,6 +30,12 @@ puts "Missing service configuration file in test/service/configurations.yml" {} end +# Azure service tests are currently failing on the main branch. +# We temporarily disable them while we get things working again. +if ENV["CI"] + SERVICE_CONFIGURATIONS.delete(:azure) + SERVICE_CONFIGURATIONS.delete(:azure_public) +end require "tmpdir" ActiveStorage::Blob.service = ActiveStorage::Service::DiskService.new(root: Dir.mktmpdir("active_storage_tests")) From 7f1e11b65a1b594ca573865a179bd48c881fd4ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 15 Nov 2021 20:37:42 +0000 Subject: [PATCH 196/244] Require MFA to release rails --- actioncable/actioncable.gemspec | 1 + actionmailbox/actionmailbox.gemspec | 1 + actionmailer/actionmailer.gemspec | 1 + actionpack/actionpack.gemspec | 1 + actiontext/actiontext.gemspec | 1 + actionview/actionview.gemspec | 1 + activejob/activejob.gemspec | 1 + activemodel/activemodel.gemspec | 1 + activerecord/activerecord.gemspec | 1 + activestorage/activestorage.gemspec | 1 + activesupport/activesupport.gemspec | 1 + rails.gemspec | 1 + railties/railties.gemspec | 1 + 13 files changed, 13 insertions(+) diff --git a/actioncable/actioncable.gemspec b/actioncable/actioncable.gemspec index 60751c3dfee17..be3e6ec8acbaa 100644 --- a/actioncable/actioncable.gemspec +++ b/actioncable/actioncable.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actioncable", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actionmailbox/actionmailbox.gemspec b/actionmailbox/actionmailbox.gemspec index 47501b1cd19e9..4830b67f45337 100644 --- a/actionmailbox/actionmailbox.gemspec +++ b/actionmailbox/actionmailbox.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionmailbox", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index 5cce629dbe8f8..b0a2add95cb2c 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -27,6 +27,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionmailer", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 332f861acda1b..148b11a69926e 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -27,6 +27,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionpack", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actiontext/actiontext.gemspec b/actiontext/actiontext.gemspec index 8c5e6564e3ec1..d0f37bd3c7262 100644 --- a/actiontext/actiontext.gemspec +++ b/actiontext/actiontext.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actiontext", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actionview/actionview.gemspec b/actionview/actionview.gemspec index 69cef1e8e5aa8..b74a64d7b2c15 100644 --- a/actionview/actionview.gemspec +++ b/actionview/actionview.gemspec @@ -27,6 +27,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionview", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activejob/activejob.gemspec b/activejob/activejob.gemspec index 9775cb2983998..c6fca43ecde1e 100644 --- a/activejob/activejob.gemspec +++ b/activejob/activejob.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activejob", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index 30a0697d3842e..f7245f76e2bda 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activemodel", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index 1e295fc27cc18..d218635f2db9a 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -29,6 +29,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activerecord", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activestorage/activestorage.gemspec b/activestorage/activestorage.gemspec index dcef84a067932..5d8016b3711d7 100644 --- a/activestorage/activestorage.gemspec +++ b/activestorage/activestorage.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activestorage", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 1de7ee06651b7..1a783c8b48c90 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -28,6 +28,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activesupport", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/rails.gemspec b/rails.gemspec index 51d98910f99eb..3ba48ad982c2f 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}", + "rubygems_mfa_required" => true, } s.add_dependency "activesupport", version diff --git a/railties/railties.gemspec b/railties/railties.gemspec index 70e3e33fa9a2f..f610322cbd5f8 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -31,6 +31,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/railties", + "rubygems_mfa_required" => true, } # NOTE: Please read our dependency guidelines before updating versions: From c7a6ec51bf097eb3f307001c1142a8565e7a1450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 15 Nov 2021 21:06:21 +0000 Subject: [PATCH 197/244] Fix gemspec --- actioncable/actioncable.gemspec | 2 +- actionmailbox/actionmailbox.gemspec | 2 +- actionmailer/actionmailer.gemspec | 2 +- actionpack/actionpack.gemspec | 2 +- actiontext/actiontext.gemspec | 2 +- actionview/actionview.gemspec | 2 +- activejob/activejob.gemspec | 2 +- activemodel/activemodel.gemspec | 2 +- activerecord/activerecord.gemspec | 2 +- activestorage/activestorage.gemspec | 2 +- activesupport/activesupport.gemspec | 2 +- rails.gemspec | 2 +- railties/railties.gemspec | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/actioncable/actioncable.gemspec b/actioncable/actioncable.gemspec index be3e6ec8acbaa..ecfcd931c3d59 100644 --- a/actioncable/actioncable.gemspec +++ b/actioncable/actioncable.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actioncable", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actionmailbox/actionmailbox.gemspec b/actionmailbox/actionmailbox.gemspec index 4830b67f45337..18786628578b6 100644 --- a/actionmailbox/actionmailbox.gemspec +++ b/actionmailbox/actionmailbox.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionmailbox", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index b0a2add95cb2c..dd550ec11159b 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionmailer", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 148b11a69926e..1dcbc5b67f61b 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionpack", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actiontext/actiontext.gemspec b/actiontext/actiontext.gemspec index d0f37bd3c7262..f639ce5f9452a 100644 --- a/actiontext/actiontext.gemspec +++ b/actiontext/actiontext.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actiontext", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/actionview/actionview.gemspec b/actionview/actionview.gemspec index b74a64d7b2c15..11928e66a89e6 100644 --- a/actionview/actionview.gemspec +++ b/actionview/actionview.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionview", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activejob/activejob.gemspec b/activejob/activejob.gemspec index c6fca43ecde1e..af671f4695d7a 100644 --- a/activejob/activejob.gemspec +++ b/activejob/activejob.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activejob", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec index f7245f76e2bda..88cbbdc3fb691 100644 --- a/activemodel/activemodel.gemspec +++ b/activemodel/activemodel.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activemodel", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index d218635f2db9a..412dcf91be1e0 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -29,7 +29,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activerecord", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activestorage/activestorage.gemspec b/activestorage/activestorage.gemspec index 5d8016b3711d7..15452a9147f33 100644 --- a/activestorage/activestorage.gemspec +++ b/activestorage/activestorage.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activestorage", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 1a783c8b48c90..1c6440c8f07d4 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -28,7 +28,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/activesupport", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: diff --git a/rails.gemspec b/rails.gemspec index 3ba48ad982c2f..ae2c47697da2e 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } s.add_dependency "activesupport", version diff --git a/railties/railties.gemspec b/railties/railties.gemspec index f610322cbd5f8..37f985ce8be86 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -31,7 +31,7 @@ Gem::Specification.new do |s| "documentation_uri" => "https://api.rubyonrails.org/v#{version}/", "mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk", "source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/railties", - "rubygems_mfa_required" => true, + "rubygems_mfa_required" => "true", } # NOTE: Please read our dependency guidelines before updating versions: From fd6a64fef1d0f7f40a8d4b046da882e83163299c Mon Sep 17 00:00:00 2001 From: Stef Schenkelaars Date: Wed, 7 Jul 2021 12:06:32 +0200 Subject: [PATCH 198/244] Fix invalid forwarded host vulnerability Prior to this commit, it was possible to pass an unvalidated host through the `X-Forwarded-Host` header. If the value of the header was prefixed with a invalid domain character (for example a `/`), it was always accepted as the actual host of that request. Since this host is used for all url helpers, an attacker could change generated links and redirects. If the header is set to `X-Forwarded-Host: //evil.hacker`, a redirect will be send to `https:////evil.hacker/`. Browsers will ignore these four slashes and redirect the user. [CVE-2021-44528] --- .../middleware/host_authorization.rb | 10 +-- .../test/dispatch/host_authorization_test.rb | 89 ++++++++++++++++++- 2 files changed, 91 insertions(+), 8 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index 8e39aee87dc70..ca2b17cb8bc99 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -46,7 +46,7 @@ def sanitize_regexp(host) def sanitize_string(host) if host.start_with?(".") - /\A(.+\.)?#{Regexp.escape(host[1..-1])}\z/i + /\A([a-z0-9-]+\.)?#{Regexp.escape(host[1..-1])}\z/i else /\A#{Regexp.escape host}\z/i end @@ -86,13 +86,9 @@ def call(env) end private - HOSTNAME = /[a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9.:]+\]/i - VALID_ORIGIN_HOST = /\A(#{HOSTNAME})(?::\d+)?\z/ - VALID_FORWARDED_HOST = /(?:\A|,[ ]?)(#{HOSTNAME})(?::\d+)?\z/ - def authorized?(request) - origin_host = request.get_header("HTTP_HOST")&.slice(VALID_ORIGIN_HOST, 1) || "" - forwarded_host = request.x_forwarded_host&.slice(VALID_FORWARDED_HOST, 1) || "" + origin_host = request.get_header("HTTP_HOST") + forwarded_host = request.x_forwarded_host&.split(/,\s?/)&.last @permissions.allows?(origin_host) && (forwarded_host.blank? || @permissions.allows?(forwarded_host)) end diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb index 63562c9046a3f..8b29dabf0c1b3 100644 --- a/actionpack/test/dispatch/host_authorization_test.rb +++ b/actionpack/test/dispatch/host_authorization_test.rb @@ -155,6 +155,44 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_match "Blocked host: 127.0.0.1", response.body end + test "blocks requests with spoofed relative X-FORWARDED-HOST" do + @app = ActionDispatch::HostAuthorization.new(App, ["www.example.com"]) + + get "/", env: { + "HTTP_X_FORWARDED_HOST" => "//randomhost.com", + "HOST" => "www.example.com", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :forbidden + assert_match "Blocked host: //randomhost.com", response.body + end + + test "forwarded secondary hosts are allowed when permitted" do + @app = ActionDispatch::HostAuthorization.new(App, ".domain.com") + + get "/", env: { + "HTTP_X_FORWARDED_HOST" => "example.com, my-sub.domain.com", + "HOST" => "domain.com", + } + + assert_response :ok + assert_equal "Success", body + end + + test "forwarded secondary hosts are blocked when mismatch" do + @app = ActionDispatch::HostAuthorization.new(App, "domain.com") + + get "/", env: { + "HTTP_X_FORWARDED_HOST" => "domain.com, evil.com", + "HOST" => "domain.com", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :forbidden + assert_match "Blocked host: evil.com", response.body + end + test "does not consider IP addresses in X-FORWARDED-HOST spoofed when disabled" do @app = ActionDispatch::HostAuthorization.new(App, nil) @@ -191,11 +229,23 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_match "Blocked host: sub.domain.com", response.body end + test "sub-sub domains should not be permitted" do + @app = ActionDispatch::HostAuthorization.new(App, ".domain.com") + + get "/", env: { + "HOST" => "secondary.sub.domain.com", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :forbidden + assert_match "Blocked host: secondary.sub.domain.com", response.body + end + test "forwarded hosts are allowed when permitted" do @app = ActionDispatch::HostAuthorization.new(App, ".domain.com") get "/", env: { - "HTTP_X_FORWARDED_HOST" => "sub.domain.com", + "HTTP_X_FORWARDED_HOST" => "my-sub.domain.com", "HOST" => "domain.com", } @@ -224,4 +274,41 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_response :forbidden assert_match "Blocked host: sub-example.com", response.body end + + test "lots of NG hosts" do + ng_hosts = [ + "hacker%E3%80%82com", + "hacker%00.com", + "www.theirsite.com@yoursite.com", + "hacker.com/test/", + "hacker%252ecom", + ".hacker.com", + "/\/\/hacker.com/", + "/hacker.com", + "../hacker.com", + ".hacker.com", + "@hacker.com", + "hacker.com", + "hacker.com%23@example.com", + "hacker.com/.jpg", + "hacker.com\texample.com/", + "hacker.com/example.com", + "hacker.com\@example.com", + "hacker.com/example.com", + "hacker.com/" + ] + + @app = ActionDispatch::HostAuthorization.new(App, "example.com") + + ng_hosts.each do |host| + get "/", env: { + "HTTP_X_FORWARDED_HOST" => host, + "HOST" => "example.com", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :forbidden + assert_match "Blocked host: #{host}", response.body + end + end end From c40867cec68f5486fe31cb9e80ba54166fb6fa9d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2021 11:14:39 -0800 Subject: [PATCH 199/244] update changelog --- actionpack/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 205d53dcda6cd..53df2a1658cb8 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,4 +1,6 @@ -## Rails 6.0.4.1 (August 19, 2021) ## +* Fix X_FORWARDED_HOST protection. [CVE-2021-44528] + +## Rails 6.1.4.1 (August 19, 2021) ## * [CVE-2021-22942] Fix possible open redirect in Host Authorization middleware. From 2d32c1ed9a749e4a0c618b1f6605c4b6f866e112 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2021 11:18:09 -0800 Subject: [PATCH 200/244] bumping version --- RAILS_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RAILS_VERSION b/RAILS_VERSION index b46fe9019d8f3..a02dcda089f0e 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.4.1 +6.0.4.2 From 9ef61211d7861093a69fa1fbfc2ba136abd37cd2 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2021 12:09:18 -0800 Subject: [PATCH 201/244] Preparing for 6.0.4.2 release --- Gemfile.lock | 113 +++++++++--------- actioncable/CHANGELOG.md | 5 + actioncable/lib/action_cable/gem_version.rb | 2 +- actioncable/package.json | 2 +- actionmailbox/CHANGELOG.md | 5 + .../lib/action_mailbox/gem_version.rb | 2 +- actionmailer/CHANGELOG.md | 5 + actionmailer/lib/action_mailer/gem_version.rb | 2 +- actionpack/CHANGELOG.md | 2 + actionpack/lib/action_pack/gem_version.rb | 2 +- actiontext/CHANGELOG.md | 5 + actiontext/lib/action_text/gem_version.rb | 2 +- actiontext/package.json | 2 +- actionview/CHANGELOG.md | 5 + actionview/lib/action_view/gem_version.rb | 2 +- actionview/package.json | 2 +- activejob/CHANGELOG.md | 5 + activejob/lib/active_job/gem_version.rb | 2 +- activemodel/CHANGELOG.md | 5 + activemodel/lib/active_model/gem_version.rb | 2 +- activerecord/CHANGELOG.md | 5 + activerecord/lib/active_record/gem_version.rb | 2 +- activestorage/CHANGELOG.md | 5 + .../lib/active_storage/gem_version.rb | 2 +- activestorage/package.json | 2 +- activesupport/CHANGELOG.md | 5 + .../lib/active_support/gem_version.rb | 2 +- guides/CHANGELOG.md | 5 + railties/CHANGELOG.md | 5 + railties/lib/rails/gem_version.rb | 2 +- version.rb | 2 +- 31 files changed, 135 insertions(+), 74 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 654eadb1ace6f..6c79e6ebff493 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,79 +32,79 @@ GIT PATH remote: . specs: - actioncable (6.0.4.1) - actionpack (= 6.0.4.1) + actioncable (6.0.4.2) + actionpack (= 6.0.4.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.1) - actionpack (= 6.0.4.1) - activejob (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) + actionmailbox (6.0.4.2) + actionpack (= 6.0.4.2) + activejob (= 6.0.4.2) + activerecord (= 6.0.4.2) + activestorage (= 6.0.4.2) + activesupport (= 6.0.4.2) mail (>= 2.7.1) - actionmailer (6.0.4.1) - actionpack (= 6.0.4.1) - actionview (= 6.0.4.1) - activejob (= 6.0.4.1) + actionmailer (6.0.4.2) + actionpack (= 6.0.4.2) + actionview (= 6.0.4.2) + activejob (= 6.0.4.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4.1) - actionview (= 6.0.4.1) - activesupport (= 6.0.4.1) + actionpack (6.0.4.2) + actionview (= 6.0.4.2) + activesupport (= 6.0.4.2) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.1) - actionpack (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) + actiontext (6.0.4.2) + actionpack (= 6.0.4.2) + activerecord (= 6.0.4.2) + activestorage (= 6.0.4.2) + activesupport (= 6.0.4.2) nokogiri (>= 1.8.5) - actionview (6.0.4.1) - activesupport (= 6.0.4.1) + actionview (6.0.4.2) + activesupport (= 6.0.4.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.1) - activesupport (= 6.0.4.1) + activejob (6.0.4.2) + activesupport (= 6.0.4.2) globalid (>= 0.3.6) - activemodel (6.0.4.1) - activesupport (= 6.0.4.1) - activerecord (6.0.4.1) - activemodel (= 6.0.4.1) - activesupport (= 6.0.4.1) - activestorage (6.0.4.1) - actionpack (= 6.0.4.1) - activejob (= 6.0.4.1) - activerecord (= 6.0.4.1) + activemodel (6.0.4.2) + activesupport (= 6.0.4.2) + activerecord (6.0.4.2) + activemodel (= 6.0.4.2) + activesupport (= 6.0.4.2) + activestorage (6.0.4.2) + actionpack (= 6.0.4.2) + activejob (= 6.0.4.2) + activerecord (= 6.0.4.2) marcel (~> 1.0.0) - activesupport (6.0.4.1) + activesupport (6.0.4.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.4.1) - actioncable (= 6.0.4.1) - actionmailbox (= 6.0.4.1) - actionmailer (= 6.0.4.1) - actionpack (= 6.0.4.1) - actiontext (= 6.0.4.1) - actionview (= 6.0.4.1) - activejob (= 6.0.4.1) - activemodel (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) + rails (6.0.4.2) + actioncable (= 6.0.4.2) + actionmailbox (= 6.0.4.2) + actionmailer (= 6.0.4.2) + actionpack (= 6.0.4.2) + actiontext (= 6.0.4.2) + actionview (= 6.0.4.2) + activejob (= 6.0.4.2) + activemodel (= 6.0.4.2) + activerecord (= 6.0.4.2) + activestorage (= 6.0.4.2) + activesupport (= 6.0.4.2) bundler (>= 1.3.0) - railties (= 6.0.4.1) + railties (= 6.0.4.2) sprockets-rails (>= 2.0.0) - railties (6.0.4.1) - actionpack (= 6.0.4.1) - activesupport (= 6.0.4.1) + railties (6.0.4.2) + actionpack (= 6.0.4.2) + activesupport (= 6.0.4.2) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -239,7 +239,7 @@ GEM fugit (1.4.5) et-orbi (~> 1.1, >= 1.1.8) raabro (~> 1.4) - globalid (0.5.2) + globalid (1.0.0) activesupport (>= 5.0) google-apis-core (0.3.0) addressable (~> 2.5, >= 2.5.1) @@ -280,7 +280,7 @@ GEM hiredis (0.6.3) http_parser.rb (0.6.0) httpclient (2.8.3) - i18n (1.8.10) + i18n (1.8.11) concurrent-ruby (~> 1.0) image_processing (1.12.1) mini_magick (>= 4.9.5, < 5) @@ -292,12 +292,12 @@ GEM mustache nokogiri libxml-ruby (3.2.1) - loofah (2.12.0) + loofah (2.13.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) - marcel (1.0.1) + marcel (1.0.2) memoist (0.16.2) method_source (1.0.0) mini_magick (4.11.0) @@ -336,7 +336,6 @@ GEM ast (~> 2.4.1) path_expander (1.1.0) pg (1.2.3) - psych (3.3.1) public_suffix (4.0.6) puma (5.2.2) nio4r (~> 2.0) @@ -358,7 +357,7 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.4.1) + rails-html-sanitizer (1.4.2) loofah (~> 2.3) rainbow (3.0.0) rake (13.0.3) @@ -507,7 +506,7 @@ GEM websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.4.2) + zeitwerk (2.5.1) PLATFORMS ruby diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 5810b99b278d0..494384c816711 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index d8bc149ff9516..aa6dd78248f10 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index b1459a22b8b31..2be442c63d6c8 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.4-1", + "version": "6.0.4-2", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index f68d914fa7240..c18b3ed56c8eb 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index b004e1f467220..e1b13fc799cfb 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 6ea1d657bdb6d..97fa95dcbe11c 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index 91e667af7a8f8..e037b2698c7ed 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 53df2a1658cb8..80d2aa13cba3d 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + * Fix X_FORWARDED_HOST protection. [CVE-2021-44528] ## Rails 6.1.4.1 (August 19, 2021) ## diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index 533f586a9a18f..b460e72face59 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index d66ca08300a35..62c6bb08c803f 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index 9a20dcb83ce99..9222d5449d868 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index e024d4aa7a8ec..f40795bc831eb 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.4-1", + "version": "6.0.4-2", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 873dafcac8141..1e7c8638baf34 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 4327ad7cf8ceb..04442ffda443f 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 3edc99cec130d..97322f10118f0 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.4-1", + "version": "6.0.4-2", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 09b3ad6a72400..90e56c227ab1b 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index 20982d7f1bd4f..ad84bcf5da341 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index a492723936154..e88fc7d3635fa 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index af2d181b0f4d4..d4319b0d96179 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 231dff1fd0b73..39f6ed5dd9fd8 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index 54eb585e14121..fca66acb78dd2 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 389c64c57233e..4620781183ce5 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index bd9cae4164ba6..b460ce4d04869 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index 5403705f7ea70..23c76bc14df61 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.4-1", + "version": "6.0.4-2", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 7815de0166f8c..af3f34497dc99 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 555a67a83c24b..7c9114417c9f3 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index 2dc1370dcaf3b..a856eb128dc86 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 2d5f81bd0ca5f..46445ab334e12 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.2 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.1 (August 19, 2021) ## * No changes. diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index 7df4e84201cdf..97b0c1f7ca6d8 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index 7df4e84201cdf..97b0c1f7ca6d8 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "1" + PRE = "2" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From b1595838a7f85235dbca73aee57657e5a81a188b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2021 13:36:20 -0800 Subject: [PATCH 202/244] Merge pull request #43863 from rails/yubikey-support Add support for YubiKey OTP codes during release --- tasks/release.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tasks/release.rb b/tasks/release.rb index 0476d56b55797..5a800ad7ae3de 100644 --- a/tasks/release.rb +++ b/tasks/release.rb @@ -99,12 +99,26 @@ end task push: :build do - sh "gem push #{gem}" + otp = "" + begin + otp = " --otp " + `ykman oath accounts code -s rubygems.org`.chomp + rescue + # User doesn't have ykman + end + + sh "gem push #{gem}#{otp}" if File.exist?("#{framework}/package.json") Dir.chdir("#{framework}") do npm_tag = /[a-z]/.match?(version) ? "pre" : "latest" - sh "npm publish --tag #{npm_tag}" + npm_otp = "" + begin + npm_otp = " --otp " + `ykman oath accounts code -s npmjs.com`.chomp + rescue + # User doesn't have ykman + end + + sh "npm publish --tag #{npm_tag}#{npm_otp}" end end end From 1ca9a4153c1cf4cf11c17987400609acbd87504b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2021 14:51:36 -0800 Subject: [PATCH 203/244] Merge pull request #43868 from rails/fix-default-hosts Allow localhost with a port by default in development --- .../action_dispatch/middleware/host_authorization.rb | 2 ++ actionpack/test/dispatch/host_authorization_test.rb | 12 ++++++++++++ railties/lib/rails/application/configuration.rb | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index ca2b17cb8bc99..a690cce866dc3 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -10,6 +10,8 @@ module ActionDispatch # application will be executed and rendered. If no +response_app+ is given, a # default one will run, which responds with +403 Forbidden+. class HostAuthorization + ALLOWED_HOSTS_IN_DEVELOPMENT = [".localhost", /\A([a-z0-9-]+\.)?localhost:\d+\z/, IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")] + class Permissions # :nodoc: def initialize(hosts) @hosts = sanitize_hosts(hosts) diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb index 8b29dabf0c1b3..c0bd0432f4e82 100644 --- a/actionpack/test/dispatch/host_authorization_test.rb +++ b/actionpack/test/dispatch/host_authorization_test.rb @@ -143,6 +143,18 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_equal "Custom", body end + test "localhost works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "localhost:3000", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + test "blocks requests with spoofed X-FORWARDED-HOST" do @app = ActionDispatch::HostAuthorization.new(App, [IPAddr.new("127.0.0.1")]) diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index cdaf507c7dbaa..e87dab37a80b1 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -31,7 +31,7 @@ def initialize(*) @filter_parameters = [] @filter_redirect = [] @helpers_paths = [] - @hosts = Array(([".localhost", IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")] if Rails.env.development?)) + @hosts = Rails.env.development? ? ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT : [] @public_file_server = ActiveSupport::OrderedOptions.new @public_file_server.enabled = true @public_file_server.index_name = "index" From 56783fef72ebd6e3c19b784a07879714f2c0acfc Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2021 14:54:32 -0800 Subject: [PATCH 204/244] update changelog --- railties/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 46445ab334e12..1616c3e94e199 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,7 @@ +* Allow localhost with a port by default in development + + [Fixes: #43864] + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. From 1169e2fabaf3cf5dd8c76b30983f56dd18e8998c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2021 14:58:57 -0800 Subject: [PATCH 205/244] bump version --- RAILS_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RAILS_VERSION b/RAILS_VERSION index a02dcda089f0e..c3d46182d54d4 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.4.2 +6.0.4.3 From 0cc179fdc77e57ee2756769ec4d14203d93e2354 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2021 15:00:27 -0800 Subject: [PATCH 206/244] Preparing for 6.0.4.3 release --- Gemfile.lock | 100 +++++++++--------- actioncable/CHANGELOG.md | 5 + actioncable/lib/action_cable/gem_version.rb | 2 +- actioncable/package.json | 2 +- actionmailbox/CHANGELOG.md | 5 + .../lib/action_mailbox/gem_version.rb | 2 +- actionmailer/CHANGELOG.md | 5 + actionmailer/lib/action_mailer/gem_version.rb | 2 +- actionpack/CHANGELOG.md | 5 + actionpack/lib/action_pack/gem_version.rb | 2 +- actiontext/CHANGELOG.md | 5 + actiontext/lib/action_text/gem_version.rb | 2 +- actiontext/package.json | 2 +- actionview/CHANGELOG.md | 5 + actionview/lib/action_view/gem_version.rb | 2 +- actionview/package.json | 2 +- activejob/CHANGELOG.md | 5 + activejob/lib/active_job/gem_version.rb | 2 +- activemodel/CHANGELOG.md | 5 + activemodel/lib/active_model/gem_version.rb | 2 +- activerecord/CHANGELOG.md | 5 + activerecord/lib/active_record/gem_version.rb | 2 +- activestorage/CHANGELOG.md | 5 + .../lib/active_storage/gem_version.rb | 2 +- activestorage/package.json | 2 +- activesupport/CHANGELOG.md | 5 + .../lib/active_support/gem_version.rb | 2 +- guides/CHANGELOG.md | 5 + railties/CHANGELOG.md | 2 + railties/lib/rails/gem_version.rb | 2 +- version.rb | 2 +- 31 files changed, 129 insertions(+), 67 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6c79e6ebff493..5a22dd468ebe3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,79 +32,79 @@ GIT PATH remote: . specs: - actioncable (6.0.4.2) - actionpack (= 6.0.4.2) + actioncable (6.0.4.3) + actionpack (= 6.0.4.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.2) - actionpack (= 6.0.4.2) - activejob (= 6.0.4.2) - activerecord (= 6.0.4.2) - activestorage (= 6.0.4.2) - activesupport (= 6.0.4.2) + actionmailbox (6.0.4.3) + actionpack (= 6.0.4.3) + activejob (= 6.0.4.3) + activerecord (= 6.0.4.3) + activestorage (= 6.0.4.3) + activesupport (= 6.0.4.3) mail (>= 2.7.1) - actionmailer (6.0.4.2) - actionpack (= 6.0.4.2) - actionview (= 6.0.4.2) - activejob (= 6.0.4.2) + actionmailer (6.0.4.3) + actionpack (= 6.0.4.3) + actionview (= 6.0.4.3) + activejob (= 6.0.4.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4.2) - actionview (= 6.0.4.2) - activesupport (= 6.0.4.2) + actionpack (6.0.4.3) + actionview (= 6.0.4.3) + activesupport (= 6.0.4.3) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.2) - actionpack (= 6.0.4.2) - activerecord (= 6.0.4.2) - activestorage (= 6.0.4.2) - activesupport (= 6.0.4.2) + actiontext (6.0.4.3) + actionpack (= 6.0.4.3) + activerecord (= 6.0.4.3) + activestorage (= 6.0.4.3) + activesupport (= 6.0.4.3) nokogiri (>= 1.8.5) - actionview (6.0.4.2) - activesupport (= 6.0.4.2) + actionview (6.0.4.3) + activesupport (= 6.0.4.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.2) - activesupport (= 6.0.4.2) + activejob (6.0.4.3) + activesupport (= 6.0.4.3) globalid (>= 0.3.6) - activemodel (6.0.4.2) - activesupport (= 6.0.4.2) - activerecord (6.0.4.2) - activemodel (= 6.0.4.2) - activesupport (= 6.0.4.2) - activestorage (6.0.4.2) - actionpack (= 6.0.4.2) - activejob (= 6.0.4.2) - activerecord (= 6.0.4.2) + activemodel (6.0.4.3) + activesupport (= 6.0.4.3) + activerecord (6.0.4.3) + activemodel (= 6.0.4.3) + activesupport (= 6.0.4.3) + activestorage (6.0.4.3) + actionpack (= 6.0.4.3) + activejob (= 6.0.4.3) + activerecord (= 6.0.4.3) marcel (~> 1.0.0) - activesupport (6.0.4.2) + activesupport (6.0.4.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.4.2) - actioncable (= 6.0.4.2) - actionmailbox (= 6.0.4.2) - actionmailer (= 6.0.4.2) - actionpack (= 6.0.4.2) - actiontext (= 6.0.4.2) - actionview (= 6.0.4.2) - activejob (= 6.0.4.2) - activemodel (= 6.0.4.2) - activerecord (= 6.0.4.2) - activestorage (= 6.0.4.2) - activesupport (= 6.0.4.2) + rails (6.0.4.3) + actioncable (= 6.0.4.3) + actionmailbox (= 6.0.4.3) + actionmailer (= 6.0.4.3) + actionpack (= 6.0.4.3) + actiontext (= 6.0.4.3) + actionview (= 6.0.4.3) + activejob (= 6.0.4.3) + activemodel (= 6.0.4.3) + activerecord (= 6.0.4.3) + activestorage (= 6.0.4.3) + activesupport (= 6.0.4.3) bundler (>= 1.3.0) - railties (= 6.0.4.2) + railties (= 6.0.4.3) sprockets-rails (>= 2.0.0) - railties (6.0.4.2) - actionpack (= 6.0.4.2) - activesupport (= 6.0.4.2) + railties (6.0.4.3) + actionpack (= 6.0.4.3) + activesupport (= 6.0.4.3) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 494384c816711..0db71ca282e01 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index aa6dd78248f10..4a23052224c65 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index 2be442c63d6c8..581d9f6b28eb3 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.4-2", + "version": "6.0.4-3", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index c18b3ed56c8eb..2e6a21185983c 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index e1b13fc799cfb..b411bfc1f2f6b 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 97fa95dcbe11c..1e8e2a25ca588 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index e037b2698c7ed..a83e1d0b8f5b5 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 80d2aa13cba3d..e48509fc57556 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * Fix X_FORWARDED_HOST protection. [CVE-2021-44528] diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index b460e72face59..681ed7f9c76db 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 62c6bb08c803f..27bc2fd4e0250 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index 9222d5449d868..9b614fa5351b2 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index f40795bc831eb..c09193676307c 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.4-2", + "version": "6.0.4-3", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 1e7c8638baf34..5f379ba480198 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 04442ffda443f..6b1e9e899fa3b 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 97322f10118f0..96036f25b4937 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.4-2", + "version": "6.0.4-3", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 90e56c227ab1b..4eb74f8631c43 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index ad84bcf5da341..c160eefc827eb 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index e88fc7d3635fa..a2c0c18614760 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index d4319b0d96179..c7d64847b493e 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 39f6ed5dd9fd8..f01f55f74afa5 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index fca66acb78dd2..51fadf9625140 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 4620781183ce5..47fc9a70c45ad 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index b460ce4d04869..3db02310cba8a 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index 23c76bc14df61..cbe538f6fa508 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.4-2", + "version": "6.0.4-3", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index af3f34497dc99..4132921462df4 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 7c9114417c9f3..43c135f4a5554 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index a856eb128dc86..f3fca55a0f50b 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + +* No changes. + + ## Rails 6.0.4.2 (December 14, 2021) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 1616c3e94e199..0835caf97eefd 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 6.0.4.3 (December 14, 2021) ## + * Allow localhost with a port by default in development [Fixes: #43864] diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index 97b0c1f7ca6d8..9da247af143db 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index 97b0c1f7ca6d8..9da247af143db 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "2" + PRE = "3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From 6a64eda5948ac9cae7237a39f7f4e40ae63c566e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 15 Dec 2021 11:48:32 -0800 Subject: [PATCH 207/244] Merge pull request #43871 from rails/rm-fix-hosts-with-port Allow any allowed host with port --- .../action_dispatch/middleware/host_authorization.rb | 9 +++++---- actionpack/test/dispatch/host_authorization_test.rb | 12 ++++++++++++ railties/lib/rails/application/configuration.rb | 6 +++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index a690cce866dc3..e26e6ddc9742c 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -10,7 +10,8 @@ module ActionDispatch # application will be executed and rendered. If no +response_app+ is given, a # default one will run, which responds with +403 Forbidden+. class HostAuthorization - ALLOWED_HOSTS_IN_DEVELOPMENT = [".localhost", /\A([a-z0-9-]+\.)?localhost:\d+\z/, IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")] + ALLOWED_HOSTS_IN_DEVELOPMENT = [".localhost", IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")] + PORT_REGEX = /(?::\d+)?/.freeze class Permissions # :nodoc: def initialize(hosts) @@ -43,14 +44,14 @@ def sanitize_hosts(hosts) end def sanitize_regexp(host) - /\A#{host}\z/ + /\A#{host}#{PORT_REGEX}\z/ end def sanitize_string(host) if host.start_with?(".") - /\A([a-z0-9-]+\.)?#{Regexp.escape(host[1..-1])}\z/i + /\A([a-z0-9-]+\.)?#{Regexp.escape(host[1..-1])}#{PORT_REGEX}\z/i else - /\A#{Regexp.escape host}\z/i + /\A#{Regexp.escape host}#{PORT_REGEX}\z/i end end end diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb index c0bd0432f4e82..0bacaeb1ea44f 100644 --- a/actionpack/test/dispatch/host_authorization_test.rb +++ b/actionpack/test/dispatch/host_authorization_test.rb @@ -155,6 +155,18 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_match "Success", response.body end + test "hosts with port works" do + @app = ActionDispatch::HostAuthorization.new(App, ["host.test"]) + + get "/", env: { + "HOST" => "host.test:3000", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + test "blocks requests with spoofed X-FORWARDED-HOST" do @app = ActionDispatch::HostAuthorization.new(App, [IPAddr.new("127.0.0.1")]) diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index e87dab37a80b1..984fad89578cf 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -31,7 +31,11 @@ def initialize(*) @filter_parameters = [] @filter_redirect = [] @helpers_paths = [] - @hosts = Rails.env.development? ? ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT : [] + if Rails.env.development? + @hosts = ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT.dup + else + @hosts = [] + end @public_file_server = ActiveSupport::OrderedOptions.new @public_file_server.enabled = true @public_file_server.index_name = "index" From 3cfcb1a5f515c799946bd858a1949ffefda90316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 15 Dec 2021 16:56:48 -0500 Subject: [PATCH 208/244] Merge pull request #43882 from rails/rm-allow-ip-with-port Allow IPs with port in the HostAuthorization middleware --- .../middleware/host_authorization.rb | 36 +++++-- .../test/dispatch/host_authorization_test.rb | 96 +++++++++++++++++++ 2 files changed, 123 insertions(+), 9 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb index e26e6ddc9742c..ca68b0241a769 100644 --- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb +++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb @@ -11,7 +11,15 @@ module ActionDispatch # default one will run, which responds with +403 Forbidden+. class HostAuthorization ALLOWED_HOSTS_IN_DEVELOPMENT = [".localhost", IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")] - PORT_REGEX = /(?::\d+)?/.freeze + PORT_REGEX = /(?::\d+)/ # :nodoc: + IPV4_HOSTNAME = /(?\d+\.\d+\.\d+\.\d+)#{PORT_REGEX}?/ # :nodoc: + IPV6_HOSTNAME = /(?[a-f0-9]*:[a-f0-9.:]+)/i # :nodoc: + IPV6_HOSTNAME_WITH_PORT = /\[#{IPV6_HOSTNAME}\]#{PORT_REGEX}/i # :nodoc: + VALID_IP_HOSTNAME = Regexp.union( # :nodoc: + /\A#{IPV4_HOSTNAME}\z/, + /\A#{IPV6_HOSTNAME}\z/, + /\A#{IPV6_HOSTNAME_WITH_PORT}\z/, + ) class Permissions # :nodoc: def initialize(hosts) @@ -24,11 +32,17 @@ def empty? def allows?(host) @hosts.any? do |allowed| - allowed === host - rescue - # IPAddr#=== raises an error if you give it a hostname instead of - # IP. Treat similar errors as blocked access. - false + if allowed.is_a?(IPAddr) + begin + allowed === extract_hostname(host) + rescue + # IPAddr#=== raises an error if you give it a hostname instead of + # IP. Treat similar errors as blocked access. + false + end + else + allowed === host + end end end @@ -44,16 +58,20 @@ def sanitize_hosts(hosts) end def sanitize_regexp(host) - /\A#{host}#{PORT_REGEX}\z/ + /\A#{host}#{PORT_REGEX}?\z/ end def sanitize_string(host) if host.start_with?(".") - /\A([a-z0-9-]+\.)?#{Regexp.escape(host[1..-1])}#{PORT_REGEX}\z/i + /\A([a-z0-9-]+\.)?#{Regexp.escape(host[1..-1])}#{PORT_REGEX}?\z/i else - /\A#{Regexp.escape host}#{PORT_REGEX}\z/i + /\A#{Regexp.escape host}#{PORT_REGEX}?\z/i end end + + def extract_hostname(host) + host.slice(VALID_IP_HOSTNAME, "host") || host + end end DEFAULT_RESPONSE_APP = -> env do diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb index 0bacaeb1ea44f..57125078c7be0 100644 --- a/actionpack/test/dispatch/host_authorization_test.rb +++ b/actionpack/test/dispatch/host_authorization_test.rb @@ -155,6 +155,102 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest assert_match "Success", response.body end + test "localhost using IPV4 works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "127.0.0.1", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + + test "localhost using IPV4 with port works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "127.0.0.1:3000", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + + test "localhost using IPV4 binding in all addresses works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "0.0.0.0", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + + test "localhost using IPV4 with port binding in all addresses works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "0.0.0.0:3000", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + + test "localhost using IPV6 works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "::1", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + + test "localhost using IPV6 with port works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "[::1]:3000", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + + test "localhost using IPV6 binding in all addresses works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "::", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + + test "localhost using IPV6 with port binding in all addresses works in dev" do + @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT) + + get "/", env: { + "HOST" => "[::]:3000", + "action_dispatch.show_detailed_exceptions" => true + } + + assert_response :ok + assert_match "Success", response.body + end + test "hosts with port works" do @app = ActionDispatch::HostAuthorization.new(App, ["host.test"]) From 34bd524a9d7580ceecbf4a6dd9dced6296e20f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 15 Dec 2021 22:45:01 +0000 Subject: [PATCH 209/244] Preparing for 6.0.4.4 release --- Gemfile.lock | 104 +++++++++--------- RAILS_VERSION | 2 +- actioncable/CHANGELOG.md | 5 + actioncable/lib/action_cable/gem_version.rb | 2 +- actioncable/package.json | 2 +- actionmailbox/CHANGELOG.md | 5 + .../lib/action_mailbox/gem_version.rb | 2 +- actionmailer/CHANGELOG.md | 5 + actionmailer/lib/action_mailer/gem_version.rb | 2 +- actionpack/CHANGELOG.md | 7 +- actionpack/lib/action_pack/gem_version.rb | 2 +- actiontext/CHANGELOG.md | 5 + actiontext/lib/action_text/gem_version.rb | 2 +- actiontext/package.json | 2 +- actionview/CHANGELOG.md | 5 + actionview/lib/action_view/gem_version.rb | 2 +- actionview/package.json | 2 +- activejob/CHANGELOG.md | 5 + activejob/lib/active_job/gem_version.rb | 2 +- activemodel/CHANGELOG.md | 5 + activemodel/lib/active_model/gem_version.rb | 2 +- activerecord/CHANGELOG.md | 5 + activerecord/lib/active_record/gem_version.rb | 2 +- activestorage/CHANGELOG.md | 5 + .../lib/active_storage/gem_version.rb | 2 +- activestorage/package.json | 2 +- activesupport/CHANGELOG.md | 5 + .../lib/active_support/gem_version.rb | 2 +- guides/CHANGELOG.md | 5 + railties/CHANGELOG.md | 5 + railties/lib/rails/gem_version.rb | 2 +- version.rb | 2 +- 32 files changed, 135 insertions(+), 72 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5a22dd468ebe3..6fa3fd59924b9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,79 +32,79 @@ GIT PATH remote: . specs: - actioncable (6.0.4.3) - actionpack (= 6.0.4.3) + actioncable (6.0.4.4) + actionpack (= 6.0.4.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.3) - actionpack (= 6.0.4.3) - activejob (= 6.0.4.3) - activerecord (= 6.0.4.3) - activestorage (= 6.0.4.3) - activesupport (= 6.0.4.3) + actionmailbox (6.0.4.4) + actionpack (= 6.0.4.4) + activejob (= 6.0.4.4) + activerecord (= 6.0.4.4) + activestorage (= 6.0.4.4) + activesupport (= 6.0.4.4) mail (>= 2.7.1) - actionmailer (6.0.4.3) - actionpack (= 6.0.4.3) - actionview (= 6.0.4.3) - activejob (= 6.0.4.3) + actionmailer (6.0.4.4) + actionpack (= 6.0.4.4) + actionview (= 6.0.4.4) + activejob (= 6.0.4.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4.3) - actionview (= 6.0.4.3) - activesupport (= 6.0.4.3) + actionpack (6.0.4.4) + actionview (= 6.0.4.4) + activesupport (= 6.0.4.4) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.3) - actionpack (= 6.0.4.3) - activerecord (= 6.0.4.3) - activestorage (= 6.0.4.3) - activesupport (= 6.0.4.3) + actiontext (6.0.4.4) + actionpack (= 6.0.4.4) + activerecord (= 6.0.4.4) + activestorage (= 6.0.4.4) + activesupport (= 6.0.4.4) nokogiri (>= 1.8.5) - actionview (6.0.4.3) - activesupport (= 6.0.4.3) + actionview (6.0.4.4) + activesupport (= 6.0.4.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.3) - activesupport (= 6.0.4.3) + activejob (6.0.4.4) + activesupport (= 6.0.4.4) globalid (>= 0.3.6) - activemodel (6.0.4.3) - activesupport (= 6.0.4.3) - activerecord (6.0.4.3) - activemodel (= 6.0.4.3) - activesupport (= 6.0.4.3) - activestorage (6.0.4.3) - actionpack (= 6.0.4.3) - activejob (= 6.0.4.3) - activerecord (= 6.0.4.3) + activemodel (6.0.4.4) + activesupport (= 6.0.4.4) + activerecord (6.0.4.4) + activemodel (= 6.0.4.4) + activesupport (= 6.0.4.4) + activestorage (6.0.4.4) + actionpack (= 6.0.4.4) + activejob (= 6.0.4.4) + activerecord (= 6.0.4.4) marcel (~> 1.0.0) - activesupport (6.0.4.3) + activesupport (6.0.4.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - rails (6.0.4.3) - actioncable (= 6.0.4.3) - actionmailbox (= 6.0.4.3) - actionmailer (= 6.0.4.3) - actionpack (= 6.0.4.3) - actiontext (= 6.0.4.3) - actionview (= 6.0.4.3) - activejob (= 6.0.4.3) - activemodel (= 6.0.4.3) - activerecord (= 6.0.4.3) - activestorage (= 6.0.4.3) - activesupport (= 6.0.4.3) + rails (6.0.4.4) + actioncable (= 6.0.4.4) + actionmailbox (= 6.0.4.4) + actionmailer (= 6.0.4.4) + actionpack (= 6.0.4.4) + actiontext (= 6.0.4.4) + actionview (= 6.0.4.4) + activejob (= 6.0.4.4) + activemodel (= 6.0.4.4) + activerecord (= 6.0.4.4) + activestorage (= 6.0.4.4) + activesupport (= 6.0.4.4) bundler (>= 1.3.0) - railties (= 6.0.4.3) + railties (= 6.0.4.4) sprockets-rails (>= 2.0.0) - railties (6.0.4.3) - actionpack (= 6.0.4.3) - activesupport (= 6.0.4.3) + railties (6.0.4.4) + actionpack (= 6.0.4.4) + activesupport (= 6.0.4.4) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -328,8 +328,6 @@ GEM nokogiri (1.11.3) mini_portile2 (~> 2.5.0) racc (~> 1.4) - nokogiri (1.11.3-x86_64-darwin) - racc (~> 1.4) os (1.1.1) parallel (1.20.1) parser (3.0.1.1) @@ -584,4 +582,4 @@ DEPENDENCIES websocket-client-simple! BUNDLED WITH - 2.2.15 + 2.2.32 diff --git a/RAILS_VERSION b/RAILS_VERSION index c3d46182d54d4..529599af18447 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -6.0.4.3 +6.0.4.4 diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 0db71ca282e01..cd92251c2da6a 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index 4a23052224c65..336e612a8271a 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index 581d9f6b28eb3..251a5199457fe 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "6.0.4-3", + "version": "6.0.4-4", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", "files": [ diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index 2e6a21185983c..03f77e26390bb 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index b411bfc1f2f6b..b5e01fe208afa 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 1e8e2a25ca588..1e5096e689f6a 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index a83e1d0b8f5b5..05113b24a894e 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index e48509fc57556..1884f1ec9d3ac 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,6 +1,11 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* Fix issue with host protection not allowing host with port in development. + + ## Rails 6.0.4.3 (December 14, 2021) ## -* No changes. +* Fix issue with host protection not allowing localhost in development. ## Rails 6.0.4.2 (December 14, 2021) ## diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb index 681ed7f9c76db..44426025329f2 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 27bc2fd4e0250..18b8fb8904335 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb index 9b614fa5351b2..0840459e884a0 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index c09193676307c..e77171ff66591 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "6.0.4-3", + "version": "6.0.4-4", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "files": [ diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 5f379ba480198..de0c16f7dc6fa 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 6b1e9e899fa3b..172257fa40d03 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 96036f25b4937..e76092863d066 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "6.0.4-3", + "version": "6.0.4-4", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", "files": [ diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 4eb74f8631c43..71a47a13ac80d 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb index c160eefc827eb..4c9cef6f9be7b 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index a2c0c18614760..254b26911d36e 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb index c7d64847b493e..dfc6e58235353 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index f01f55f74afa5..2106d69832fa7 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index 51fadf9625140..75b004eceaeb9 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 47fc9a70c45ad..c1dd9e408d8c5 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb index 3db02310cba8a..18e8fe6c6067d 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index cbe538f6fa508..a0ef6c222ed3e 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "6.0.4-3", + "version": "6.0.4-4", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", "files": [ diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 4132921462df4..6122a441c4980 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index 43c135f4a5554..f7f853fcfeb28 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index f3fca55a0f50b..acb02eeca0d42 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 0835caf97eefd..0c937553af39f 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 6.0.4.4 (December 15, 2021) ## + +* No changes. + + ## Rails 6.0.4.3 (December 14, 2021) ## * Allow localhost with a port by default in development diff --git a/railties/lib/rails/gem_version.rb b/railties/lib/rails/gem_version.rb index 9da247af143db..7d0eefee31be7 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index 9da247af143db..7d0eefee31be7 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 6 MINOR = 0 TINY = 4 - PRE = "3" + PRE = "4" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From 2715b5db76e78620a018269e7cc41330ba6752c0 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 17 Dec 2021 20:25:16 +0900 Subject: [PATCH 210/244] Merge pull request #43910 from p8/guides/fix-blog-link Update URLs for the blog --- RELEASING_RAILS.md | 2 +- guides/source/layout.html.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASING_RAILS.md b/RELEASING_RAILS.md index e4026c7d32ea7..ecdfd7e3e8c60 100644 --- a/RELEASING_RAILS.md +++ b/RELEASING_RAILS.md @@ -158,7 +158,7 @@ break existing applications. If you used Markdown format for your email, you can just paste it into the blog. -* https://weblog.rubyonrails.org +* https://rubyonrails.org/blog ### Post the announcement to the Rails Twitter account. diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb index 477be76ebc039..7a646bde6ca28 100644 --- a/guides/source/layout.html.erb +++ b/guides/source/layout.html.erb @@ -35,7 +35,7 @@ More Ruby on Rails