From 7b8546572e3c082140b5958b78d088efe6874af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 19 Nov 2021 23:30:17 +0000 Subject: [PATCH 001/455] Fix warnings and wrong indentation --- activerecord/test/cases/bind_parameter_test.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb index b7fea26212ada..f14cb9eed55c4 100644 --- a/activerecord/test/cases/bind_parameter_test.rb +++ b/activerecord/test/cases/bind_parameter_test.rb @@ -283,18 +283,18 @@ def debug(str) def assert_filtered_log_binds(binds) payload = { - name: "SQL", - sql: "select * from users where auth_token = ?", - binds: binds, - type_casted_binds: @connection.send(:type_casted_binds, binds) + name: "SQL", + sql: "select * from users where auth_token = ?", + binds: binds, + type_casted_binds: @connection.send(:type_casted_binds, binds) } event = ActiveSupport::Notifications::Event.new( - "foo", - Time.now, - Time.now, - 123, - payload) + "foo", + Time.now, + Time.now, + 123, + payload) logger = Class.new(ActiveRecord::LogSubscriber) { attr_reader :debugs From 60e9fd6106027296b4409e9028e0ed6c50091f33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 19 Nov 2021 23:32:42 +0000 Subject: [PATCH 002/455] Remove deprecated `ActiveRecord::Base#remove_connection` --- activerecord/CHANGELOG.md | 6 +++++- .../abstract/connection_handler.rb | 9 --------- .../connection_adapters/connection_handler_test.rb | 12 ------------ guides/source/7_0_release_notes.md | 2 ++ 4 files changed, 7 insertions(+), 22 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 15ae3a3103776..29d2651639ffb 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Remove deprecated `ActiveRecord::Base#remove_connection`. + + *Rafael Mendonça França* + * Load STI Models in fixtures Data from Fixtures now loads based on the specific class for models with @@ -5,7 +9,7 @@ the value of these fields was not parsed and remained `nil` *Andres Howard* - + * `#authenticate` returns false when the password is blank instead of raising an error. *Muhammad Muhammad Ibrahim* diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb index 68a305fb12250..c8ed812e447e9 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb @@ -218,15 +218,6 @@ def connected?(spec_name, role: ActiveRecord::Base.current_role, shard: ActiveRe pool && pool.connected? end - # Remove the connection for this class. This will close the active - # connection and the defined connection (if they exist). The result - # can be used as an argument for #establish_connection, for easily - # re-establishing the connection. - def remove_connection(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) - remove_connection_pool(owner, role: role, shard: shard)&.configuration_hash - end - deprecate remove_connection: "Use #remove_connection_pool, which now returns a DatabaseConfig object instead of a Hash" - def remove_connection_pool(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) if pool_manager = get_pool_manager(owner) pool_config = pool_manager.remove_pool_config(role, shard) diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb index 0650f1fe2f07a..1c00a6a9adb87 100644 --- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb +++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb @@ -148,18 +148,6 @@ def test_establish_connection_using_2_level_config_defaults_to_default_env_prima ENV["RAILS_ENV"] = previous_env ActiveRecord::Base.establish_connection(:arunit) end - - def test_remove_connection_is_deprecated - expected = @handler.retrieve_connection_pool(@owner_name).db_config.configuration_hash - - config_hash = assert_deprecated do - @handler.remove_connection(@owner_name) - end - - assert_equal expected, config_hash - ensure - ActiveRecord::Base.establish_connection(:arunit) - end end def test_establish_connection_using_two_level_configurations diff --git a/guides/source/7_0_release_notes.md b/guides/source/7_0_release_notes.md index b8ee83db42107..58fc3377aec3f 100644 --- a/guides/source/7_0_release_notes.md +++ b/guides/source/7_0_release_notes.md @@ -264,6 +264,8 @@ Please refer to the [Changelog][active-job] for detailed changes. * Remove deprecated `ActiveRecord::Result#map!` and `ActiveRecord::Result#collect!`. +* Remove deprecated `ActiveRecord::Base#remove_connection`. + ### Deprecations * Deprecated `Rails.config.active_job.skip_after_callbacks_if_terminated`. From 126319ec3d62b8d0d86bec0c88c3555007f9d4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 3 Dec 2021 02:21:49 +0000 Subject: [PATCH 003/455] Remove deprecated `ActiveRecord::Connection#allowed_index_name_length` --- activerecord/CHANGELOG.md | 4 ++++ .../connection_adapters/abstract/database_limits.rb | 10 ---------- activerecord/test/cases/adapter_test.rb | 4 ---- guides/source/7_0_release_notes.md | 4 +++- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 29d2651639ffb..55d411898ab08 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`. + + *Rafael Mendonça França* + * Remove deprecated `ActiveRecord::Base#remove_connection`. *Rafael Mendonça França* diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb index b1ff8eec743e6..b37e9fc095dfa 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb @@ -12,16 +12,6 @@ def table_alias_length max_identifier_length end - # Returns the maximum allowed length for an index name. This - # limit is enforced by \Rails and is less than or equal to - # #index_name_length. The gap between - # #index_name_length is to allow internal \Rails - # operations to use prefixes in temporary operations. - def allowed_index_name_length - index_name_length - end - deprecate :allowed_index_name_length - # Returns the maximum length of an index name. def index_name_length max_identifier_length diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 3175f42eba83f..9311dca076c70 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -301,10 +301,6 @@ def test_select_methods_passing_a_relation assert_equal "special_db_type", @connection.type_to_sql(:special_db_type) end - def test_allowed_index_name_length_is_deprecated - assert_deprecated { @connection.allowed_index_name_length } - end - unless current_adapter?(:OracleAdapter) def test_in_clause_length_is_deprecated assert_deprecated { @connection.in_clause_length } diff --git a/guides/source/7_0_release_notes.md b/guides/source/7_0_release_notes.md index 58fc3377aec3f..70a8fec9245c0 100644 --- a/guides/source/7_0_release_notes.md +++ b/guides/source/7_0_release_notes.md @@ -149,9 +149,11 @@ Please refer to the [Changelog][active-record] for detailed changes. * Remove deprecated `Tasks::DatabaseTasks.current_config`. +* Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`. + ### Deprecations -* Deprecated `Tasks::DatabaseTasks.:schema_file_type`. +* Deprecated `Tasks::DatabaseTasks.schema_file_type`. ### Notable changes From 887dc810d18b3be04d56975d1a488b5ebac36f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 3 Dec 2021 02:27:54 +0000 Subject: [PATCH 004/455] Remove deprecated `ActiveRecord::Connection#:in_clause_length` --- activerecord/CHANGELOG.md | 4 ++++ .../connection_adapters/abstract/database_limits.rb | 7 ------- activerecord/test/cases/adapter_test.rb | 6 ------ guides/source/7_0_release_notes.md | 2 ++ 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 55d411898ab08..20a9f288caed3 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Remove deprecated `ActiveRecord::Connection#:in_clause_length`. + + *Rafael Mendonça França* + * Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`. *Rafael Mendonça França* diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb index b37e9fc095dfa..f088c4c97c059 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb @@ -17,13 +17,6 @@ def index_name_length max_identifier_length end - # Returns the maximum number of elements in an IN (x,y,z) clause. - # +nil+ means no limit. - def in_clause_length - nil - end - deprecate :in_clause_length - private def bind_params_length 65535 diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 9311dca076c70..b725bd294450f 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -300,12 +300,6 @@ def test_select_methods_passing_a_relation test "type_to_sql returns a String for unmapped types" do assert_equal "special_db_type", @connection.type_to_sql(:special_db_type) end - - unless current_adapter?(:OracleAdapter) - def test_in_clause_length_is_deprecated - assert_deprecated { @connection.in_clause_length } - end - end end class AdapterForeignKeyTest < ActiveRecord::TestCase diff --git a/guides/source/7_0_release_notes.md b/guides/source/7_0_release_notes.md index 70a8fec9245c0..61f1854131e40 100644 --- a/guides/source/7_0_release_notes.md +++ b/guides/source/7_0_release_notes.md @@ -151,6 +151,8 @@ Please refer to the [Changelog][active-record] for detailed changes. * Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`. +* Remove deprecated `ActiveRecord::Connection#:in_clause_length`. + ### Deprecations * Deprecated `Tasks::DatabaseTasks.schema_file_type`. From 25c4cf82cdb90ad26df96412c25d25e3eda20eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 3 Dec 2021 02:35:07 +0000 Subject: [PATCH 005/455] Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name` --- activerecord/CHANGELOG.md | 6 +++++- .../database_configurations/database_config.rb | 5 ----- activerecord/test/cases/database_configurations_test.rb | 8 -------- guides/source/7_0_release_notes.md | 4 +++- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 20a9f288caed3..87ba34e21a9f7 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,4 +1,8 @@ -* Remove deprecated `ActiveRecord::Connection#:in_clause_length`. +* Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`. + + *Rafael Mendonça França* + +* Remove deprecated `ActiveRecord::Connection#in_clause_length`. *Rafael Mendonça França* diff --git a/activerecord/lib/active_record/database_configurations/database_config.rb b/activerecord/lib/active_record/database_configurations/database_config.rb index 163fc6bbe3e10..be9e534f15866 100644 --- a/activerecord/lib/active_record/database_configurations/database_config.rb +++ b/activerecord/lib/active_record/database_configurations/database_config.rb @@ -15,11 +15,6 @@ def initialize(env_name, name) @name = name end - def spec_name - @name - end - deprecate spec_name: "please use name instead" - def adapter_method "#{adapter}_connection" end diff --git a/activerecord/test/cases/database_configurations_test.rb b/activerecord/test/cases/database_configurations_test.rb index 4106f3da74592..72f2a82d8cd6b 100644 --- a/activerecord/test/cases/database_configurations_test.rb +++ b/activerecord/test/cases/database_configurations_test.rb @@ -94,14 +94,6 @@ def test_unsupported_method_raises end end - def test_spec_name_getter_is_deprecated - db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary") - - assert_deprecated do - assert_equal "primary", db_config.spec_name - end - end - def test_hidden_returns_replicas config = { "default_env" => { diff --git a/guides/source/7_0_release_notes.md b/guides/source/7_0_release_notes.md index 61f1854131e40..205ca499ae37b 100644 --- a/guides/source/7_0_release_notes.md +++ b/guides/source/7_0_release_notes.md @@ -151,7 +151,9 @@ Please refer to the [Changelog][active-record] for detailed changes. * Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`. -* Remove deprecated `ActiveRecord::Connection#:in_clause_length`. +* Remove deprecated `ActiveRecord::Connection#in_clause_length`. + +* Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`. ### Deprecations From fdb0b29ad9e25965f506e340ea59b33815927378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 3 Dec 2021 03:39:20 +0000 Subject: [PATCH 006/455] Remove deprecated `config` in `dbconsole` --- guides/source/7_0_release_notes.md | 2 ++ railties/CHANGELOG.md | 4 ++++ railties/lib/rails/commands/dbconsole/dbconsole_command.rb | 5 ----- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/guides/source/7_0_release_notes.md b/guides/source/7_0_release_notes.md index 205ca499ae37b..c09a34fb8dd16 100644 --- a/guides/source/7_0_release_notes.md +++ b/guides/source/7_0_release_notes.md @@ -30,6 +30,8 @@ Please refer to the [Changelog][railties] for detailed changes. ### Removals +* Remove deprecated `config` in `dbconsole`. + ### Deprecations ### Notable changes diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 803f61d6f57bb..7330745db5dad 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,7 @@ +* Remove deprecated `config` in `dbconsole`. + + *Rafael Mendonça França* + * Change default `X-XSS-Protection` header to disable XSS auditor This header has been deprecated and the XSS auditor it triggered diff --git a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb index ba5f70cd84a34..bd418a73d10d6 100644 --- a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb +++ b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb @@ -94,11 +94,6 @@ def start end end - def config - db_config.configuration_hash - end - deprecate config: "please use db_config.configuration_hash" - def db_config return @db_config if defined?(@db_config) From c7525a1d7f96cb843254a941452b0bfd5d9916ed Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 3 Dec 2021 11:12:04 +0100 Subject: [PATCH 007/455] Distribute both ESM and CJS version And make sure module refers to the ESM version. --- activestorage/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activestorage/package.json b/activestorage/package.json index ec0f774bc79f8..60e345d1e3668 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -2,8 +2,8 @@ "name": "@rails/activestorage", "version": "7.0.0-alpha2", "description": "Attach cloud and local files in Rails applications", + "module": "app/assets/javascripts/activestorage.esm.js", "main": "app/assets/javascripts/activestorage.js", - "type": "module", "files": [ "app/assets/javascripts/*.js", "src/*.js" From 6afb7623138b25c0cd307e3af5cecb704c0a9e97 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 3 Dec 2021 11:37:03 +0100 Subject: [PATCH 008/455] Add -c as alias for --css --- railties/lib/rails/generators/rails/app/app_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 6f01c87ec7bf2..32b18311953f4 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -266,7 +266,7 @@ class AppGenerator < AppBase class_option :api, type: :boolean, desc: "Preconfigure smaller stack for API only apps" class_option :minimal, type: :boolean, desc: "Preconfigure a minimal rails app" class_option :javascript, type: :string, aliases: "-j", default: "importmap", desc: "Choose JavaScript approach [options: importmap (default), webpack, esbuild, rollup]" - class_option :css, type: :string, desc: "Choose CSS processor [options: tailwind, bootstrap, bulma, postcss, sass... check https://github.com/rails/cssbundling-rails]" + class_option :css, type: :string, aliases: "-c", desc: "Choose CSS processor [options: tailwind, bootstrap, bulma, postcss, sass... check https://github.com/rails/cssbundling-rails]" class_option :skip_bundle, type: :boolean, aliases: "-B", default: false, desc: "Don't run bundle install" def initialize(*args) From 94359bffa512cf5ed5d703252c1d8377fe63cca0 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 3 Dec 2021 11:56:19 +0100 Subject: [PATCH 009/455] Use latest versions for dependencies --- railties/lib/rails/generators/app_base.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 9e2b564218196..ec0c47096ae30 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -172,10 +172,10 @@ def asset_pipeline_gemfile_entry return [] if options[:skip_asset_pipeline] if options[:asset_pipeline] == "sprockets" - GemfileEntry.version "sprockets-rails", ">= 2.0.0", + GemfileEntry.version "sprockets-rails", ">= 3.4.1", "The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]" elsif options[:asset_pipeline] == "propshaft" - GemfileEntry.version "propshaft", ">= 0.1.7", "The modern asset pipeline for Rails [https://github.com/rails/propshaft/]" + GemfileEntry.version "propshaft", ">= 0.4.1", "The modern asset pipeline for Rails [https://github.com/rails/propshaft/]" else [] end @@ -307,16 +307,16 @@ def rails_version_specifier(gem_version = Rails.gem_version) def jbuilder_gemfile_entry return [] if options[:skip_jbuilder] comment = "Build JSON APIs with ease [https://github.com/rails/jbuilder]" - GemfileEntry.new "jbuilder", "~> 2.7", comment, {}, options[:api] + GemfileEntry.new "jbuilder", "~> 2.11", comment, {}, options[:api] end def javascript_gemfile_entry return [] if options[:skip_javascript] if adjusted_javascript_option == "importmap" - GemfileEntry.version("importmap-rails", ">= 0.3.4", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]") + GemfileEntry.version("importmap-rails", ">= 0.9.2", "Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]") else - GemfileEntry.version "jsbundling-rails", ">= 0.2.0", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]" + GemfileEntry.version "jsbundling-rails", ">= 0.2.2", "Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]" end end @@ -324,10 +324,10 @@ def hotwire_gemfile_entry return [] if options[:skip_javascript] || options[:skip_hotwire] turbo_rails_entry = - GemfileEntry.version("turbo-rails", ">= 0.7.11", "Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]") + GemfileEntry.version("turbo-rails", ">= 0.9.0", "Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]") stimulus_rails_entry = - GemfileEntry.version("stimulus-rails", ">= 0.4.0", "Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]") + GemfileEntry.version("stimulus-rails", ">= 0.7.3", "Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]") [ turbo_rails_entry, stimulus_rails_entry ] end @@ -350,9 +350,9 @@ def css_gemfile_entry return [] unless options[:css] if !using_node? && options[:css] == "tailwind" - GemfileEntry.version("tailwindcss-rails", ">= 0.4.3", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]") + GemfileEntry.version("tailwindcss-rails", ">= 0.5.3", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]") else - GemfileEntry.version("cssbundling-rails", ">= 0.1.0", "Bundle and process CSS [https://github.com/rails/cssbundling-rails]") + GemfileEntry.version("cssbundling-rails", ">= 0.2.7", "Bundle and process CSS [https://github.com/rails/cssbundling-rails]") end end From 0ea3a5f458564ad690836fd1347597addf5ddc7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 3 Dec 2021 15:28:21 -0500 Subject: [PATCH 010/455] Merge pull request #43771 from jonathanhefner/flakey-activerecord-dirty_test Fix flakey test in Active Record dirty_test.rb --- activerecord/test/cases/dirty_test.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index da710a322941b..0850b619257b4 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -948,10 +948,11 @@ def check_around assert_equal "Boeing", aircraft.name aircraft.save! + expected_manufactured_at = Time.now aircraft.reload assert_equal "Boeing", aircraft.name - assert_equal Time.now.utc.strftime("%Y-%m-%d %H:%M:%S"), aircraft.manufactured_at.strftime("%Y-%m-%d %H:%M:%S") + assert_in_delta expected_manufactured_at, aircraft.manufactured_at, 1 end end From 73c401b8be810b57ca7b1fb67720e9e3e3e5c504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 3 Dec 2021 15:32:32 -0500 Subject: [PATCH 011/455] Merge pull request #43591 from SkipKayhil/fix-actioncable-js-module fix actioncable module field in package.json --- actioncable/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actioncable/package.json b/actioncable/package.json index e2b618459285a..ca0b3194adbe2 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -2,7 +2,7 @@ "name": "@rails/actioncable", "version": "7.0.0-alpha2", "description": "WebSocket framework for Ruby on Rails.", - "module": "app/javascript/action_cable/index.js", + "module": "app/assets/javascripts/actioncable.esm.js", "main": "app/assets/javascripts/actioncable.js", "files": [ "app/assets/javascripts/*.js", From 0f47b24defc981add26c9e8c64158b277e55c36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 3 Dec 2021 15:48:53 -0500 Subject: [PATCH 012/455] Merge pull request #43774 from sambostock/document-deprecation-test-helpers Document `ActiveSupport::Testing::Deprecation` --- activesupport/CHANGELOG.md | 4 ++ .../lib/active_support/testing/deprecation.rb | 53 ++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 0a6feb752b956..d7cb3639c6f56 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,7 @@ +* Document `ActiveSupport::Testing::Deprecation`. + + *Sam Bostock & Sam Jordan* + * Add `Pathname#existence`. ```ruby diff --git a/activesupport/lib/active_support/testing/deprecation.rb b/activesupport/lib/active_support/testing/deprecation.rb index b16bf2bdc6380..f762d24377f4a 100644 --- a/activesupport/lib/active_support/testing/deprecation.rb +++ b/activesupport/lib/active_support/testing/deprecation.rb @@ -4,7 +4,30 @@ module ActiveSupport module Testing - module Deprecation # :nodoc: + module Deprecation + # Asserts that a matching deprecation warning was emitted by the given deprecator during the execution of the yielded block. + # + # assert_deprecated(/foo/, CustomDeprecator) do + # CustomDeprecator.warn "foo should no longer be used" + # end + # + # The +match+ object may be a +Regexp+, or +String+ appearing in the message. + # + # assert_deprecated('foo', CustomDeprecator) do + # CustomDeprecator.warn "foo should no longer be used" + # end + # + # If the +match+ is omitted (or explicitly +nil+), any deprecation warning will match. + # + # assert_deprecated(nil, CustomDeprecator) do + # CustomDeprecator.warn "foo should no longer be used" + # end + # + # If no +deprecator+ is given, defaults to ActiveSupport::Deprecation. + # + # assert_deprecated do + # ActiveSupport::Deprecation.warn "foo should no longer be used" + # end def assert_deprecated(match = nil, deprecator = nil, &block) result, warnings = collect_deprecations(deprecator, &block) assert !warnings.empty?, "Expected a deprecation warning within the block but received none" @@ -15,12 +38,40 @@ def assert_deprecated(match = nil, deprecator = nil, &block) result end + # Asserts that no deprecation warnings are emitted by the given deprecator during the execution of the yielded block. + # + # assert_not_deprecated(CustomDeprecator) do + # CustomDeprecator.warn "message" # fails assertion + # end + # + # If no +deprecator+ is given, defaults to ActiveSupport::Deprecation. + # + # assert_not_deprecated do + # ActiveSupport::Deprecation.warn "message" # fails assertion + # end + # + # assert_not_deprecated do + # CustomDeprecator.warn "message" # passes assertion + # end def assert_not_deprecated(deprecator = nil, &block) result, deprecations = collect_deprecations(deprecator, &block) assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}" result end + # Returns an array of all the deprecation warnings emitted by the given + # +deprecator+ during the execution of the yielded block. + # + # collect_deprecations(CustomDeprecator) do + # CustomDeprecator.warn "message" + # end # => ["message"] + # + # If no +deprecator+ is given, defaults to ActiveSupport::Deprecation. + # + # collect_deprecations do + # CustomDeprecator.warn "custom message" + # ActiveSupport::Deprecation.warn "message" + # end # => ["message"] def collect_deprecations(deprecator = nil) deprecator ||= ActiveSupport::Deprecation old_behavior = deprecator.behavior From a687128775696e6520658080819e457354473523 Mon Sep 17 00:00:00 2001 From: Kasper Timm Hansen Date: Sat, 4 Dec 2021 01:20:05 +0100 Subject: [PATCH 013/455] Flip blob question to allow us to exit early --- activestorage/app/models/active_storage/blob.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb index fac5ca5239a26..a88c6a485393b 100644 --- a/activestorage/app/models/active_storage/blob.rb +++ b/activestorage/app/models/active_storage/blob.rb @@ -149,9 +149,7 @@ def scope_for_strict_loading # :nodoc: # Concatenate multiple blobs into a single "composed" blob. def compose(filename:, blobs:, content_type: nil, metadata: nil) - unless blobs.all?(&:persisted?) - raise(ActiveRecord::RecordNotSaved, "All blobs must be persisted.") - end + raise ActiveRecord::RecordNotSaved, "All blobs must be persisted." if blobs.any?(&:new_record?) content_type ||= blobs.pluck(:content_type).compact.first From 09acf8e9e76eb9658c3c521f0efe66c12af02ce4 Mon Sep 17 00:00:00 2001 From: Kasper Timm Hansen Date: Sat, 4 Dec 2021 02:14:48 +0100 Subject: [PATCH 014/455] compose is primarily meant to take blobs so make them a positional argument --- activestorage/app/models/active_storage/blob.rb | 2 +- activestorage/test/models/blob_test.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb index a88c6a485393b..85ed3eb184df1 100644 --- a/activestorage/app/models/active_storage/blob.rb +++ b/activestorage/app/models/active_storage/blob.rb @@ -148,7 +148,7 @@ def scope_for_strict_loading # :nodoc: end # Concatenate multiple blobs into a single "composed" blob. - def compose(filename:, blobs:, content_type: nil, metadata: nil) + def compose(blobs, filename:, content_type: nil, metadata: nil) raise ActiveRecord::RecordNotSaved, "All blobs must be persisted." if blobs.any?(&:new_record?) content_type ||= blobs.pluck(:content_type).compact.first diff --git a/activestorage/test/models/blob_test.rb b/activestorage/test/models/blob_test.rb index c18c604989d2a..749137e4181a5 100644 --- a/activestorage/test/models/blob_test.rb +++ b/activestorage/test/models/blob_test.rb @@ -86,7 +86,7 @@ class ActiveStorage::BlobTest < ActiveSupport::TestCase test "compose" do blobs = 3.times.map { create_blob(data: "123", filename: "numbers.txt", content_type: "text/plain", identify: false) } - blob = ActiveStorage::Blob.compose(filename: "all_numbers.txt", blobs: blobs) + blob = ActiveStorage::Blob.compose(blobs, filename: "all_numbers.txt") assert_equal "123123123", blob.download assert_equal "text/plain", blob.content_type @@ -99,7 +99,7 @@ class ActiveStorage::BlobTest < ActiveSupport::TestCase blobs = 3.times.map { create_blob(data: "123", filename: "numbers.txt", content_type: "text/plain", identify: false).dup } error = assert_raises(ActiveRecord::RecordNotSaved) do - ActiveStorage::Blob.compose(filename: "all_numbers.txt", blobs: blobs) + ActiveStorage::Blob.compose(blobs, filename: "all_numbers.txt") end assert_equal "All blobs must be persisted.", error.message end From 4520ba20acca4320024dcc0b55c497f898bb6064 Mon Sep 17 00:00:00 2001 From: Kasper Timm Hansen Date: Sat, 4 Dec 2021 02:19:19 +0100 Subject: [PATCH 015/455] [ci skip] compose no longer returns the checksum, remove comment --- activestorage/lib/active_storage/service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activestorage/lib/active_storage/service.rb b/activestorage/lib/active_storage/service.rb index fc8906b6c43b3..f4794cffb82e1 100644 --- a/activestorage/lib/active_storage/service.rb +++ b/activestorage/lib/active_storage/service.rb @@ -90,7 +90,7 @@ def open(*args, **options, &block) ActiveStorage::Downloader.new(self).open(*args, **options, &block) end - # Concatenate multiple files into a single "composed" file. Returns the checksum of the composed file. + # Concatenate multiple files into a single "composed" file. def compose(*source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) raise NotImplementedError end From 3add1161d3b34f48daedc4e567a644f3a96c0fd5 Mon Sep 17 00:00:00 2001 From: Kasper Timm Hansen Date: Sat, 4 Dec 2021 02:25:42 +0100 Subject: [PATCH 016/455] Pass an array through our stack, don't bother converting back & forth Users aren't likely to pass non-array values here anyway. --- activestorage/app/models/active_storage/blob.rb | 6 +++--- activestorage/lib/active_storage/service.rb | 2 +- .../lib/active_storage/service/azure_storage_service.rb | 2 +- activestorage/lib/active_storage/service/disk_service.rb | 2 +- activestorage/lib/active_storage/service/gcs_service.rb | 2 +- activestorage/lib/active_storage/service/s3_service.rb | 2 +- activestorage/test/service/shared_service_tests.rb | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb index 85ed3eb184df1..5c00b141abac2 100644 --- a/activestorage/app/models/active_storage/blob.rb +++ b/activestorage/app/models/active_storage/blob.rb @@ -154,7 +154,7 @@ def compose(blobs, filename:, content_type: nil, metadata: nil) content_type ||= blobs.pluck(:content_type).compact.first new(filename: filename, content_type: content_type, metadata: metadata, byte_size: blobs.sum(&:byte_size)).tap do |combined_blob| - combined_blob.compose(*blobs.pluck(:key)) + combined_blob.compose(blobs.pluck(:key)) combined_blob.save! end end @@ -268,9 +268,9 @@ def upload_without_unfurling(io) # :nodoc: service.upload key, io, checksum: checksum, **service_metadata end - def compose(*keys) # :nodoc: + def compose(keys) # :nodoc: self.composed = true - service.compose(*keys, key, **service_metadata) + service.compose(keys, key, **service_metadata) end # Downloads the file associated with this blob. If no block is given, the entire file is read into memory and returned. diff --git a/activestorage/lib/active_storage/service.rb b/activestorage/lib/active_storage/service.rb index f4794cffb82e1..b0e33179bec55 100644 --- a/activestorage/lib/active_storage/service.rb +++ b/activestorage/lib/active_storage/service.rb @@ -91,7 +91,7 @@ def open(*args, **options, &block) end # Concatenate multiple files into a single "composed" file. - def compose(*source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) + def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) raise NotImplementedError end diff --git a/activestorage/lib/active_storage/service/azure_storage_service.rb b/activestorage/lib/active_storage/service/azure_storage_service.rb index 33c65a2053fde..3bd8edce15ef3 100644 --- a/activestorage/lib/active_storage/service/azure_storage_service.rb +++ b/activestorage/lib/active_storage/service/azure_storage_service.rb @@ -107,7 +107,7 @@ def headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disp { "Content-Type" => content_type, "Content-MD5" => checksum, "x-ms-blob-content-disposition" => content_disposition, "x-ms-blob-type" => "BlockBlob", **custom_metadata_headers(custom_metadata) } end - def compose(*source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) + def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename client.create_append_blob( diff --git a/activestorage/lib/active_storage/service/disk_service.rb b/activestorage/lib/active_storage/service/disk_service.rb index 4ad74eff0202e..271b430ea577c 100644 --- a/activestorage/lib/active_storage/service/disk_service.rb +++ b/activestorage/lib/active_storage/service/disk_service.rb @@ -100,7 +100,7 @@ def path_for(key) # :nodoc: File.join root, folder_for(key), key end - def compose(*source_keys, destination_key, **) + def compose(source_keys, destination_key, **) File.open(make_path_for(destination_key), "w") do |destination_file| source_keys.each do |source_key| File.open(path_for(source_key), "rb") do |source_file| diff --git a/activestorage/lib/active_storage/service/gcs_service.rb b/activestorage/lib/active_storage/service/gcs_service.rb index 969ca7b12f3ce..f438e0fee8b98 100644 --- a/activestorage/lib/active_storage/service/gcs_service.rb +++ b/activestorage/lib/active_storage/service/gcs_service.rb @@ -134,7 +134,7 @@ def headers_for_direct_upload(key, checksum:, filename: nil, disposition: nil, c headers end - def compose(*source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) + def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) bucket.compose(source_keys, destination_key).update do |file| file.content_type = content_type file.content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename diff --git a/activestorage/lib/active_storage/service/s3_service.rb b/activestorage/lib/active_storage/service/s3_service.rb index f8ce56e0d4983..87bb6d0753772 100644 --- a/activestorage/lib/active_storage/service/s3_service.rb +++ b/activestorage/lib/active_storage/service/s3_service.rb @@ -95,7 +95,7 @@ def headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disp { "Content-Type" => content_type, "Content-MD5" => checksum, "Content-Disposition" => content_disposition, **custom_metadata_headers(custom_metadata) } end - def compose(*source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) + def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename object_for(destination_key).upload_stream( diff --git a/activestorage/test/service/shared_service_tests.rb b/activestorage/test/service/shared_service_tests.rb index 4a3db65f1841b..4695af821a927 100644 --- a/activestorage/test/service/shared_service_tests.rb +++ b/activestorage/test/service/shared_service_tests.rb @@ -153,7 +153,7 @@ module ActiveStorage::Service::SharedServiceTests ) end destination_key = SecureRandom.base58(24) - @service.compose(*keys, destination_key) + @service.compose(keys, destination_key) assert_equal "Together", @service.download(destination_key) end From afb6347ef58bb713e38f0e616aab3a3215b2b648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Sat, 4 Dec 2021 14:58:01 -0500 Subject: [PATCH 017/455] Merge pull request #43777 from rails/use-default-application-css-even-without-sprockets Use default application css even without sprockets --- railties/lib/rails/generators/rails/app/app_generator.rb | 2 ++ railties/test/generators/app_generator_test.rb | 1 - railties/test/generators/shared_generator_tests.rb | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 32b18311953f4..ea595964970b4 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -447,7 +447,9 @@ def delete_assets_initializer_skipping_sprockets if skip_sprockets? remove_file "config/initializers/assets.rb" remove_file "app/assets/config/manifest.js" + remove_dir "app/assets/config" remove_file "app/assets/stylesheets/application.css" + create_file "app/assets/stylesheets/application.css", "/* Application styles */\n" unless options[:api] end end diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index d77f06ad71338..552db95788f94 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -241,7 +241,6 @@ def test_app_update_does_not_generate_assets_initializer_when_sprockets_is_not_u assert_no_file "#{app_root}/config/initializers/assets.rb" assert_no_file "#{app_root}/app/assets/config/manifest.js" - assert_no_file "#{app_root}/app/assets/stylesheets/application.css" end end diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index d5b02f80b7de3..a804de1e6ea12 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -295,7 +295,6 @@ def test_generator_when_sprockets_is_not_used assert_no_file "#{application_path}/config/initializers/assets.rb" assert_no_file "#{application_path}/app/assets/config/manifest.js" - assert_no_file "#{application_path}/app/assets/stylesheets/application.css" assert_file "Gemfile" do |content| assert_no_match(/sass-rails/, content) From ef7e3c46c4417167e7ac702471e537f4e8b9def8 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sun, 5 Dec 2021 13:27:02 +0100 Subject: [PATCH 018/455] Document suggestions for debugging --- .../lib/rails/generators/rails/app/templates/Gemfile.tt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt index 2e763124755c1..4caa0d8e987b9 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt @@ -44,7 +44,13 @@ gem "bootsnap", ">= 1.4.4", require: false <% if RUBY_ENGINE == "ruby" -%> group :development, :test do - # Start debugger with binding.b [https://github.com/ruby/debug] + # Writing `binding.irb` in a spot to debug gives you a console. If the project + # depends on Pry, `binding.pry` is also available. For them to work, you don't + # need to depend on the `debug` gem. + # + # To get a proper debugger, depend on the `debug` gem and execute `binding.b`. + # However, better eager load the application, because `debug` and autoloading + # are not fully compatible. See https://github.com/ruby/debug/issues/408. gem "debug", ">= 1.0.0", platforms: %i[ mri mingw x64_mingw ] end <% end -%> From b4ddcb266e7c142c9b4dd0688b149412ed008374 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Mon, 6 Dec 2021 12:42:39 +0100 Subject: [PATCH 019/455] Revise docs/comments for the debug gem --- guides/source/debugging_rails_applications.md | 29 +++++++++++++++++++ .../generators/rails/app/templates/Gemfile.tt | 8 +---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md index d47406d5bddaa..70165b8bc65a2 100644 --- a/guides/source/debugging_rails_applications.md +++ b/guides/source/debugging_rails_applications.md @@ -470,6 +470,35 @@ class variables: @@raise_on_missing_translations @@raise_on_open_redirects You can find more commands and configuration options from its [documentation](https://github.com/ruby/debug). +#### Autoloading Caveat + +Debugging with `debug` works fine most of the time, but there's an edge case: If you evaluate an expression in the console that autoloads a namespace defined in a file, constants in that namespace won't be found. + +For example, if the application has these two files: + +```ruby +# hotel.rb +class Hotel +end + +# hotel/pricing.rb +module Hotel::Pricing +end +``` + +and `Hotel` is not yet loaded, then + +``` +(rdbg) p Hotel::Pricing +``` + +will raise a `NameError`. In some cases, Ruby will be able to resolve an unintended constant in a different scope. + +If you hit this, please restart your debugging session with eager loading enabled (`config.eager_load = true`). + +Stepping commands line `next`, `continue`, etc., do not present this issue. Namespaces defined implictly only by subdirectories are not subject to this issue either. + +See [ruby/debug#408](https://github.com/ruby/debug/issues/408) for details. Debugging with the `web-console` gem ------------------------------------ diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt index 4caa0d8e987b9..abb5432d0fd51 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile.tt +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile.tt @@ -44,13 +44,7 @@ gem "bootsnap", ">= 1.4.4", require: false <% if RUBY_ENGINE == "ruby" -%> group :development, :test do - # Writing `binding.irb` in a spot to debug gives you a console. If the project - # depends on Pry, `binding.pry` is also available. For them to work, you don't - # need to depend on the `debug` gem. - # - # To get a proper debugger, depend on the `debug` gem and execute `binding.b`. - # However, better eager load the application, because `debug` and autoloading - # are not fully compatible. See https://github.com/ruby/debug/issues/408. + # See https://edgeguides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem gem "debug", ">= 1.0.0", platforms: %i[ mri mingw x64_mingw ] end <% end -%> From f9fbfe0ab3cfc31f72663b9f06286ab32224b886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 6 Dec 2021 14:58:38 -0500 Subject: [PATCH 020/455] Merge pull request #43772 from rails/rm-deprecate-to_s Deprecate `to_s(format)` in favor of `to_formatted_s(format)` --- .../lib/action_controller/metal/helpers.rb | 2 +- actionview/test/fixtures/replies.yml | 4 +- actionview/test/fixtures/topics.yml | 6 +- activemodel/lib/active_model/type/date.rb | 2 +- .../active_model/type/helpers/time_value.rb | 2 +- .../lib/active_record/attribute_methods.rb | 2 +- .../connection_adapters/abstract/quoting.rb | 2 +- activerecord/lib/active_record/fixtures.rb | 2 +- activerecord/lib/active_record/integration.rb | 5 +- activerecord/lib/active_record/relation.rb | 2 +- .../cases/adapters/sqlite3/quoting_test.rb | 4 +- .../test/cases/attribute_methods_test.rb | 2 +- activerecord/test/cases/cache_key_test.rb | 4 +- .../test/cases/collection_cache_key_test.rb | 14 +- activerecord/test/cases/core_test.rb | 2 +- activerecord/test/cases/integration_test.rb | 10 +- .../cases/multiparameter_attributes_test.rb | 4 +- activerecord/test/cases/quoting_test.rb | 18 +- activerecord/test/fixtures/memberships.yml | 12 +- activerecord/test/fixtures/pirates.yml | 4 +- .../lib/active_support/core_ext/array.rb | 1 + .../core_ext/array/conversions.rb | 4 +- .../core_ext/array/deprecated_conversions.rb | 25 + .../lib/active_support/core_ext/date.rb | 1 + .../core_ext/date/conversions.rb | 6 +- .../core_ext/date/deprecated_conversions.rb | 26 + .../lib/active_support/core_ext/date_time.rb | 1 + .../core_ext/date_time/conversions.rb | 10 +- .../date_time/deprecated_conversions.rb | 22 + .../lib/active_support/core_ext/numeric.rb | 1 + .../core_ext/numeric/conversions.rb | 153 +++--- .../numeric/deprecated_conversions.rb | 60 +++ .../lib/active_support/core_ext/range.rb | 1 + .../core_ext/range/conversions.rb | 16 +- .../core_ext/range/deprecated_conversions.rb | 26 + .../lib/active_support/core_ext/time.rb | 1 + .../core_ext/time/conversions.rb | 7 +- .../core_ext/time/deprecated_conversions.rb | 22 + activesupport/lib/active_support/railtie.rb | 1 + .../lib/active_support/time_with_zone.rb | 40 +- activesupport/lib/active_support/xml_mini.rb | 2 +- .../test/core_ext/array/conversions_test.rb | 34 +- activesupport/test/core_ext/date_ext_test.rb | 85 +++- .../test/core_ext/date_time_ext_test.rb | 78 ++- .../test/core_ext/numeric_ext_test.rb | 472 ++++++++++-------- activesupport/test/core_ext/range_ext_test.rb | 33 +- activesupport/test/core_ext/time_ext_test.rb | 114 ++++- .../test/core_ext/time_with_zone_test.rb | 23 +- activesupport/test/time_travel_test.rb | 22 +- .../source/active_support_core_extensions.md | 82 ++- guides/source/configuring.md | 15 +- guides/source/debugging_rails_applications.md | 3 +- guides/source/security.md | 4 +- railties/lib/rails/application/bootstrap.rb | 1 + .../lib/rails/application/configuration.rb | 1 + .../rails/generators/generated_attribute.rb | 4 +- .../test/application/configuration_test.rb | 70 +++ .../generators/generated_attribute_test.rb | 4 +- 58 files changed, 1082 insertions(+), 492 deletions(-) create mode 100644 activesupport/lib/active_support/core_ext/array/deprecated_conversions.rb create mode 100644 activesupport/lib/active_support/core_ext/date/deprecated_conversions.rb create mode 100644 activesupport/lib/active_support/core_ext/date_time/deprecated_conversions.rb create mode 100644 activesupport/lib/active_support/core_ext/numeric/deprecated_conversions.rb create mode 100644 activesupport/lib/active_support/core_ext/range/deprecated_conversions.rb create mode 100644 activesupport/lib/active_support/core_ext/time/deprecated_conversions.rb diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index 5988d5c577354..d383c5053258a 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -26,7 +26,7 @@ module ActionController # # module FormattedTimeHelper # def format_time(time, format=:long, blank_message=" ") - # time.blank? ? blank_message : time.to_s(format) + # time.blank? ? blank_message : time.to_formatted_s(format) # end # end # diff --git a/actionview/test/fixtures/replies.yml b/actionview/test/fixtures/replies.yml index 2a3454b8bf844..977513ae6309f 100644 --- a/actionview/test/fixtures/replies.yml +++ b/actionview/test/fixtures/replies.yml @@ -3,7 +3,7 @@ witty_retort: topic_id: 1 developer_id: 1 content: Birdman is better! - created_at: <%= 6.hours.ago.to_s(:db) %> + created_at: <%= 6.hours.ago.to_formatted_s(:db) %> updated_at: nil another: @@ -11,5 +11,5 @@ another: topic_id: 2 developer_id: 1 content: Nuh uh! - created_at: <%= 1.hour.ago.to_s(:db) %> + created_at: <%= 1.hour.ago.to_formatted_s(:db) %> updated_at: nil diff --git a/actionview/test/fixtures/topics.yml b/actionview/test/fixtures/topics.yml index 41bd3849bc693..aac6802d60f91 100644 --- a/actionview/test/fixtures/topics.yml +++ b/actionview/test/fixtures/topics.yml @@ -3,7 +3,7 @@ futurama: title: Isn't futurama awesome? subtitle: It really is, isn't it. content: I like futurama - created_at: <%= 1.day.ago.to_s(:db) %> + created_at: <%= 1.day.ago.to_formatted_s(:db) %> updated_at: harvey_birdman: @@ -11,7 +11,7 @@ harvey_birdman: title: Harvey Birdman is the king of all men subtitle: yup content: It really is - created_at: <%= 2.hours.ago.to_s(:db) %> + created_at: <%= 2.hours.ago.to_formatted_s(:db) %> updated_at: rails: @@ -19,4 +19,4 @@ rails: title: Rails is nice subtitle: It makes me happy content: except when I have to hack internals to fix pagination. even then really. - created_at: <%= 20.minutes.ago.to_s(:db) %> + created_at: <%= 20.minutes.ago.to_formatted_s(:db) %> diff --git a/activemodel/lib/active_model/type/date.rb b/activemodel/lib/active_model/type/date.rb index 0e96d2c8a496f..4b0403161d2f1 100644 --- a/activemodel/lib/active_model/type/date.rb +++ b/activemodel/lib/active_model/type/date.rb @@ -11,7 +11,7 @@ def type end def type_cast_for_schema(value) - value.to_s(:db).inspect + value.to_formatted_s(:db).inspect end private diff --git a/activemodel/lib/active_model/type/helpers/time_value.rb b/activemodel/lib/active_model/type/helpers/time_value.rb index f357a1f72f5d3..fe2ac7f2415d7 100644 --- a/activemodel/lib/active_model/type/helpers/time_value.rb +++ b/activemodel/lib/active_model/type/helpers/time_value.rb @@ -36,7 +36,7 @@ def apply_seconds_precision(value) end def type_cast_for_schema(value) - value.to_s(:db).inspect + value.to_formatted_s(:db).inspect end def user_input_in_time_zone(value) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 26f2124cb7424..dfc422f535c4b 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -413,7 +413,7 @@ def format_for_inspect(name, value) inspected_value = if value.is_a?(String) && value.length > 50 "#{value[0, 50]}...".inspect elsif value.is_a?(Date) || value.is_a?(Time) - %("#{value.to_s(:inspect)}") + %("#{value.to_formatted_s(:inspect)}") else value.inspect end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 304338cce60f4..928a72181c355 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -128,7 +128,7 @@ def quoted_date(value) end end - result = value.to_s(:db) + result = value.to_formatted_s(:db) if value.respond_to?(:usec) && value.usec > 0 result << "." << sprintf("%06d", value.usec) else diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index b22ac2e980b9f..386d6e8ce8b70 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -407,7 +407,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # defaults: # # DEFAULTS: &DEFAULTS - # created_on: <%= 3.weeks.ago.to_s(:db) %> + # created_on: <%= 3.weeks.ago.to_formatted_s(:db) %> # # first: # name: Smurf diff --git a/activerecord/lib/active_record/integration.rb b/activerecord/lib/active_record/integration.rb index 930f608b6d7c8..b82b38d4023a4 100644 --- a/activerecord/lib/active_record/integration.rb +++ b/activerecord/lib/active_record/integration.rb @@ -79,7 +79,7 @@ def cache_key timestamp = max_updated_column_timestamp if timestamp - timestamp = timestamp.utc.to_s(cache_timestamp_format) + timestamp = timestamp.utc.to_formatted_s(cache_timestamp_format) "#{model_name.cache_key}/#{id}-#{timestamp}" else "#{model_name.cache_key}/#{id}" @@ -101,8 +101,9 @@ def cache_version timestamp = updated_at_before_type_cast if can_use_fast_cache_version?(timestamp) raw_timestamp_to_cache_version(timestamp) + elsif timestamp = updated_at - timestamp.utc.to_s(cache_timestamp_format) + timestamp.utc.to_formatted_s(cache_timestamp_format) end elsif self.class.has_attribute?("updated_at") raise ActiveModel::MissingAttributeError, "missing attribute: updated_at" diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 22dbf08762c19..d57a27f0c855a 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -389,7 +389,7 @@ def compute_cache_version(timestamp_column) # :nodoc: end if timestamp - "#{size}-#{timestamp.utc.to_s(cache_timestamp_format)}" + "#{size}-#{timestamp.utc.to_formatted_s(cache_timestamp_format)}" else "#{size}" end diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb index 9d26f32102c22..c13e8232cf2de 100644 --- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb @@ -57,7 +57,7 @@ def test_quoted_time_dst_utc t = Time.new(2000, 7, 1, 0, 0, 0, "+04:30") expected = t.change(year: 2000, month: 1, day: 1) - expected = expected.getutc.to_s(:db).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ") + expected = expected.getutc.to_formatted_s(:db).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ") assert_equal expected, @conn.quoted_time(t) end @@ -70,7 +70,7 @@ def test_quoted_time_dst_local t = Time.new(2000, 7, 1, 0, 0, 0, "+04:30") expected = t.change(year: 2000, month: 1, day: 1) - expected = expected.getlocal.to_s(:db).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ") + expected = expected.getlocal.to_formatted_s(:db).sub(/\A\d\d\d\d-\d\d-\d\d /, "2000-01-01 ") assert_equal expected, @conn.quoted_time(t) end diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index bbdcce51dc45e..6de3e728390f7 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -41,7 +41,7 @@ def setup test "attribute_for_inspect with a date" do t = topics(:first) - assert_equal %("#{t.written_on.to_s(:inspect)}"), t.attribute_for_inspect(:written_on) + assert_equal %("#{t.written_on.to_formatted_s(:inspect)}"), t.attribute_for_inspect(:written_on) end test "attribute_for_inspect with an array" do diff --git a/activerecord/test/cases/cache_key_test.rb b/activerecord/test/cases/cache_key_test.rb index c27eb8a65d9b5..43a06e9e6dba5 100644 --- a/activerecord/test/cases/cache_key_test.rb +++ b/activerecord/test/cases/cache_key_test.rb @@ -44,10 +44,10 @@ class CacheMeWithVersion < ActiveRecord::Base test "cache_key_with_version always has both key and version" do r1 = CacheMeWithVersion.create - assert_equal "active_record/cache_key_test/cache_me_with_versions/#{r1.id}-#{r1.updated_at.utc.to_s(:usec)}", r1.cache_key_with_version + assert_equal "active_record/cache_key_test/cache_me_with_versions/#{r1.id}-#{r1.updated_at.utc.to_formatted_s(:usec)}", r1.cache_key_with_version r2 = CacheMe.create - assert_equal "active_record/cache_key_test/cache_mes/#{r2.id}-#{r2.updated_at.utc.to_s(:usec)}", r2.cache_key_with_version + assert_equal "active_record/cache_key_test/cache_mes/#{r2.id}-#{r2.updated_at.utc.to_formatted_s(:usec)}", r2.cache_key_with_version end test "cache_version is the same when it comes from the DB or from the user" do diff --git a/activerecord/test/cases/collection_cache_key_test.rb b/activerecord/test/cases/collection_cache_key_test.rb index db7e274e021d4..f458a1cae10e3 100644 --- a/activerecord/test/cases/collection_cache_key_test.rb +++ b/activerecord/test/cases/collection_cache_key_test.rb @@ -27,7 +27,7 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase assert_equal ActiveSupport::Digest.hexdigest(developers.to_sql), $1 assert_equal developers.count.to_s, $2 - assert_equal last_developer_timestamp.to_s(ActiveRecord::Base.cache_timestamp_format), $3 + assert_equal last_developer_timestamp.to_formatted_s(ActiveRecord::Base.cache_timestamp_format), $3 end test "cache_key for relation with limit" do @@ -40,7 +40,7 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase assert_equal ActiveSupport::Digest.hexdigest(developers.to_sql), $1 assert_equal developers.count.to_s, $2 - assert_equal last_developer_timestamp.to_s(ActiveRecord::Base.cache_timestamp_format), $3 + assert_equal last_developer_timestamp.to_formatted_s(ActiveRecord::Base.cache_timestamp_format), $3 end test "cache_key for relation with custom select and limit" do @@ -54,7 +54,7 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase assert_equal ActiveSupport::Digest.hexdigest(developers_with_select.to_sql), $1 assert_equal developers.count.to_s, $2 - assert_equal last_developer_timestamp.to_s(ActiveRecord::Base.cache_timestamp_format), $3 + assert_equal last_developer_timestamp.to_formatted_s(ActiveRecord::Base.cache_timestamp_format), $3 end test "cache_key for loaded relation" do @@ -67,7 +67,7 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase assert_equal ActiveSupport::Digest.hexdigest(developers.to_sql), $1 assert_equal developers.count.to_s, $2 - assert_equal last_developer_timestamp.to_s(ActiveRecord::Base.cache_timestamp_format), $3 + assert_equal last_developer_timestamp.to_formatted_s(ActiveRecord::Base.cache_timestamp_format), $3 end test "cache_key for relation with table alias" do @@ -89,7 +89,7 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase assert_equal ActiveSupport::Digest.hexdigest(developers.to_sql), $1 assert_equal developers.count.to_s, $2 - assert_equal last_developer_timestamp.to_s(ActiveRecord::Base.cache_timestamp_format), $3 + assert_equal last_developer_timestamp.to_formatted_s(ActiveRecord::Base.cache_timestamp_format), $3 end test "cache_key for relation with includes" do @@ -182,7 +182,7 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase test "cache_key with custom timestamp column" do topics = Topic.where("title like ?", "%Topic%") - last_topic_timestamp = topics(:fifth).written_on.utc.to_s(:usec) + last_topic_timestamp = topics(:fifth).written_on.utc.to_formatted_s(:usec) assert_match(last_topic_timestamp, topics.cache_key(:written_on)) end @@ -250,7 +250,7 @@ class CollectionCacheKeyTest < ActiveRecord::TestCase /(\d+)-(\d+)\z/ =~ developers.cache_version assert_equal developers.count.to_s, $1 - assert_equal last_developer_timestamp.to_s(ActiveRecord::Base.cache_timestamp_format), $2 + assert_equal last_developer_timestamp.to_formatted_s(ActiveRecord::Base.cache_timestamp_format), $2 end end diff --git a/activerecord/test/cases/core_test.rb b/activerecord/test/cases/core_test.rb index 35d4590de4d00..63d38f40c7821 100644 --- a/activerecord/test/cases/core_test.rb +++ b/activerecord/test/cases/core_test.rb @@ -18,7 +18,7 @@ def test_inspect_class def test_inspect_instance topic = topics(:first) - assert_equal %(#), topic.inspect + assert_equal %(#), topic.inspect end def test_inspect_instance_with_lambda_date_formatter diff --git a/activerecord/test/cases/integration_test.rb b/activerecord/test/cases/integration_test.rb index 145ae97e63844..229c805dbccf0 100644 --- a/activerecord/test/cases/integration_test.rb +++ b/activerecord/test/cases/integration_test.rb @@ -108,12 +108,12 @@ def test_cache_key_for_existing_record_is_not_timezone_dependent def test_cache_key_format_for_existing_record_with_updated_at dev = Developer.first - assert_equal "developers/#{dev.id}-#{dev.updated_at.utc.to_s(:usec)}", dev.cache_key + assert_equal "developers/#{dev.id}-#{dev.updated_at.utc.to_formatted_s(:usec)}", dev.cache_key end def test_cache_key_format_for_existing_record_with_updated_at_and_custom_cache_timestamp_format dev = CachedDeveloper.first - assert_equal "cached_developers/#{dev.id}-#{dev.updated_at.utc.to_s(:number)}", dev.cache_key + assert_equal "cached_developers/#{dev.id}-#{dev.updated_at.utc.to_formatted_s(:number)}", dev.cache_key end def test_cache_key_changes_when_child_touched @@ -138,19 +138,19 @@ def test_cache_key_format_for_existing_record_with_nil_updated_timestamps def test_cache_key_for_updated_on dev = Developer.first dev.updated_at = nil - assert_equal "developers/#{dev.id}-#{dev.updated_on.utc.to_s(:usec)}", dev.cache_key + assert_equal "developers/#{dev.id}-#{dev.updated_on.utc.to_formatted_s(:usec)}", dev.cache_key end def test_cache_key_for_newer_updated_at dev = Developer.first dev.updated_at += 3600 - assert_equal "developers/#{dev.id}-#{dev.updated_at.utc.to_s(:usec)}", dev.cache_key + assert_equal "developers/#{dev.id}-#{dev.updated_at.utc.to_formatted_s(:usec)}", dev.cache_key end def test_cache_key_for_newer_updated_on dev = Developer.first dev.updated_on += 3600 - assert_equal "developers/#{dev.id}-#{dev.updated_on.utc.to_s(:usec)}", dev.cache_key + assert_equal "developers/#{dev.id}-#{dev.updated_on.utc.to_formatted_s(:usec)}", dev.cache_key end def test_cache_key_format_is_precise_enough diff --git a/activerecord/test/cases/multiparameter_attributes_test.rb b/activerecord/test/cases/multiparameter_attributes_test.rb index 6f3903eed4f79..1ec448f7919ab 100644 --- a/activerecord/test/cases/multiparameter_attributes_test.rb +++ b/activerecord/test/cases/multiparameter_attributes_test.rb @@ -107,8 +107,8 @@ def test_multiparameter_attributes_on_time_with_old_date } topic = Topic.find(1) topic.attributes = attributes - # testing against to_s(:db) representation because either a Time or a DateTime might be returned, depending on platform - assert_equal "1850-06-24 16:24:00", topic.written_on.to_s(:db) + # testing against to_formatted_s(:db) representation because either a Time or a DateTime might be returned, depending on platform + assert_equal "1850-06-24 16:24:00", topic.written_on.to_formatted_s(:db) end def test_multiparameter_attributes_on_time_will_raise_on_big_time_if_missing_date_parts diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb index ed77ccf138bad..cea079bb6b23b 100644 --- a/activerecord/test/cases/quoting_test.rb +++ b/activerecord/test/cases/quoting_test.rb @@ -43,20 +43,20 @@ def test_quote_string def test_quoted_date t = Date.today - assert_equal t.to_s(:db), @quoter.quoted_date(t) + assert_equal t.to_formatted_s(:db), @quoter.quoted_date(t) end def test_quoted_timestamp_utc with_timezone_config default: :utc do t = Time.now.change(usec: 0) - assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t) + assert_equal t.getutc.to_formatted_s(:db), @quoter.quoted_date(t) end end def test_quoted_timestamp_local with_timezone_config default: :local do t = Time.now.change(usec: 0) - assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t) + assert_equal t.getlocal.to_formatted_s(:db), @quoter.quoted_date(t) end end @@ -65,7 +65,7 @@ def test_quoted_time_utc t = Time.now.change(usec: 0) expected = t.change(year: 2000, month: 1, day: 1) - expected = expected.getutc.to_s(:db).slice(11..-1) + expected = expected.getutc.to_formatted_s(:db).slice(11..-1) assert_equal expected, @quoter.quoted_time(t) end @@ -76,7 +76,7 @@ def test_quoted_time_local t = Time.now.change(usec: 0) expected = t.change(year: 2000, month: 1, day: 1) - expected = expected.getlocal.to_s(:db).sub("2000-01-01 ", "") + expected = expected.getlocal.to_formatted_s(:db).sub("2000-01-01 ", "") assert_equal expected, @quoter.quoted_time(t) end @@ -88,7 +88,7 @@ def test_quoted_time_dst_utc t = Time.new(2000, 7, 1, 0, 0, 0, "+04:30") expected = t.change(year: 2000, month: 1, day: 1) - expected = expected.getutc.to_s(:db).slice(11..-1) + expected = expected.getutc.to_formatted_s(:db).slice(11..-1) assert_equal expected, @quoter.quoted_time(t) end @@ -101,7 +101,7 @@ def test_quoted_time_dst_local t = Time.new(2000, 7, 1, 0, 0, 0, "+04:30") expected = t.change(year: 2000, month: 1, day: 1) - expected = expected.getlocal.to_s(:db).slice(11..-1) + expected = expected.getlocal.to_formatted_s(:db).slice(11..-1) assert_equal expected, @quoter.quoted_time(t) end @@ -111,7 +111,7 @@ def test_quoted_time_dst_local def test_quoted_datetime_utc with_timezone_config default: :utc do t = Time.now.change(usec: 0).to_datetime - assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t) + assert_equal t.getutc.to_formatted_s(:db), @quoter.quoted_date(t) end end @@ -120,7 +120,7 @@ def test_quoted_datetime_utc def test_quoted_datetime_local with_timezone_config default: :local do t = Time.now.change(usec: 0).to_datetime - assert_equal t.to_s(:db), @quoter.quoted_date(t) + assert_equal t.to_formatted_s(:db), @quoter.quoted_date(t) end end diff --git a/activerecord/test/fixtures/memberships.yml b/activerecord/test/fixtures/memberships.yml index bc20734231ed0..9fc88287207a7 100644 --- a/activerecord/test/fixtures/memberships.yml +++ b/activerecord/test/fixtures/memberships.yml @@ -1,40 +1,40 @@ membership_of_boring_club: - joined_on: <%= 3.weeks.ago.to_s(:db) %> + joined_on: <%= 3.weeks.ago.to_formatted_s(:db) %> club: boring_club member_id: 1 favorite: false type: CurrentMembership membership_of_favorite_club: - joined_on: <%= 3.weeks.ago.to_s(:db) %> + joined_on: <%= 3.weeks.ago.to_formatted_s(:db) %> club: moustache_club member_id: 1 favorite: true type: Membership other_guys_membership: - joined_on: <%= 4.weeks.ago.to_s(:db) %> + joined_on: <%= 4.weeks.ago.to_formatted_s(:db) %> club: boring_club member_id: 2 favorite: false type: CurrentMembership blarpy_winkup_outrageous_club: - joined_on: <%= 4.weeks.ago.to_s(:db) %> + joined_on: <%= 4.weeks.ago.to_formatted_s(:db) %> club: outrageous_club member_id: 3 favorite: false type: CurrentMembership super_membership_of_boring_club: - joined_on: <%= 3.weeks.ago.to_s(:db) %> + joined_on: <%= 3.weeks.ago.to_formatted_s(:db) %> club: boring_club member_id: 1 favorite: false type: SuperMembership selected_membership_of_boring_club: - joined_on: <%= 3.weeks.ago.to_s(:db) %> + joined_on: <%= 3.weeks.ago.to_formatted_s(:db) %> club: boring_club member_id: 1 favorite: false diff --git a/activerecord/test/fixtures/pirates.yml b/activerecord/test/fixtures/pirates.yml index 0b1a78585312d..ba6f50ce33701 100644 --- a/activerecord/test/fixtures/pirates.yml +++ b/activerecord/test/fixtures/pirates.yml @@ -5,8 +5,8 @@ blackbeard: redbeard: catchphrase: "Avast!" parrot: louis - created_on: "<%= 2.weeks.ago.to_s(:db) %>" - updated_on: "<%= 2.weeks.ago.to_s(:db) %>" + created_on: "<%= 2.weeks.ago.to_formatted_s(:db) %>" + updated_on: "<%= 2.weeks.ago.to_formatted_s(:db) %>" mark: catchphrase: "X $LABELs the spot!" diff --git a/activesupport/lib/active_support/core_ext/array.rb b/activesupport/lib/active_support/core_ext/array.rb index 88b6567712379..81c9f694c5815 100644 --- a/activesupport/lib/active_support/core_ext/array.rb +++ b/activesupport/lib/active_support/core_ext/array.rb @@ -3,6 +3,7 @@ require "active_support/core_ext/array/wrap" require "active_support/core_ext/array/access" require "active_support/core_ext/array/conversions" +require "active_support/core_ext/array/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"] require "active_support/core_ext/array/extract" require "active_support/core_ext/array/extract_options" require "active_support/core_ext/array/grouping" diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index c4afcdef3079b..82cc221a3c981 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -87,6 +87,8 @@ def to_sentence(options = {}) # Extends Array#to_s to convert a collection of elements into a # comma separated id list if :db argument is given as the format. # + # This method is aliased to to_fs. + # # Blog.all.to_formatted_s(:db) # => "1,2,3" # Blog.none.to_formatted_s(:db) # => "null" # [1,2].to_formatted_s # => "[1, 2]" @@ -102,8 +104,8 @@ def to_formatted_s(format = :default) to_default_s end end + alias_method :to_fs, :to_formatted_s alias_method :to_default_s, :to_s - alias_method :to_s, :to_formatted_s # Returns a string that represents the array in XML by invoking +to_xml+ # on each element. Active Record collections delegate their representation diff --git a/activesupport/lib/active_support/core_ext/array/deprecated_conversions.rb b/activesupport/lib/active_support/core_ext/array/deprecated_conversions.rb new file mode 100644 index 0000000000000..907c31d7b854b --- /dev/null +++ b/activesupport/lib/active_support/core_ext/array/deprecated_conversions.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class Array + NOT_SET = Object.new # :nodoc: + def to_s(format = NOT_SET) # :nodoc: + case format + when :db + ActiveSupport::Deprecation.warn( + "Array#to_s(#{format.inspect}) is deprecated. Please use Array#to_formatted_s(#{format.inspect}) instead." + ) + if empty? + "null" + else + collect(&:id).join(",") + end + when NOT_SET + to_default_s + else + ActiveSupport::Deprecation.warn( + "Array#to_s(#{format.inspect}) is deprecated. Please use Array#to_formatted_s(#{format.inspect}) instead." + ) + to_default_s + end + end +end diff --git a/activesupport/lib/active_support/core_ext/date.rb b/activesupport/lib/active_support/core_ext/date.rb index cce73f2db2232..b683597f2affa 100644 --- a/activesupport/lib/active_support/core_ext/date.rb +++ b/activesupport/lib/active_support/core_ext/date.rb @@ -4,4 +4,5 @@ require "active_support/core_ext/date/blank" require "active_support/core_ext/date/calculations" require "active_support/core_ext/date/conversions" +require "active_support/core_ext/date/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"] require "active_support/core_ext/date/zones" diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb index 050a62bb31298..a4f3ae447be23 100644 --- a/activesupport/lib/active_support/core_ext/date/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date/conversions.rb @@ -22,12 +22,12 @@ class Date # Convert to a formatted string. See DATE_FORMATS for predefined formats. # - # This method is aliased to to_s. + # This method is aliased to to_fs. # # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007 # # date.to_formatted_s(:db) # => "2007-11-10" - # date.to_s(:db) # => "2007-11-10" + # date.to_formatted_s(:db) # => "2007-11-10" # # date.to_formatted_s(:short) # => "10 Nov" # date.to_formatted_s(:number) # => "20071110" @@ -55,8 +55,8 @@ def to_formatted_s(format = :default) to_default_s end end + alias_method :to_fs, :to_formatted_s alias_method :to_default_s, :to_s - alias_method :to_s, :to_formatted_s # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005" def readable_inspect diff --git a/activesupport/lib/active_support/core_ext/date/deprecated_conversions.rb b/activesupport/lib/active_support/core_ext/date/deprecated_conversions.rb new file mode 100644 index 0000000000000..030c54f75c5b0 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/date/deprecated_conversions.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "date" + +class Date + NOT_SET = Object.new # :nodoc: + def to_s(format = NOT_SET) # :nodoc: + if formatter = DATE_FORMATS[format] + ActiveSupport::Deprecation.warn( + "Date#to_s(#{format.inspect}) is deprecated. Please use Date#to_formatted_s(#{format.inspect}) instead." + ) + if formatter.respond_to?(:call) + formatter.call(self).to_s + else + strftime(formatter) + end + elsif format == NOT_SET + to_default_s + else + ActiveSupport::Deprecation.warn( + "Date#to_s(#{format.inspect}) is deprecated. Please use Date#to_formatted_s(#{format.inspect}) instead." + ) + to_default_s + end + end +end diff --git a/activesupport/lib/active_support/core_ext/date_time.rb b/activesupport/lib/active_support/core_ext/date_time.rb index 790dbeec1b479..e23a8be6ae92d 100644 --- a/activesupport/lib/active_support/core_ext/date_time.rb +++ b/activesupport/lib/active_support/core_ext/date_time.rb @@ -5,3 +5,4 @@ require "active_support/core_ext/date_time/calculations" require "active_support/core_ext/date_time/compatibility" require "active_support/core_ext/date_time/conversions" +require "active_support/core_ext/date_time/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"] diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb index 231bf870a2692..16fe529e4029f 100644 --- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb @@ -9,14 +9,14 @@ class DateTime # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats. # - # This method is aliased to to_s. + # This method is aliased to to_fs. # # === Examples # datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000 # # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00" - # datetime.to_s(:db) # => "2007-12-04 00:00:00" - # datetime.to_s(:number) # => "20071204000000" + # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00" + # datetime.to_formatted_s(:number) # => "20071204000000" # datetime.to_formatted_s(:short) # => "04 Dec 00:00" # datetime.to_formatted_s(:long) # => "December 04, 2007 00:00" # datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00" @@ -39,8 +39,8 @@ def to_formatted_s(format = :default) to_default_s end end + alias_method :to_fs, :to_formatted_s alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s) - alias_method :to_s, :to_formatted_s # Returns a formatted string of the offset from UTC, or an alternative # string if the time zone is already UTC. @@ -54,7 +54,7 @@ def formatted_offset(colon = true, alternate_utc_string = nil) # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000". def readable_inspect - to_s(:rfc822) + to_formatted_s(:rfc822) end alias_method :default_inspect, :inspect alias_method :inspect, :readable_inspect diff --git a/activesupport/lib/active_support/core_ext/date_time/deprecated_conversions.rb b/activesupport/lib/active_support/core_ext/date_time/deprecated_conversions.rb new file mode 100644 index 0000000000000..7ab305229630e --- /dev/null +++ b/activesupport/lib/active_support/core_ext/date_time/deprecated_conversions.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require "date" + +class DateTime + NOT_SET = Object.new # :nodoc: + def to_s(format = NOT_SET) # :nodoc: + if formatter = ::Time::DATE_FORMATS[format] + ActiveSupport::Deprecation.warn( + "DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_formatted_s(#{format.inspect}) instead." + ) + formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter) + elsif format == NOT_SET + to_default_s + else + ActiveSupport::Deprecation.warn( + "DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_formatted_s(#{format.inspect}) instead." + ) + to_default_s + end + end +end diff --git a/activesupport/lib/active_support/core_ext/numeric.rb b/activesupport/lib/active_support/core_ext/numeric.rb index fe778470f1649..9368cb3fcfc80 100644 --- a/activesupport/lib/active_support/core_ext/numeric.rb +++ b/activesupport/lib/active_support/core_ext/numeric.rb @@ -3,3 +3,4 @@ require "active_support/core_ext/numeric/bytes" require "active_support/core_ext/numeric/time" require "active_support/core_ext/numeric/conversions" +require "active_support/core_ext/numeric/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"] diff --git a/activesupport/lib/active_support/core_ext/numeric/conversions.rb b/activesupport/lib/active_support/core_ext/numeric/conversions.rb index 1e67e7c7e7dcf..a03b5facd3f1b 100644 --- a/activesupport/lib/active_support/core_ext/numeric/conversions.rb +++ b/activesupport/lib/active_support/core_ext/numeric/conversions.rb @@ -9,6 +9,8 @@ module NumericWithFormat # Options are provided for phone numbers, currency, percentage, # precision, positional notation, file size and pretty printing. # + # This method is aliased to to_fs. + # # ==== Options # # For details on which formats use which options, see ActiveSupport::NumberHelper @@ -16,102 +18,102 @@ module NumericWithFormat # ==== Examples # # Phone Numbers: - # 5551234.to_s(:phone) # => "555-1234" - # 1235551234.to_s(:phone) # => "123-555-1234" - # 1235551234.to_s(:phone, area_code: true) # => "(123) 555-1234" - # 1235551234.to_s(:phone, delimiter: ' ') # => "123 555 1234" - # 1235551234.to_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555" - # 1235551234.to_s(:phone, country_code: 1) # => "+1-123-555-1234" - # 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.') + # 5551234.to_formatted_s(:phone) # => "555-1234" + # 1235551234.to_formatted_s(:phone) # => "123-555-1234" + # 1235551234.to_formatted_s(:phone, area_code: true) # => "(123) 555-1234" + # 1235551234.to_formatted_s(:phone, delimiter: ' ') # => "123 555 1234" + # 1235551234.to_formatted_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555" + # 1235551234.to_formatted_s(:phone, country_code: 1) # => "+1-123-555-1234" + # 1235551234.to_formatted_s(:phone, country_code: 1, extension: 1343, delimiter: '.') # # => "+1.123.555.1234 x 1343" # # Currency: - # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50" - # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51" - # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506" - # 1234567890.506.to_s(:currency, round_mode: :down) # => "$1,234,567,890.50" - # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €" - # -1234567890.50.to_s(:currency, negative_format: '(%u%n)') + # 1234567890.50.to_formatted_s(:currency) # => "$1,234,567,890.50" + # 1234567890.506.to_formatted_s(:currency) # => "$1,234,567,890.51" + # 1234567890.506.to_formatted_s(:currency, precision: 3) # => "$1,234,567,890.506" + # 1234567890.506.to_formatted_s(:currency, round_mode: :down) # => "$1,234,567,890.50" + # 1234567890.506.to_formatted_s(:currency, locale: :fr) # => "1 234 567 890,51 €" + # -1234567890.50.to_formatted_s(:currency, negative_format: '(%u%n)') # # => "($1,234,567,890.50)" - # 1234567890.50.to_s(:currency, unit: '£', separator: ',', delimiter: '') + # 1234567890.50.to_formatted_s(:currency, unit: '£', separator: ',', delimiter: '') # # => "£1234567890,50" - # 1234567890.50.to_s(:currency, unit: '£', separator: ',', delimiter: '', format: '%n %u') + # 1234567890.50.to_formatted_s(:currency, unit: '£', separator: ',', delimiter: '', format: '%n %u') # # => "1234567890,50 £" # # Percentage: - # 100.to_s(:percentage) # => "100.000%" - # 100.to_s(:percentage, precision: 0) # => "100%" - # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%" - # 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%" - # 302.24398923423.to_s(:percentage, round_mode: :down) # => "302.243%" - # 1000.to_s(:percentage, locale: :fr) # => "1 000,000%" - # 100.to_s(:percentage, format: '%n %') # => "100.000 %" + # 100.to_formatted_s(:percentage) # => "100.000%" + # 100.to_formatted_s(:percentage, precision: 0) # => "100%" + # 1000.to_formatted_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%" + # 302.24398923423.to_formatted_s(:percentage, precision: 5) # => "302.24399%" + # 302.24398923423.to_formatted_s(:percentage, round_mode: :down) # => "302.243%" + # 1000.to_formatted_s(:percentage, locale: :fr) # => "1 000,000%" + # 100.to_formatted_s(:percentage, format: '%n %') # => "100.000 %" # # Delimited: - # 12345678.to_s(:delimited) # => "12,345,678" - # 12345678.05.to_s(:delimited) # => "12,345,678.05" - # 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678" - # 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678" - # 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05" - # 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05" - # 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',') + # 12345678.to_formatted_s(:delimited) # => "12,345,678" + # 12345678.05.to_formatted_s(:delimited) # => "12,345,678.05" + # 12345678.to_formatted_s(:delimited, delimiter: '.') # => "12.345.678" + # 12345678.to_formatted_s(:delimited, delimiter: ',') # => "12,345,678" + # 12345678.05.to_formatted_s(:delimited, separator: ' ') # => "12,345,678 05" + # 12345678.05.to_formatted_s(:delimited, locale: :fr) # => "12 345 678,05" + # 98765432.98.to_formatted_s(:delimited, delimiter: ' ', separator: ',') # # => "98 765 432,98" # # Rounded: - # 111.2345.to_s(:rounded) # => "111.235" - # 111.2345.to_s(:rounded, precision: 2) # => "111.23" - # 111.2345.to_s(:rounded, precision: 2, round_mode: :up) # => "111.24" - # 13.to_s(:rounded, precision: 5) # => "13.00000" - # 389.32314.to_s(:rounded, precision: 0) # => "389" - # 111.2345.to_s(:rounded, significant: true) # => "111" - # 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100" - # 13.to_s(:rounded, precision: 5, significant: true) # => "13.000" - # 111.234.to_s(:rounded, locale: :fr) # => "111,234" - # 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true) + # 111.2345.to_formatted_s(:rounded) # => "111.235" + # 111.2345.to_formatted_s(:rounded, precision: 2) # => "111.23" + # 111.2345.to_formatted_s(:rounded, precision: 2, round_mode: :up) # => "111.24" + # 13.to_formatted_s(:rounded, precision: 5) # => "13.00000" + # 389.32314.to_formatted_s(:rounded, precision: 0) # => "389" + # 111.2345.to_formatted_s(:rounded, significant: true) # => "111" + # 111.2345.to_formatted_s(:rounded, precision: 1, significant: true) # => "100" + # 13.to_formatted_s(:rounded, precision: 5, significant: true) # => "13.000" + # 111.234.to_formatted_s(:rounded, locale: :fr) # => "111,234" + # 13.to_formatted_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true) # # => "13" - # 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3" - # 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.') + # 389.32314.to_formatted_s(:rounded, precision: 4, significant: true) # => "389.3" + # 1111.2345.to_formatted_s(:rounded, precision: 2, separator: ',', delimiter: '.') # # => "1.111,23" # # Human-friendly size in Bytes: - # 123.to_s(:human_size) # => "123 Bytes" - # 1234.to_s(:human_size) # => "1.21 KB" - # 12345.to_s(:human_size) # => "12.1 KB" - # 1234567.to_s(:human_size) # => "1.18 MB" - # 1234567890.to_s(:human_size) # => "1.15 GB" - # 1234567890123.to_s(:human_size) # => "1.12 TB" - # 1234567890123456.to_s(:human_size) # => "1.1 PB" - # 1234567890123456789.to_s(:human_size) # => "1.07 EB" - # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB" - # 1234567.to_s(:human_size, precision: 2, round_mode: :up) # => "1.3 MB" - # 483989.to_s(:human_size, precision: 2) # => "470 KB" - # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB" - # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB" - # 524288000.to_s(:human_size, precision: 5) # => "500 MB" + # 123.to_formatted_s(:human_size) # => "123 Bytes" + # 1234.to_formatted_s(:human_size) # => "1.21 KB" + # 12345.to_formatted_s(:human_size) # => "12.1 KB" + # 1234567.to_formatted_s(:human_size) # => "1.18 MB" + # 1234567890.to_formatted_s(:human_size) # => "1.15 GB" + # 1234567890123.to_formatted_s(:human_size) # => "1.12 TB" + # 1234567890123456.to_formatted_s(:human_size) # => "1.1 PB" + # 1234567890123456789.to_formatted_s(:human_size) # => "1.07 EB" + # 1234567.to_formatted_s(:human_size, precision: 2) # => "1.2 MB" + # 1234567.to_formatted_s(:human_size, precision: 2, round_mode: :up) # => "1.3 MB" + # 483989.to_formatted_s(:human_size, precision: 2) # => "470 KB" + # 1234567.to_formatted_s(:human_size, precision: 2, separator: ',') # => "1,2 MB" + # 1234567890123.to_formatted_s(:human_size, precision: 5) # => "1.1228 TB" + # 524288000.to_formatted_s(:human_size, precision: 5) # => "500 MB" # # Human-friendly format: - # 123.to_s(:human) # => "123" - # 1234.to_s(:human) # => "1.23 Thousand" - # 12345.to_s(:human) # => "12.3 Thousand" - # 1234567.to_s(:human) # => "1.23 Million" - # 1234567890.to_s(:human) # => "1.23 Billion" - # 1234567890123.to_s(:human) # => "1.23 Trillion" - # 1234567890123456.to_s(:human) # => "1.23 Quadrillion" - # 1234567890123456789.to_s(:human) # => "1230 Quadrillion" - # 489939.to_s(:human, precision: 2) # => "490 Thousand" - # 489939.to_s(:human, precision: 2, round_mode: :down) # => "480 Thousand" - # 489939.to_s(:human, precision: 4) # => "489.9 Thousand" - # 1234567.to_s(:human, precision: 4, - # significant: false) # => "1.2346 Million" - # 1234567.to_s(:human, precision: 1, + # 123.to_formatted_s(:human) # => "123" + # 1234.to_formatted_s(:human) # => "1.23 Thousand" + # 12345.to_formatted_s(:human) # => "12.3 Thousand" + # 1234567.to_formatted_s(:human) # => "1.23 Million" + # 1234567890.to_formatted_s(:human) # => "1.23 Billion" + # 1234567890123.to_formatted_s(:human) # => "1.23 Trillion" + # 1234567890123456.to_formatted_s(:human) # => "1.23 Quadrillion" + # 1234567890123456789.to_formatted_s(:human) # => "1230 Quadrillion" + # 489939.to_formatted_s(:human, precision: 2) # => "490 Thousand" + # 489939.to_formatted_s(:human, precision: 2, round_mode: :down) # => "480 Thousand" + # 489939.to_formatted_s(:human, precision: 4) # => "489.9 Thousand" + # 1234567.to_formatted_s(:human, precision: 4, + # significant: false) # => "1.2346 Million" + # 1234567.to_formatted_s(:human, precision: 1, # separator: ',', - # significant: false) # => "1,2 Million" - def to_s(format = nil, options = nil) - return super() if format.nil? + # significant: false) # => "1,2 Million" + def to_formatted_s(format = nil, options = nil) + return to_s if format.nil? case format when Integer, String - super(format) + to_s(format) when :phone ActiveSupport::NumberHelper.number_to_phone(self, options || {}) when :currency @@ -127,11 +129,12 @@ def to_s(format = nil, options = nil) when :human_size ActiveSupport::NumberHelper.number_to_human_size(self, options || {}) when Symbol - super() + to_s else - super(format) + to_s(format) end end + alias_method :to_fs, :to_formatted_s end end diff --git a/activesupport/lib/active_support/core_ext/numeric/deprecated_conversions.rb b/activesupport/lib/active_support/core_ext/numeric/deprecated_conversions.rb new file mode 100644 index 0000000000000..fe83e08e10af7 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/numeric/deprecated_conversions.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module ActiveSupport + module DeprecatedNumericWithFormat # :nodoc: + def to_s(format = nil, options = nil) + return super() if format.nil? + + case format + when Integer, String + super(format) + when :phone + ActiveSupport::Deprecation.warn( + "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead." + ) + ActiveSupport::NumberHelper.number_to_phone(self, options || {}) + when :currency + ActiveSupport::Deprecation.warn( + "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead." + ) + ActiveSupport::NumberHelper.number_to_currency(self, options || {}) + when :percentage + ActiveSupport::Deprecation.warn( + "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead." + ) + ActiveSupport::NumberHelper.number_to_percentage(self, options || {}) + when :delimited + ActiveSupport::Deprecation.warn( + "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead." + ) + ActiveSupport::NumberHelper.number_to_delimited(self, options || {}) + when :rounded + ActiveSupport::Deprecation.warn( + "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead." + ) + ActiveSupport::NumberHelper.number_to_rounded(self, options || {}) + when :human + ActiveSupport::Deprecation.warn( + "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead." + ) + ActiveSupport::NumberHelper.number_to_human(self, options || {}) + when :human_size + ActiveSupport::Deprecation.warn( + "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead." + ) + ActiveSupport::NumberHelper.number_to_human_size(self, options || {}) + when Symbol + ActiveSupport::Deprecation.warn( + "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead." + ) + super() + else + super(format) + end + end + end +end + +Integer.prepend ActiveSupport::DeprecatedNumericWithFormat +Float.prepend ActiveSupport::DeprecatedNumericWithFormat +BigDecimal.prepend ActiveSupport::DeprecatedNumericWithFormat diff --git a/activesupport/lib/active_support/core_ext/range.rb b/activesupport/lib/active_support/core_ext/range.rb index fcfba532ae2a7..ba6bc9bdca87a 100644 --- a/activesupport/lib/active_support/core_ext/range.rb +++ b/activesupport/lib/active_support/core_ext/range.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "active_support/core_ext/range/conversions" +require "active_support/core_ext/range/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"] require "active_support/core_ext/range/compare_range" require "active_support/core_ext/range/overlaps" require "active_support/core_ext/range/each" diff --git a/activesupport/lib/active_support/core_ext/range/conversions.rb b/activesupport/lib/active_support/core_ext/range/conversions.rb index 024e32db40548..8b11475121252 100644 --- a/activesupport/lib/active_support/core_ext/range/conversions.rb +++ b/activesupport/lib/active_support/core_ext/range/conversions.rb @@ -7,34 +7,34 @@ module RangeWithFormat case start when String then "BETWEEN '#{start}' AND '#{stop}'" else - "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" + "BETWEEN '#{start.to_formatted_s(:db)}' AND '#{stop.to_formatted_s(:db)}'" end end } # Convert range to a formatted string. See RANGE_FORMATS for predefined formats. # + # This method is aliased to to_fs. + # # range = (1..100) # => 1..100 # # range.to_s # => "1..100" - # range.to_s(:db) # => "BETWEEN '1' AND '100'" + # range.to_formatted_s(:db) # => "BETWEEN '1' AND '100'" # # == Adding your own range formats to to_s # You can add your own formats to the Range::RANGE_FORMATS hash. # Use the format name as the hash key and a Proc instance. # # # config/initializers/range_formats.rb - # Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" } - def to_s(format = :default) + # Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_formatted_s(:db)} and #{stop.to_formatted_s(:db)}" } + def to_formatted_s(format = :default) if formatter = RANGE_FORMATS[format] formatter.call(first, last) else - super() + to_s end end - - alias_method :to_default_s, :to_s - alias_method :to_formatted_s, :to_s + alias_method :to_fs, :to_formatted_s end end diff --git a/activesupport/lib/active_support/core_ext/range/deprecated_conversions.rb b/activesupport/lib/active_support/core_ext/range/deprecated_conversions.rb new file mode 100644 index 0000000000000..aa6400b055d69 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/range/deprecated_conversions.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module ActiveSupport + module DeprecatedRangeWithFormat # :nodoc: + NOT_SET = Object.new # :nodoc: + def to_s(format = NOT_SET) + if formatter = RangeWithFormat::RANGE_FORMATS[format] + ActiveSupport::Deprecation.warn( + "Range#to_s(#{format.inspect}) is deprecated. Please use Range#to_formatted_s(#{format.inspect}) instead." + ) + formatter.call(first, last) + elsif format == NOT_SET + super() + else + ActiveSupport::Deprecation.warn( + "Range#to_s(#{format.inspect}) is deprecated. Please use Range#to_formatted_s(#{format.inspect}) instead." + ) + super() + end + end + alias_method :to_default_s, :to_s + deprecate :to_default_s + end +end + +Range.prepend(ActiveSupport::DeprecatedRangeWithFormat) diff --git a/activesupport/lib/active_support/core_ext/time.rb b/activesupport/lib/active_support/core_ext/time.rb index c809def05f35b..97162570801eb 100644 --- a/activesupport/lib/active_support/core_ext/time.rb +++ b/activesupport/lib/active_support/core_ext/time.rb @@ -4,4 +4,5 @@ require "active_support/core_ext/time/calculations" require "active_support/core_ext/time/compatibility" require "active_support/core_ext/time/conversions" +require "active_support/core_ext/time/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"] require "active_support/core_ext/time/zones" diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb index d61a191e33342..985d5ad1b2a7a 100644 --- a/activesupport/lib/active_support/core_ext/time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/time/conversions.rb @@ -27,12 +27,12 @@ class Time # Converts to a formatted string. See DATE_FORMATS for built-in formats. # - # This method is aliased to to_s. + # This method is aliased to to_fs. # # time = Time.now # => 2007-01-18 06:10:17 -06:00 # # time.to_formatted_s(:time) # => "06:10" - # time.to_s(:time) # => "06:10" + # time.to_formatted_s(:time) # => "06:10" # # time.to_formatted_s(:db) # => "2007-01-18 06:10:17" # time.to_formatted_s(:number) # => "20070118061017" @@ -54,11 +54,12 @@ def to_formatted_s(format = :default) if formatter = DATE_FORMATS[format] formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter) else + # Change to `to_s` when deprecation is gone. Also deprecate `to_default_s`. to_default_s end end + alias_method :to_fs, :to_formatted_s alias_method :to_default_s, :to_s - alias_method :to_s, :to_formatted_s # Returns a formatted string of the offset from UTC, or an alternative # string if the time zone is already UTC. diff --git a/activesupport/lib/active_support/core_ext/time/deprecated_conversions.rb b/activesupport/lib/active_support/core_ext/time/deprecated_conversions.rb new file mode 100644 index 0000000000000..5d4af95036fd5 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/time/deprecated_conversions.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require "time" + +class Time + NOT_SET = Object.new # :nodoc: + def to_s(format = NOT_SET) # :nodoc: + if formatter = DATE_FORMATS[format] + ActiveSupport::Deprecation.warn( + "Time#to_s(#{format.inspect}) is deprecated. Please use Time#to_formatted_s(#{format.inspect}) instead." + ) + formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter) + elsif format == NOT_SET + to_default_s + else + ActiveSupport::Deprecation.warn( + "Time#to_s(#{format.inspect}) is deprecated. Please use Time#to_formatted_s(#{format.inspect}) instead." + ) + to_default_s + end + end +end diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb index e5e826e5ae635..6ddd58a21027e 100644 --- a/activesupport/lib/active_support/railtie.rb +++ b/activesupport/lib/active_support/railtie.rb @@ -6,6 +6,7 @@ module ActiveSupport class Railtie < Rails::Railtie # :nodoc: config.active_support = ActiveSupport::OrderedOptions.new + config.active_support.disable_to_s_conversion = false config.eager_load_namespaces << ActiveSupport diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 8343c3d18a8df..43b9d23a0e8ac 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -33,7 +33,7 @@ module ActiveSupport # t.dst? # => true # t.utc_offset # => -14400 # t.zone # => "EDT" - # t.to_s(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400" + # t.to_formatted_s(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400" # t + 1.day # => Mon, 19 May 2008 13:27:25.031505668 EDT -04:00 # t.beginning_of_year # => Tue, 01 Jan 2008 00:00:00.000000000 EST -05:00 # t > Time.utc(1999) # => true @@ -202,25 +202,53 @@ def httpdate # # Time.zone.now.rfc2822 # => "Tue, 01 Jan 2013 04:51:39 +0000" def rfc2822 - to_s(:rfc822) + to_formatted_s(:rfc822) end alias_method :rfc822, :rfc2822 + NOT_SET = Object.new # :nodoc: + + # Returns a string of the object's date and time. + def to_s(format = NOT_SET) + if format == :db + ActiveSupport::Deprecation.warn( + "TimeWithZone#to_s(:db) is deprecated. Please use TimeWithZone#to_formatted_s(:db) instead." + ) + utc.to_formatted_s(format) + elsif formatter = ::Time::DATE_FORMATS[format] + ActiveSupport::Deprecation.warn( + "TimeWithZone#to_s(#{format.inspect}) is deprecated. Please use TimeWithZone#to_formatted_s(#{format.inspect}) instead." + ) + formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter) + elsif format == NOT_SET + "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format + else + ActiveSupport::Deprecation.warn( + "TimeWithZone#to_s(#{format.inspect}) is deprecated. Please use TimeWithZone#to_formatted_s(#{format.inspect}) instead." + ) + "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format + end + end + # Returns a string of the object's date and time. + # + # This method is aliased to to_fs. + # # Accepts an optional format: # * :default - default value, mimics Ruby Time#to_s format. # * :db - format outputs time in UTC :db time. See Time#to_formatted_s(:db). # * Any key in Time::DATE_FORMATS can be used. See active_support/core_ext/time/conversions.rb. - def to_s(format = :default) + def to_formatted_s(format = :default) if format == :db - utc.to_s(format) + utc.to_formatted_s(format) elsif formatter = ::Time::DATE_FORMATS[format] formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter) else - "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format + # Change to to_s when deprecation is gone. + "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" end end - alias_method :to_formatted_s, :to_s + alias_method :to_fs, :to_formatted_s # Replaces %Z directive with +zone before passing to Time#strftime, # so that zone information is correct. diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index e2b52daa65205..3a4efb106fe33 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -54,7 +54,7 @@ def content_type FORMATTING = { "symbol" => Proc.new { |symbol| symbol.to_s }, - "date" => Proc.new { |date| date.to_s(:db) }, + "date" => Proc.new { |date| date.to_formatted_s(:db) }, "dateTime" => Proc.new { |time| time.xmlschema }, "binary" => Proc.new { |binary| ::Base64.encode64(binary) }, "yaml" => Proc.new { |yaml| yaml.to_yaml } diff --git a/activesupport/test/core_ext/array/conversions_test.rb b/activesupport/test/core_ext/array/conversions_test.rb index 7312fa009b565..f09133f70d871 100644 --- a/activesupport/test/core_ext/array/conversions_test.rb +++ b/activesupport/test/core_ext/array/conversions_test.rb @@ -79,17 +79,45 @@ def test_returns_no_frozen_string class ToSTest < ActiveSupport::TestCase class TestDB - @@counter = 0 + def self.reset + @@counter = 0 + end + + reset + def id @@counter += 1 end end + setup do + TestDB.reset + end + def test_to_s_db collection = [TestDB.new, TestDB.new, TestDB.new] - assert_equal "null", [].to_s(:db) - assert_equal "1,2,3", collection.to_s(:db) + assert_deprecated do + assert_equal "null", [].to_s(:db) + end + assert_deprecated do + assert_equal "1,2,3", collection.to_s(:db) + end + end + + def test_to_s_not_existent + assert_deprecated do + assert_equal "[]", [].to_s(:not_existent) + end + end + + def test_to_formatted_s_db + collection = [TestDB.new, TestDB.new, TestDB.new] + + assert_equal "null", [].to_formatted_s(:db) + assert_equal "1,2,3", collection.to_formatted_s(:db) + assert_equal "null", [].to_fs(:db) + assert_equal "4,5,6", collection.to_fs(:db) end end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index 0612e6707904b..7bc53820e2f56 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -24,25 +24,82 @@ def test_tomorrow_in_calendar_reform def test_to_s date = Date.new(2005, 2, 21) assert_equal "2005-02-21", date.to_s - assert_equal "21 Feb", date.to_s(:short) - assert_equal "February 21, 2005", date.to_s(:long) - assert_equal "February 21st, 2005", date.to_s(:long_ordinal) - assert_equal "2005-02-21", date.to_s(:db) - assert_equal "2005-02-21", date.to_s(:inspect) - assert_equal "21 Feb 2005", date.to_s(:rfc822) - assert_equal "2005-02-21", date.to_s(:iso8601) + assert_deprecated do + assert_equal "21 Feb", date.to_s(:short) + end + assert_deprecated do + assert_equal "February 21, 2005", date.to_s(:long) + end + assert_deprecated do + assert_equal "February 21st, 2005", date.to_s(:long_ordinal) + end + assert_deprecated do + assert_equal "2005-02-21", date.to_s(:db) + end + assert_deprecated do + assert_equal "2005-02-21", date.to_s(:inspect) + end + assert_deprecated do + assert_equal "21 Feb 2005", date.to_s(:rfc822) + end + assert_deprecated do + assert_equal "2005-02-21", date.to_s(:iso8601) + end + assert_deprecated do + assert_equal "2005-02-21", date.to_s(:not_existent) + end end def test_to_s_with_single_digit_day date = Date.new(2005, 2, 1) assert_equal "2005-02-01", date.to_s - assert_equal "01 Feb", date.to_s(:short) - assert_equal "February 01, 2005", date.to_s(:long) - assert_equal "February 1st, 2005", date.to_s(:long_ordinal) - assert_equal "2005-02-01", date.to_s(:db) - assert_equal "2005-02-01", date.to_s(:inspect) - assert_equal "01 Feb 2005", date.to_s(:rfc822) - assert_equal "2005-02-01", date.to_s(:iso8601) + assert_deprecated do + assert_equal "01 Feb", date.to_s(:short) + end + assert_deprecated do + assert_equal "February 01, 2005", date.to_s(:long) + end + assert_deprecated do + assert_equal "February 1st, 2005", date.to_s(:long_ordinal) + end + assert_deprecated do + assert_equal "2005-02-01", date.to_s(:db) + end + assert_deprecated do + assert_equal "2005-02-01", date.to_s(:inspect) + end + assert_deprecated do + assert_equal "01 Feb 2005", date.to_s(:rfc822) + end + assert_deprecated do + assert_equal "2005-02-01", date.to_s(:iso8601) + end + assert_deprecated do + assert_equal "2005-02-01", date.to_s(:not_existent) + end + end + + def test_to_formatted_s + date = Date.new(2005, 2, 21) + assert_equal "21 Feb", date.to_formatted_s(:short) + assert_equal "February 21, 2005", date.to_formatted_s(:long) + assert_equal "February 21st, 2005", date.to_formatted_s(:long_ordinal) + assert_equal "2005-02-21", date.to_formatted_s(:db) + assert_equal "2005-02-21", date.to_formatted_s(:inspect) + assert_equal "21 Feb 2005", date.to_formatted_s(:rfc822) + assert_equal "2005-02-21", date.to_formatted_s(:iso8601) + assert_equal "21 Feb", date.to_fs(:short) + end + + def test_to_formatted_s_with_single_digit_day + date = Date.new(2005, 2, 1) + assert_equal "01 Feb", date.to_formatted_s(:short) + assert_equal "February 01, 2005", date.to_formatted_s(:long) + assert_equal "February 1st, 2005", date.to_formatted_s(:long_ordinal) + assert_equal "2005-02-01", date.to_formatted_s(:db) + assert_equal "2005-02-01", date.to_formatted_s(:inspect) + assert_equal "01 Feb 2005", date.to_formatted_s(:rfc822) + assert_equal "2005-02-01", date.to_formatted_s(:iso8601) end def test_readable_inspect diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 2c6ad8d8669d3..d872bf6700e77 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -15,31 +15,85 @@ def date_time_init(year, month, day, hour, minute, second, usec = 0) def test_to_s datetime = DateTime.new(2005, 2, 21, 14, 30, 0, 0) - assert_equal "2005-02-21 14:30:00", datetime.to_s(:db) - assert_equal "2005-02-21 14:30:00.000000000 +0000", datetime.to_s(:inspect) - assert_equal "14:30", datetime.to_s(:time) - assert_equal "21 Feb 14:30", datetime.to_s(:short) - assert_equal "February 21, 2005 14:30", datetime.to_s(:long) - assert_equal "Mon, 21 Feb 2005 14:30:00 +0000", datetime.to_s(:rfc822) - assert_equal "February 21st, 2005 14:30", datetime.to_s(:long_ordinal) + assert_deprecated do + assert_equal "2005-02-21 14:30:00", datetime.to_s(:db) + end + assert_deprecated do + assert_equal "2005-02-21 14:30:00.000000000 +0000", datetime.to_s(:inspect) + end + assert_deprecated do + assert_equal "14:30", datetime.to_s(:time) + end + assert_deprecated do + assert_equal "21 Feb 14:30", datetime.to_s(:short) + end + assert_deprecated do + assert_equal "February 21, 2005 14:30", datetime.to_s(:long) + end + assert_deprecated do + assert_equal "Mon, 21 Feb 2005 14:30:00 +0000", datetime.to_s(:rfc822) + end + assert_deprecated do + assert_equal "February 21st, 2005 14:30", datetime.to_s(:long_ordinal) + end assert_match(/^2005-02-21T14:30:00(Z|\+00:00)$/, datetime.to_s) + assert_deprecated do + assert_match(/^2005-02-21T14:30:00(Z|\+00:00)$/, datetime.to_s(:not_existent)) + end with_env_tz "US/Central" do - assert_equal "2009-02-05T14:30:05-06:00", DateTime.civil(2009, 2, 5, 14, 30, 5, Rational(-21600, 86400)).to_s(:iso8601) - assert_equal "2008-06-09T04:05:01-05:00", DateTime.civil(2008, 6, 9, 4, 5, 1, Rational(-18000, 86400)).to_s(:iso8601) - assert_equal "2009-02-05T14:30:05+00:00", DateTime.civil(2009, 2, 5, 14, 30, 5).to_s(:iso8601) + assert_deprecated do + assert_equal "2009-02-05T14:30:05-06:00", DateTime.civil(2009, 2, 5, 14, 30, 5, Rational(-21600, 86400)).to_s(:iso8601) + end + assert_deprecated do + assert_equal "2008-06-09T04:05:01-05:00", DateTime.civil(2008, 6, 9, 4, 5, 1, Rational(-18000, 86400)).to_s(:iso8601) + end + assert_deprecated do + assert_equal "2009-02-05T14:30:05+00:00", DateTime.civil(2009, 2, 5, 14, 30, 5).to_s(:iso8601) + end end end + def test_to_formatted_s + datetime = DateTime.new(2005, 2, 21, 14, 30, 0, 0) + assert_equal "2005-02-21 14:30:00", datetime.to_formatted_s(:db) + assert_equal "2005-02-21 14:30:00.000000000 +0000", datetime.to_formatted_s(:inspect) + assert_equal "14:30", datetime.to_formatted_s(:time) + assert_equal "21 Feb 14:30", datetime.to_formatted_s(:short) + assert_equal "February 21, 2005 14:30", datetime.to_formatted_s(:long) + assert_equal "Mon, 21 Feb 2005 14:30:00 +0000", datetime.to_formatted_s(:rfc822) + assert_equal "February 21st, 2005 14:30", datetime.to_formatted_s(:long_ordinal) + assert_match(/^2005-02-21T14:30:00(Z|\+00:00)$/, datetime.to_formatted_s) + assert_match(/^2005-02-21T14:30:00(Z|\+00:00)$/, datetime.to_formatted_s(:not_existent)) + + with_env_tz "US/Central" do + assert_equal "2009-02-05T14:30:05-06:00", DateTime.civil(2009, 2, 5, 14, 30, 5, Rational(-21600, 86400)).to_formatted_s(:iso8601) + assert_equal "2008-06-09T04:05:01-05:00", DateTime.civil(2008, 6, 9, 4, 5, 1, Rational(-18000, 86400)).to_formatted_s(:iso8601) + assert_equal "2009-02-05T14:30:05+00:00", DateTime.civil(2009, 2, 5, 14, 30, 5).to_formatted_s(:iso8601) + end + + assert_equal "2005-02-21 14:30:00", datetime.to_fs(:db) + end + def test_readable_inspect datetime = DateTime.new(2005, 2, 21, 14, 30, 0) assert_equal "Mon, 21 Feb 2005 14:30:00 +0000", datetime.readable_inspect assert_equal datetime.readable_inspect, datetime.inspect end - def test_custom_date_format + def test_to_s_with_custom_date_format + Time::DATE_FORMATS[:custom] = "%Y%m%d%H%M%S" + assert_deprecated do + assert_equal "20050221143000", DateTime.new(2005, 2, 21, 14, 30, 0).to_s(:custom) + end + ensure + Time::DATE_FORMATS.delete(:custom) + end + + def test_to_formatted_s_with_custom_date_format Time::DATE_FORMATS[:custom] = "%Y%m%d%H%M%S" - assert_equal "20050221143000", DateTime.new(2005, 2, 21, 14, 30, 0).to_s(:custom) + assert_equal "20050221143000", DateTime.new(2005, 2, 21, 14, 30, 0).to_formatted_s(:custom) + ensure Time::DATE_FORMATS.delete(:custom) end diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb index 13088082b5049..bb8d90fa695a8 100644 --- a/activesupport/test/core_ext/numeric_ext_test.rb +++ b/activesupport/test/core_ext/numeric_ext_test.rb @@ -73,6 +73,10 @@ def test_add_one_year_to_leap_day assert_equal Time.utc(2005, 2, 28, 15, 15, 10), Time.utc(2004, 2, 29, 15, 15, 10) + 1.year assert_equal DateTime.civil(2005, 2, 28, 15, 15, 10), DateTime.civil(2004, 2, 29, 15, 15, 10) + 1.year end + + def test_in_milliseconds + assert_equal 10_000, 10.seconds.in_milliseconds + end end class NumericExtDateTest < ActiveSupport::TestCase @@ -153,262 +157,300 @@ def exabytes(number) petabytes(number) * 1024 end - def test_to_s__phone - assert_equal("555-1234", 5551234.to_s(:phone)) - assert_equal("800-555-1212", 8005551212.to_s(:phone)) - assert_equal("(800) 555-1212", 8005551212.to_s(:phone, area_code: true)) - assert_equal("800 555 1212", 8005551212.to_s(:phone, delimiter: " ")) - assert_equal("(800) 555-1212 x 123", 8005551212.to_s(:phone, area_code: true, extension: 123)) - assert_equal("800-555-1212", 8005551212.to_s(:phone, extension: " ")) - assert_equal("555.1212", 5551212.to_s(:phone, delimiter: ".")) - assert_equal("+1-800-555-1212", 8005551212.to_s(:phone, country_code: 1)) - assert_equal("+18005551212", 8005551212.to_s(:phone, country_code: 1, delimiter: "")) - assert_equal("22-555-1212", 225551212.to_s(:phone)) - assert_equal("+45-22-555-1212", 225551212.to_s(:phone, country_code: 45)) - end - - def test_to_s__currency - assert_equal("$1,234,567,890.50", 1234567890.50.to_s(:currency)) - assert_equal("$1,234,567,890.51", 1234567890.506.to_s(:currency)) - assert_equal("-$1,234,567,890.50", -1234567890.50.to_s(:currency)) - assert_equal("-$ 1,234,567,890.50", -1234567890.50.to_s(:currency, format: "%u %n")) - assert_equal("($1,234,567,890.50)", -1234567890.50.to_s(:currency, negative_format: "(%u%n)")) - assert_equal("$1,234,567,892", 1234567891.50.to_s(:currency, precision: 0)) - assert_equal("$1,234,567,891", 1234567891.50.to_s(:currency, precision: 0, round_mode: :down)) - assert_equal("$1,234,567,890.5", 1234567890.50.to_s(:currency, precision: 1)) - assert_equal("£1234567890,50", 1234567890.50.to_s(:currency, unit: "£", separator: ",", delimiter: "")) - end - - def test_to_s__rounded - assert_equal("-111.235", -111.2346.to_s(:rounded)) - assert_equal("111.235", 111.2346.to_s(:rounded)) - assert_equal("31.83", 31.825.to_s(:rounded, precision: 2)) - assert_equal("31.82", 31.825.to_s(:rounded, precision: 2, round_mode: :down)) - assert_equal("111.23", 111.2346.to_s(:rounded, precision: 2)) - assert_equal("111.00", 111.to_s(:rounded, precision: 2)) - assert_equal("3268", (32.6751 * 100.00).to_s(:rounded, precision: 0)) - assert_equal("112", 111.50.to_s(:rounded, precision: 0)) - assert_equal("1234567892", 1234567891.50.to_s(:rounded, precision: 0)) - assert_equal("0", 0.to_s(:rounded, precision: 0)) - assert_equal("0.00100", 0.001.to_s(:rounded, precision: 5)) - assert_equal("0.001", 0.00111.to_s(:rounded, precision: 3)) - assert_equal("10.00", 9.995.to_s(:rounded, precision: 2)) - assert_equal("11.00", 10.995.to_s(:rounded, precision: 2)) - assert_equal("0.00", -0.001.to_s(:rounded, precision: 2)) - end - - def test_to_s__percentage - assert_equal("100.000%", 100.to_s(:percentage)) - assert_equal("100%", 100.to_s(:percentage, precision: 0)) - assert_equal("302.06%", 302.0574.to_s(:percentage, precision: 2)) - assert_equal("302.05%", 302.0574.to_s(:percentage, precision: 2, round_mode: :down)) - assert_equal("123.4%", 123.400.to_s(:percentage, precision: 3, strip_insignificant_zeros: true)) - assert_equal("1.000,000%", 1000.to_s(:percentage, delimiter: ".", separator: ",")) - assert_equal("1000.000 %", 1000.to_s(:percentage, format: "%n %")) - end - - def test_to_s__delimited - assert_equal("12,345,678", 12345678.to_s(:delimited)) - assert_equal("0", 0.to_s(:delimited)) - assert_equal("123", 123.to_s(:delimited)) - assert_equal("123,456", 123456.to_s(:delimited)) - assert_equal("123,456.78", 123456.78.to_s(:delimited)) - assert_equal("123,456.789", 123456.789.to_s(:delimited)) - assert_equal("123,456.78901", 123456.78901.to_s(:delimited)) - assert_equal("123,456,789.78901", 123456789.78901.to_s(:delimited)) - assert_equal("0.78901", 0.78901.to_s(:delimited)) - end - - def test_to_s__delimited__with_options_hash - assert_equal "12 345 678", 12345678.to_s(:delimited, delimiter: " ") - assert_equal "12,345,678-05", 12345678.05.to_s(:delimited, separator: "-") - assert_equal "12.345.678,05", 12345678.05.to_s(:delimited, separator: ",", delimiter: ".") - assert_equal "12.345.678,05", 12345678.05.to_s(:delimited, delimiter: ".", separator: ",") - end - - def test_to_s__rounded_with_custom_delimiter_and_separator - assert_equal "31,83", 31.825.to_s(:rounded, precision: 2, separator: ",") - assert_equal "1.231,83", 1231.825.to_s(:rounded, precision: 2, separator: ",", delimiter: ".") - end - - def test_to_s__rounded__with_significant_digits - assert_equal "124000", 123987.to_s(:rounded, precision: 3, significant: true) - assert_equal "120000000", 123987876.to_s(:rounded, precision: 2, significant: true) - assert_equal "9775", 9775.to_s(:rounded, precision: 4, significant: true) - assert_equal "5.4", 5.3923.to_s(:rounded, precision: 2, significant: true) - assert_equal "5", 5.3923.to_s(:rounded, precision: 1, significant: true) - assert_equal "1", 1.232.to_s(:rounded, precision: 1, significant: true) - assert_equal "7", 7.to_s(:rounded, precision: 1, significant: true) - assert_equal "1", 1.to_s(:rounded, precision: 1, significant: true) - assert_equal "53", 52.7923.to_s(:rounded, precision: 2, significant: true) - assert_equal "9775.00", 9775.to_s(:rounded, precision: 6, significant: true) - assert_equal "5.392900", 5.3929.to_s(:rounded, precision: 7, significant: true) - assert_equal "0.0", 0.to_s(:rounded, precision: 2, significant: true) - assert_equal "0", 0.to_s(:rounded, precision: 1, significant: true) - assert_equal "0.0001", 0.0001.to_s(:rounded, precision: 1, significant: true) - assert_equal "0.000100", 0.0001.to_s(:rounded, precision: 3, significant: true) - assert_equal "0.0001", 0.0001111.to_s(:rounded, precision: 1, significant: true) - assert_equal "10.0", 9.995.to_s(:rounded, precision: 3, significant: true) - assert_equal "9.99", 9.994.to_s(:rounded, precision: 3, significant: true) - assert_equal "11.0", 10.995.to_s(:rounded, precision: 3, significant: true) - assert_equal "10.9", 10.995.to_s(:rounded, precision: 3, significant: true, round_mode: :down) - end - - def test_to_s__rounded__with_strip_insignificant_zeros - assert_equal "9775.43", 9775.43.to_s(:rounded, precision: 4, strip_insignificant_zeros: true) - assert_equal "9775.2", 9775.2.to_s(:rounded, precision: 6, significant: true, strip_insignificant_zeros: true) - assert_equal "0", 0.to_s(:rounded, precision: 6, significant: true, strip_insignificant_zeros: true) - end - - def test_to_s__rounded__with_significant_true_and_zero_precision + def test_to_formatted_s__phone + assert_deprecated do + assert_equal("555-1234", 5551234.to_s(:phone)) + end + assert_equal("555-1234", 5551234.to_formatted_s(:phone)) + assert_equal("555-1234", 5551234.to_fs(:phone)) + assert_equal("800-555-1212", 8005551212.to_formatted_s(:phone)) + assert_equal("(800) 555-1212", 8005551212.to_formatted_s(:phone, area_code: true)) + assert_equal("800 555 1212", 8005551212.to_formatted_s(:phone, delimiter: " ")) + assert_equal("(800) 555-1212 x 123", 8005551212.to_formatted_s(:phone, area_code: true, extension: 123)) + assert_equal("800-555-1212", 8005551212.to_formatted_s(:phone, extension: " ")) + assert_equal("555.1212", 5551212.to_formatted_s(:phone, delimiter: ".")) + assert_equal("+1-800-555-1212", 8005551212.to_formatted_s(:phone, country_code: 1)) + assert_equal("+18005551212", 8005551212.to_formatted_s(:phone, country_code: 1, delimiter: "")) + assert_equal("22-555-1212", 225551212.to_formatted_s(:phone)) + assert_equal("+45-22-555-1212", 225551212.to_formatted_s(:phone, country_code: 45)) + end + + def test_to_formatted_s__currency + assert_deprecated do + assert_equal("$1,234,567,890.50", 1234567890.50.to_s(:currency)) + end + assert_equal("$1,234,567,890.50", 1234567890.50.to_formatted_s(:currency)) + assert_equal("$1,234,567,890.50", 1234567890.50.to_fs(:currency)) + assert_equal("$1,234,567,890.51", 1234567890.506.to_formatted_s(:currency)) + assert_equal("-$1,234,567,890.50", -1234567890.50.to_formatted_s(:currency)) + assert_equal("-$ 1,234,567,890.50", -1234567890.50.to_formatted_s(:currency, format: "%u %n")) + assert_equal("($1,234,567,890.50)", -1234567890.50.to_formatted_s(:currency, negative_format: "(%u%n)")) + assert_equal("$1,234,567,892", 1234567891.50.to_formatted_s(:currency, precision: 0)) + assert_equal("$1,234,567,891", 1234567891.50.to_formatted_s(:currency, precision: 0, round_mode: :down)) + assert_equal("$1,234,567,890.5", 1234567890.50.to_formatted_s(:currency, precision: 1)) + assert_equal("£1234567890,50", 1234567890.50.to_formatted_s(:currency, unit: "£", separator: ",", delimiter: "")) + end + + def test_to_formatted_s__rounded + assert_deprecated do + assert_equal("-111.235", -111.2346.to_s(:rounded)) + end + assert_equal("-111.235", -111.2346.to_formatted_s(:rounded)) + assert_equal("-111.235", -111.2346.to_fs(:rounded)) + assert_equal("111.235", 111.2346.to_formatted_s(:rounded)) + assert_equal("31.83", 31.825.to_formatted_s(:rounded, precision: 2)) + assert_equal("31.82", 31.825.to_formatted_s(:rounded, precision: 2, round_mode: :down)) + assert_equal("111.23", 111.2346.to_formatted_s(:rounded, precision: 2)) + assert_equal("111.00", 111.to_formatted_s(:rounded, precision: 2)) + assert_equal("3268", (32.6751 * 100.00).to_formatted_s(:rounded, precision: 0)) + assert_equal("112", 111.50.to_formatted_s(:rounded, precision: 0)) + assert_equal("1234567892", 1234567891.50.to_formatted_s(:rounded, precision: 0)) + assert_equal("0", 0.to_formatted_s(:rounded, precision: 0)) + assert_equal("0.00100", 0.001.to_formatted_s(:rounded, precision: 5)) + assert_equal("0.001", 0.00111.to_formatted_s(:rounded, precision: 3)) + assert_equal("10.00", 9.995.to_formatted_s(:rounded, precision: 2)) + assert_equal("11.00", 10.995.to_formatted_s(:rounded, precision: 2)) + assert_equal("0.00", -0.001.to_formatted_s(:rounded, precision: 2)) + end + + def test_to_formatted_s__rounded_with_custom_delimiter_and_separator + assert_equal "31,83", 31.825.to_formatted_s(:rounded, precision: 2, separator: ",") + assert_equal "1.231,83", 1231.825.to_formatted_s(:rounded, precision: 2, separator: ",", delimiter: ".") + end + + def test_to_formatted_s__rounded__with_significant_digits + assert_equal "124000", 123987.to_formatted_s(:rounded, precision: 3, significant: true) + assert_equal "120000000", 123987876.to_formatted_s(:rounded, precision: 2, significant: true) + assert_equal "9775", 9775.to_formatted_s(:rounded, precision: 4, significant: true) + assert_equal "5.4", 5.3923.to_formatted_s(:rounded, precision: 2, significant: true) + assert_equal "5", 5.3923.to_formatted_s(:rounded, precision: 1, significant: true) + assert_equal "1", 1.232.to_formatted_s(:rounded, precision: 1, significant: true) + assert_equal "7", 7.to_formatted_s(:rounded, precision: 1, significant: true) + assert_equal "1", 1.to_formatted_s(:rounded, precision: 1, significant: true) + assert_equal "53", 52.7923.to_formatted_s(:rounded, precision: 2, significant: true) + assert_equal "9775.00", 9775.to_formatted_s(:rounded, precision: 6, significant: true) + assert_equal "5.392900", 5.3929.to_formatted_s(:rounded, precision: 7, significant: true) + assert_equal "0.0", 0.to_formatted_s(:rounded, precision: 2, significant: true) + assert_equal "0", 0.to_formatted_s(:rounded, precision: 1, significant: true) + assert_equal "0.0001", 0.0001.to_formatted_s(:rounded, precision: 1, significant: true) + assert_equal "0.000100", 0.0001.to_formatted_s(:rounded, precision: 3, significant: true) + assert_equal "0.0001", 0.0001111.to_formatted_s(:rounded, precision: 1, significant: true) + assert_equal "10.0", 9.995.to_formatted_s(:rounded, precision: 3, significant: true) + assert_equal "9.99", 9.994.to_formatted_s(:rounded, precision: 3, significant: true) + assert_equal "11.0", 10.995.to_formatted_s(:rounded, precision: 3, significant: true) + assert_equal "10.9", 10.995.to_formatted_s(:rounded, precision: 3, significant: true, round_mode: :down) + end + + def test_to_formatted_s__rounded__with_strip_insignificant_zeros + assert_equal "9775.43", 9775.43.to_formatted_s(:rounded, precision: 4, strip_insignificant_zeros: true) + assert_equal "9775.2", 9775.2.to_formatted_s(:rounded, precision: 6, significant: true, strip_insignificant_zeros: true) + assert_equal "0", 0.to_formatted_s(:rounded, precision: 6, significant: true, strip_insignificant_zeros: true) + end + + def test_to_formatted_s__rounded__with_significant_true_and_zero_precision # Zero precision with significant is a mistake (would always return zero), # so we treat it as if significant was false (increases backwards compatibility for number_to_human_size) - assert_equal "124", 123.987.to_s(:rounded, precision: 0, significant: true) - assert_equal "12", 12.to_s(:rounded, precision: 0, significant: true) - end - - def test_to_s__human_size - assert_equal "0 Bytes", 0.to_s(:human_size) - assert_equal "1 Byte", 1.to_s(:human_size) - assert_equal "3 Bytes", 3.14159265.to_s(:human_size) - assert_equal "123 Bytes", 123.0.to_s(:human_size) - assert_equal "123 Bytes", 123.to_s(:human_size) - assert_equal "1.21 KB", 1234.to_s(:human_size) - assert_equal "12.1 KB", 12345.to_s(:human_size) - assert_equal "1.18 MB", 1234567.to_s(:human_size) - assert_equal "1.15 GB", 1234567890.to_s(:human_size) - assert_equal "1.12 TB", 1234567890123.to_s(:human_size) - assert_equal "1.1 PB", 1234567890123456.to_s(:human_size) - assert_equal "1.07 EB", 1234567890123456789.to_s(:human_size) - assert_equal "1030 EB", exabytes(1026).to_s(:human_size) - assert_equal "444 KB", kilobytes(444).to_s(:human_size) - assert_equal "1020 MB", megabytes(1023).to_s(:human_size) - assert_equal "3 TB", terabytes(3).to_s(:human_size) - assert_equal "1.2 MB", 1234567.to_s(:human_size, precision: 2) - assert_equal "3 Bytes", 3.14159265.to_s(:human_size, precision: 4) - assert_equal "1 KB", kilobytes(1.0123).to_s(:human_size, precision: 2) - assert_equal "1.01 KB", kilobytes(1.0100).to_s(:human_size, precision: 4) - assert_equal "10 KB", kilobytes(10.000).to_s(:human_size, precision: 4) - assert_equal "1 Byte", 1.1.to_s(:human_size) - assert_equal "10 Bytes", 10.to_s(:human_size) - end - - def test_to_s__human_size_with_options_hash - assert_equal "1.2 MB", 1234567.to_s(:human_size, precision: 2) - assert_equal "3 Bytes", 3.14159265.to_s(:human_size, precision: 4) - assert_equal "1 KB", kilobytes(1.0123).to_s(:human_size, precision: 2) - assert_equal "1.01 KB", kilobytes(1.0100).to_s(:human_size, precision: 4) - assert_equal "10 KB", kilobytes(10.000).to_s(:human_size, precision: 4) - assert_equal "1 TB", 1234567890123.to_s(:human_size, precision: 1) - assert_equal "500 MB", 524288000.to_s(:human_size, precision: 3) - assert_equal "10 MB", 9961472.to_s(:human_size, precision: 0) - assert_equal "40 KB", 41010.to_s(:human_size, precision: 1) - assert_equal "40 KB", 41100.to_s(:human_size, precision: 2) - assert_equal "50 KB", 41100.to_s(:human_size, precision: 1, round_mode: :up) - assert_equal "1.0 KB", kilobytes(1.0123).to_s(:human_size, precision: 2, strip_insignificant_zeros: false) - assert_equal "1.012 KB", kilobytes(1.0123).to_s(:human_size, precision: 3, significant: false) - assert_equal "1 KB", kilobytes(1.0123).to_s(:human_size, precision: 0, significant: true) # ignores significant it precision is 0 - end - - def test_to_s__human_size_with_custom_delimiter_and_separator - assert_equal "1,01 KB", kilobytes(1.0123).to_s(:human_size, precision: 3, separator: ",") - assert_equal "1,01 KB", kilobytes(1.0100).to_s(:human_size, precision: 4, separator: ",") - assert_equal "1.000,1 TB", terabytes(1000.1).to_s(:human_size, precision: 5, delimiter: ".", separator: ",") + assert_equal "124", 123.987.to_formatted_s(:rounded, precision: 0, significant: true) + assert_equal "12", 12.to_formatted_s(:rounded, precision: 0, significant: true) + end + + def test_to_formatted_s__percentage + assert_deprecated do + assert_equal("100.000%", 100.to_s(:percentage)) + end + assert_equal("100.000%", 100.to_formatted_s(:percentage)) + assert_equal("100.000%", 100.to_fs(:percentage)) + assert_equal("100%", 100.to_formatted_s(:percentage, precision: 0)) + assert_equal("302.06%", 302.0574.to_formatted_s(:percentage, precision: 2)) + assert_equal("302.05%", 302.0574.to_formatted_s(:percentage, precision: 2, round_mode: :down)) + assert_equal("123.4%", 123.400.to_formatted_s(:percentage, precision: 3, strip_insignificant_zeros: true)) + assert_equal("1.000,000%", 1000.to_formatted_s(:percentage, delimiter: ".", separator: ",")) + assert_equal("1000.000 %", 1000.to_formatted_s(:percentage, format: "%n %")) + end + + def test_to_formatted_s__delimited + assert_deprecated do + assert_equal("12,345,678", 12345678.to_s(:delimited)) + end + assert_equal("12,345,678", 12345678.to_formatted_s(:delimited)) + assert_equal("12,345,678", 12345678.to_fs(:delimited)) + assert_equal("0", 0.to_formatted_s(:delimited)) + assert_equal("123", 123.to_formatted_s(:delimited)) + assert_equal("123,456", 123456.to_formatted_s(:delimited)) + assert_equal("123,456.78", 123456.78.to_formatted_s(:delimited)) + assert_equal("123,456.789", 123456.789.to_formatted_s(:delimited)) + assert_equal("123,456.78901", 123456.78901.to_formatted_s(:delimited)) + assert_equal("123,456,789.78901", 123456789.78901.to_formatted_s(:delimited)) + assert_equal("0.78901", 0.78901.to_formatted_s(:delimited)) + end + + def test_to_formatted_s__delimited__with_options_hash + assert_equal "12 345 678", 12345678.to_formatted_s(:delimited, delimiter: " ") + assert_equal "12,345,678-05", 12345678.05.to_formatted_s(:delimited, separator: "-") + assert_equal "12.345.678,05", 12345678.05.to_formatted_s(:delimited, separator: ",", delimiter: ".") + assert_equal "12.345.678,05", 12345678.05.to_formatted_s(:delimited, delimiter: ".", separator: ",") + end + + def test_to_formatted_s__human_size + assert_deprecated do + assert_equal "0 Bytes", 0.to_s(:human_size) + end + assert_equal "0 Bytes", 0.to_formatted_s(:human_size) + assert_equal "1 Byte", 1.to_formatted_s(:human_size) + assert_equal "3 Bytes", 3.14159265.to_formatted_s(:human_size) + assert_equal "123 Bytes", 123.0.to_formatted_s(:human_size) + assert_equal "123 Bytes", 123.to_formatted_s(:human_size) + assert_equal "1.21 KB", 1234.to_formatted_s(:human_size) + assert_equal "12.1 KB", 12345.to_formatted_s(:human_size) + assert_equal "1.18 MB", 1234567.to_formatted_s(:human_size) + assert_equal "1.15 GB", 1234567890.to_formatted_s(:human_size) + assert_equal "1.12 TB", 1234567890123.to_formatted_s(:human_size) + assert_equal "1.1 PB", 1234567890123456.to_formatted_s(:human_size) + assert_equal "1.07 EB", 1234567890123456789.to_formatted_s(:human_size) + assert_equal "1030 EB", exabytes(1026).to_formatted_s(:human_size) + assert_equal "444 KB", kilobytes(444).to_formatted_s(:human_size) + assert_equal "1020 MB", megabytes(1023).to_formatted_s(:human_size) + assert_equal "3 TB", terabytes(3).to_formatted_s(:human_size) + assert_equal "1.2 MB", 1234567.to_formatted_s(:human_size, precision: 2) + assert_equal "3 Bytes", 3.14159265.to_formatted_s(:human_size, precision: 4) + assert_equal "1 KB", kilobytes(1.0123).to_formatted_s(:human_size, precision: 2) + assert_equal "1.01 KB", kilobytes(1.0100).to_formatted_s(:human_size, precision: 4) + assert_equal "10 KB", kilobytes(10.000).to_formatted_s(:human_size, precision: 4) + assert_equal "1 Byte", 1.1.to_formatted_s(:human_size) + assert_equal "10 Bytes", 10.to_formatted_s(:human_size) + end + + def test_to_formatted_s__human_size_with_options_hash + assert_equal "1.2 MB", 1234567.to_formatted_s(:human_size, precision: 2) + assert_equal "3 Bytes", 3.14159265.to_formatted_s(:human_size, precision: 4) + assert_equal "1 KB", kilobytes(1.0123).to_formatted_s(:human_size, precision: 2) + assert_equal "1.01 KB", kilobytes(1.0100).to_formatted_s(:human_size, precision: 4) + assert_equal "10 KB", kilobytes(10.000).to_formatted_s(:human_size, precision: 4) + assert_equal "1 TB", 1234567890123.to_formatted_s(:human_size, precision: 1) + assert_equal "500 MB", 524288000.to_formatted_s(:human_size, precision: 3) + assert_equal "10 MB", 9961472.to_formatted_s(:human_size, precision: 0) + assert_equal "40 KB", 41010.to_formatted_s(:human_size, precision: 1) + assert_equal "40 KB", 41100.to_formatted_s(:human_size, precision: 2) + assert_equal "50 KB", 41100.to_formatted_s(:human_size, precision: 1, round_mode: :up) + assert_equal "1.0 KB", kilobytes(1.0123).to_formatted_s(:human_size, precision: 2, strip_insignificant_zeros: false) + assert_equal "1.012 KB", kilobytes(1.0123).to_formatted_s(:human_size, precision: 3, significant: false) + assert_equal "1 KB", kilobytes(1.0123).to_formatted_s(:human_size, precision: 0, significant: true) # ignores significant it precision is 0 + end + + def test_to_formatted_s__human_size_with_custom_delimiter_and_separator + assert_equal "1,01 KB", kilobytes(1.0123).to_formatted_s(:human_size, precision: 3, separator: ",") + assert_equal "1,01 KB", kilobytes(1.0100).to_formatted_s(:human_size, precision: 4, separator: ",") + assert_equal "1.000,1 TB", terabytes(1000.1).to_formatted_s(:human_size, precision: 5, delimiter: ".", separator: ",") end def test_number_to_human - assert_equal "-123", -123.to_s(:human) - assert_equal "-0.5", -0.5.to_s(:human) - assert_equal "0", 0.to_s(:human) - assert_equal "0.5", 0.5.to_s(:human) - assert_equal "123", 123.to_s(:human) - assert_equal "1.23 Thousand", 1234.to_s(:human) - assert_equal "12.3 Thousand", 12345.to_s(:human) - assert_equal "1.23 Million", 1234567.to_s(:human) - assert_equal "1.23 Billion", 1234567890.to_s(:human) - assert_equal "1.23 Trillion", 1234567890123.to_s(:human) - assert_equal "1.23 Quadrillion", 1234567890123456.to_s(:human) - assert_equal "1230 Quadrillion", 1234567890123456789.to_s(:human) - assert_equal "490 Thousand", 489939.to_s(:human, precision: 2) - assert_equal "489.9 Thousand", 489939.to_s(:human, precision: 4) - assert_equal "489 Thousand", 489000.to_s(:human, precision: 4) - assert_equal "480 Thousand", 489939.to_s(:human, precision: 2, round_mode: :down) - assert_equal "489.0 Thousand", 489000.to_s(:human, precision: 4, strip_insignificant_zeros: false) - assert_equal "1.2346 Million", 1234567.to_s(:human, precision: 4, significant: false) - assert_equal "1,2 Million", 1234567.to_s(:human, precision: 1, significant: false, separator: ",") - assert_equal "1 Million", 1234567.to_s(:human, precision: 0, significant: true, separator: ",") # significant forced to false + assert_deprecated do + assert_equal "-123", -123.to_s(:human) + end + assert_equal "-123", -123.to_formatted_s(:human) + assert_equal "-123", -123.to_fs(:human) + assert_equal "-0.5", -0.5.to_formatted_s(:human) + assert_equal "0", 0.to_formatted_s(:human) + assert_equal "0.5", 0.5.to_formatted_s(:human) + assert_equal "123", 123.to_formatted_s(:human) + assert_equal "1.23 Thousand", 1234.to_formatted_s(:human) + assert_equal "12.3 Thousand", 12345.to_formatted_s(:human) + assert_equal "1.23 Million", 1234567.to_formatted_s(:human) + assert_equal "1.23 Billion", 1234567890.to_formatted_s(:human) + assert_equal "1.23 Trillion", 1234567890123.to_formatted_s(:human) + assert_equal "1.23 Quadrillion", 1234567890123456.to_formatted_s(:human) + assert_equal "1230 Quadrillion", 1234567890123456789.to_formatted_s(:human) + assert_equal "490 Thousand", 489939.to_formatted_s(:human, precision: 2) + assert_equal "489.9 Thousand", 489939.to_formatted_s(:human, precision: 4) + assert_equal "489 Thousand", 489000.to_formatted_s(:human, precision: 4) + assert_equal "480 Thousand", 489939.to_formatted_s(:human, precision: 2, round_mode: :down) + assert_equal "489.0 Thousand", 489000.to_formatted_s(:human, precision: 4, strip_insignificant_zeros: false) + assert_equal "1.2346 Million", 1234567.to_formatted_s(:human, precision: 4, significant: false) + assert_equal "1,2 Million", 1234567.to_formatted_s(:human, precision: 1, significant: false, separator: ",") + assert_equal "1 Million", 1234567.to_formatted_s(:human, precision: 0, significant: true, separator: ",") # significant forced to false end def test_number_to_human_with_custom_units # Only integers volume = { unit: "ml", thousand: "lt", million: "m3" } - assert_equal "123 lt", 123456.to_s(:human, units: volume) - assert_equal "12 ml", 12.to_s(:human, units: volume) - assert_equal "1.23 m3", 1234567.to_s(:human, units: volume) + assert_equal "123 lt", 123456.to_formatted_s(:human, units: volume) + assert_equal "12 ml", 12.to_formatted_s(:human, units: volume) + assert_equal "1.23 m3", 1234567.to_formatted_s(:human, units: volume) # Including fractionals distance = { mili: "mm", centi: "cm", deci: "dm", unit: "m", ten: "dam", hundred: "hm", thousand: "km" } - assert_equal "1.23 mm", 0.00123.to_s(:human, units: distance) - assert_equal "1.23 cm", 0.0123.to_s(:human, units: distance) - assert_equal "1.23 dm", 0.123.to_s(:human, units: distance) - assert_equal "1.23 m", 1.23.to_s(:human, units: distance) - assert_equal "1.23 dam", 12.3.to_s(:human, units: distance) - assert_equal "1.23 hm", 123.to_s(:human, units: distance) - assert_equal "1.23 km", 1230.to_s(:human, units: distance) - assert_equal "1.23 km", 1230.to_s(:human, units: distance) - assert_equal "1.23 km", 1230.to_s(:human, units: distance) - assert_equal "12.3 km", 12300.to_s(:human, units: distance) + assert_equal "1.23 mm", 0.00123.to_formatted_s(:human, units: distance) + assert_equal "1.23 cm", 0.0123.to_formatted_s(:human, units: distance) + assert_equal "1.23 dm", 0.123.to_formatted_s(:human, units: distance) + assert_equal "1.23 m", 1.23.to_formatted_s(:human, units: distance) + assert_equal "1.23 dam", 12.3.to_formatted_s(:human, units: distance) + assert_equal "1.23 hm", 123.to_formatted_s(:human, units: distance) + assert_equal "1.23 km", 1230.to_formatted_s(:human, units: distance) + assert_equal "1.23 km", 1230.to_formatted_s(:human, units: distance) + assert_equal "1.23 km", 1230.to_formatted_s(:human, units: distance) + assert_equal "12.3 km", 12300.to_formatted_s(:human, units: distance) # The quantifiers don't need to be a continuous sequence gangster = { hundred: "hundred bucks", million: "thousand quids" } - assert_equal "1 hundred bucks", 100.to_s(:human, units: gangster) - assert_equal "25 hundred bucks", 2500.to_s(:human, units: gangster) - assert_equal "25 thousand quids", 25000000.to_s(:human, units: gangster) - assert_equal "12300 thousand quids", 12345000000.to_s(:human, units: gangster) + assert_equal "1 hundred bucks", 100.to_formatted_s(:human, units: gangster) + assert_equal "25 hundred bucks", 2500.to_formatted_s(:human, units: gangster) + assert_equal "25 thousand quids", 25000000.to_formatted_s(:human, units: gangster) + assert_equal "12300 thousand quids", 12345000000.to_formatted_s(:human, units: gangster) # Spaces are stripped from the resulting string - assert_equal "4", 4.to_s(:human, units: { unit: "", ten: "tens " }) - assert_equal "4.5 tens", 45.to_s(:human, units: { unit: "", ten: " tens " }) + assert_equal "4", 4.to_formatted_s(:human, units: { unit: "", ten: "tens " }) + assert_equal "4.5 tens", 45.to_formatted_s(:human, units: { unit: "", ten: " tens " }) end def test_number_to_human_with_custom_format - assert_equal "123 times Thousand", 123456.to_s(:human, format: "%n times %u") + assert_equal "123 times Thousand", 123456.to_formatted_s(:human, format: "%n times %u") volume = { unit: "ml", thousand: "lt", million: "m3" } - assert_equal "123.lt", 123456.to_s(:human, units: volume, format: "%n.%u") + assert_equal "123.lt", 123456.to_formatted_s(:human, units: volume, format: "%n.%u") end - def test_to_s__injected_on_proper_types - assert_equal "1.23 Thousand", 1230.to_s(:human) - assert_equal "1.23 Thousand", Float(1230).to_s(:human) - assert_equal "100000 Quadrillion", (100**10).to_s(:human) - assert_equal "1 Million", BigDecimal("1000010").to_s(:human) + def test_to_formatted_s__injected_on_proper_types + assert_equal "1.23 Thousand", 1230.to_formatted_s(:human) + assert_equal "1.23 Thousand", Float(1230).to_formatted_s(:human) + assert_equal "100000 Quadrillion", (100**10).to_formatted_s(:human) + assert_equal "1 Million", BigDecimal("1000010").to_formatted_s(:human) end - def test_to_s_with_invalid_formatter - assert_equal "123", 123.to_s(:invalid) - assert_equal "2.5", 2.5.to_s(:invalid) - assert_equal "100000000000000000000", (100**10).to_s(:invalid) - assert_equal "1000010.0", BigDecimal("1000010").to_s(:invalid) + def test_to_formatted_s_with_invalid_formatter + assert_deprecated do + assert_equal "123", 123.to_s(:invalid) + end + assert_equal "123", 123.to_formatted_s(:invalid) + assert_equal "123", 123.to_fs(:invalid) + assert_equal "2.5", 2.5.to_formatted_s(:invalid) + assert_equal "100000000000000000000", (100**10).to_formatted_s(:invalid) + assert_equal "1000010.0", BigDecimal("1000010").to_formatted_s(:invalid) end - def test_default_to_s + def test_default_to_formatted_s assert_equal "123", 123.to_s + assert_equal "123", 123.to_formatted_s + assert_equal "123", 123.to_fs assert_equal "1111011", 123.to_s(2) + assert_equal "1111011", 123.to_formatted_s(2) assert_equal "2.5", 2.5.to_s + assert_equal "2.5", 2.5.to_formatted_s assert_equal "100000000000000000000", (100**10).to_s + assert_equal "100000000000000000000", (100**10).to_formatted_s assert_equal "1010110101111000111010111100010110101100011000100000000000000000000", (100**10).to_s(2) + assert_equal "1010110101111000111010111100010110101100011000100000000000000000000", (100**10).to_formatted_s(2) assert_equal "1000010.0", BigDecimal("1000010").to_s + assert_equal "1000010.0", BigDecimal("1000010").to_formatted_s assert_equal "10000 10.0", BigDecimal("1000010").to_s("5F") + assert_equal "10000 10.0", BigDecimal("1000010").to_formatted_s("5F") assert_raises TypeError do 1.to_s({}) end - end - - def test_in_milliseconds - assert_equal 10_000, 10.seconds.in_milliseconds + assert_raises TypeError do + 1.to_formatted_s({}) + end end end diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index f9c1da384047e..8b3c2c5e0f20c 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -6,24 +6,41 @@ require "active_support/core_ext/range" class RangeTest < ActiveSupport::TestCase - def test_to_s_from_dates + def test_to_formatted_s_from_dates date_range = Date.new(2005, 12, 10)..Date.new(2005, 12, 12) - assert_equal "BETWEEN '2005-12-10' AND '2005-12-12'", date_range.to_s(:db) + assert_equal "BETWEEN '2005-12-10' AND '2005-12-12'", date_range.to_formatted_s(:db) + assert_equal "BETWEEN '2005-12-10' AND '2005-12-12'", date_range.to_fs(:db) end - def test_to_s_from_times + def test_to_formatted_s_from_times date_range = Time.utc(2005, 12, 10, 15, 30)..Time.utc(2005, 12, 10, 17, 30) - assert_equal "BETWEEN '2005-12-10 15:30:00' AND '2005-12-10 17:30:00'", date_range.to_s(:db) + assert_equal "BETWEEN '2005-12-10 15:30:00' AND '2005-12-10 17:30:00'", date_range.to_formatted_s(:db) end - def test_to_s_with_alphabets + def test_to_formatted_s_with_alphabets alphabet_range = ("a".."z") - assert_equal "BETWEEN 'a' AND 'z'", alphabet_range.to_s(:db) + assert_equal "BETWEEN 'a' AND 'z'", alphabet_range.to_formatted_s(:db) end - def test_to_s_with_numeric + def test_to_formatted_s_with_numeric number_range = (1..100) - assert_equal "BETWEEN '1' AND '100'", number_range.to_s(:db) + assert_equal "BETWEEN '1' AND '100'", number_range.to_formatted_s(:db) + end + + def test_to_s_with_format + number_range = (1..100) + + assert_deprecated do + assert_equal "BETWEEN '1' AND '100'", number_range.to_s(:db) + end + end + + def test_to_s_with_format_invalid_format + number_range = (1..100) + + assert_deprecated do + assert_equal "1..100", number_range.to_s(:not_existent) + end end def test_date_range diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 3c28310940fe8..56de684d4a5a6 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -582,33 +582,107 @@ def test_next_week_near_daylight_end def test_to_s time = Time.utc(2005, 2, 21, 17, 44, 30.12345678901) assert_equal time.to_default_s, time.to_s - assert_equal time.to_default_s, time.to_s(:doesnt_exist) - assert_equal "2005-02-21 17:44:30", time.to_s(:db) - assert_equal "21 Feb 17:44", time.to_s(:short) - assert_equal "17:44", time.to_s(:time) - assert_equal "20050221174430", time.to_s(:number) - assert_equal "20050221174430123456789", time.to_s(:nsec) - assert_equal "20050221174430123456", time.to_s(:usec) - assert_equal "February 21, 2005 17:44", time.to_s(:long) - assert_equal "February 21st, 2005 17:44", time.to_s(:long_ordinal) + assert_deprecated do + assert_equal time.to_default_s, time.to_s(:doesnt_exist) + end + assert_deprecated do + assert_equal "2005-02-21 17:44:30", time.to_s(:db) + end + assert_deprecated do + assert_equal "21 Feb 17:44", time.to_s(:short) + end + assert_deprecated do + assert_equal "17:44", time.to_s(:time) + end + assert_deprecated do + assert_equal "20050221174430", time.to_s(:number) + end + assert_deprecated do + assert_equal "20050221174430123456789", time.to_s(:nsec) + end + assert_deprecated do + assert_equal "20050221174430123456", time.to_s(:usec) + end + assert_deprecated do + assert_equal "February 21, 2005 17:44", time.to_s(:long) + end + assert_deprecated do + assert_equal "February 21st, 2005 17:44", time.to_s(:long_ordinal) + end with_env_tz "UTC" do - assert_equal "Mon, 21 Feb 2005 17:44:30 +0000", time.to_s(:rfc822) - assert_equal "2005-02-21 17:44:30.123456789 +0000", time.to_s(:inspect) + assert_deprecated do + assert_equal "Mon, 21 Feb 2005 17:44:30 +0000", time.to_s(:rfc822) + end + assert_deprecated do + assert_equal "2005-02-21 17:44:30.123456789 +0000", time.to_s(:inspect) + end end with_env_tz "US/Central" do - assert_equal "Thu, 05 Feb 2009 14:30:05 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_s(:rfc822) - assert_equal "Mon, 09 Jun 2008 04:05:01 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_s(:rfc822) - assert_equal "2009-02-05T14:30:05-06:00", Time.local(2009, 2, 5, 14, 30, 5).to_s(:iso8601) - assert_equal "2008-06-09T04:05:01-05:00", Time.local(2008, 6, 9, 4, 5, 1).to_s(:iso8601) - assert_equal "2009-02-05T14:30:05Z", Time.utc(2009, 2, 5, 14, 30, 5).to_s(:iso8601) - assert_equal "2009-02-05 14:30:05.000000000 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_s(:inspect) - assert_equal "2008-06-09 04:05:01.000000000 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_s(:inspect) + assert_deprecated do + assert_equal "Thu, 05 Feb 2009 14:30:05 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_s(:rfc822) + end + assert_deprecated do + assert_equal "Mon, 09 Jun 2008 04:05:01 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_s(:rfc822) + end + assert_deprecated do + assert_equal "2009-02-05T14:30:05-06:00", Time.local(2009, 2, 5, 14, 30, 5).to_s(:iso8601) + end + assert_deprecated do + assert_equal "2008-06-09T04:05:01-05:00", Time.local(2008, 6, 9, 4, 5, 1).to_s(:iso8601) + end + assert_deprecated do + assert_equal "2009-02-05T14:30:05Z", Time.utc(2009, 2, 5, 14, 30, 5).to_s(:iso8601) + end + assert_deprecated do + assert_equal "2009-02-05 14:30:05.000000000 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_s(:inspect) + end + assert_deprecated do + assert_equal "2008-06-09 04:05:01.000000000 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_s(:inspect) + end + end + end + + def test_to_formatted_s + time = Time.utc(2005, 2, 21, 17, 44, 30.12345678901) + assert_equal time.to_s, time.to_formatted_s(:doesnt_exist) + assert_equal "2005-02-21 17:44:30", time.to_formatted_s(:db) + assert_equal "21 Feb 17:44", time.to_formatted_s(:short) + assert_equal "17:44", time.to_formatted_s(:time) + assert_equal "20050221174430", time.to_formatted_s(:number) + assert_equal "20050221174430123456789", time.to_formatted_s(:nsec) + assert_equal "20050221174430123456", time.to_formatted_s(:usec) + assert_equal "February 21, 2005 17:44", time.to_formatted_s(:long) + assert_equal "February 21st, 2005 17:44", time.to_formatted_s(:long_ordinal) + with_env_tz "UTC" do + assert_equal "Mon, 21 Feb 2005 17:44:30 +0000", time.to_formatted_s(:rfc822) + assert_equal "2005-02-21 17:44:30.123456789 +0000", time.to_formatted_s(:inspect) end + with_env_tz "US/Central" do + assert_equal "Thu, 05 Feb 2009 14:30:05 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_formatted_s(:rfc822) + assert_equal "Mon, 09 Jun 2008 04:05:01 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_formatted_s(:rfc822) + assert_equal "2009-02-05T14:30:05-06:00", Time.local(2009, 2, 5, 14, 30, 5).to_formatted_s(:iso8601) + assert_equal "2008-06-09T04:05:01-05:00", Time.local(2008, 6, 9, 4, 5, 1).to_formatted_s(:iso8601) + assert_equal "2009-02-05T14:30:05Z", Time.utc(2009, 2, 5, 14, 30, 5).to_formatted_s(:iso8601) + assert_equal "2009-02-05 14:30:05.000000000 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_formatted_s(:inspect) + assert_equal "2008-06-09 04:05:01.000000000 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_formatted_s(:inspect) + end + + assert_equal "2005-02-21 17:44:30", time.to_fs(:db) + end + + def test_to_s_custom_date_format + Time::DATE_FORMATS[:custom] = "%Y%m%d%H%M%S" + assert_deprecated do + assert_equal "20050221143000", Time.local(2005, 2, 21, 14, 30, 0).to_s(:custom) + end + ensure + Time::DATE_FORMATS.delete(:custom) end - def test_custom_date_format + def test_to_formatted_s_custom_date_format Time::DATE_FORMATS[:custom] = "%Y%m%d%H%M%S" - assert_equal "20050221143000", Time.local(2005, 2, 21, 14, 30, 0).to_s(:custom) + assert_equal "20050221143000", Time.local(2005, 2, 21, 14, 30, 0).to_formatted_s(:custom) + ensure Time::DATE_FORMATS.delete(:custom) end diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index c328234a39b0d..f9cc06109420d 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -137,12 +137,31 @@ def test_to_formatted_s assert_equal "1999-12-31 19:00:00 -0500", @twz.to_formatted_s end + def test_to_formatted_s_db + assert_equal "2000-01-01 00:00:00", @twz.to_formatted_s(:db) + assert_equal "2000-01-01 00:00:00", @twz.to_fs(:db) + end + + def test_to_formatted_s_inspect + assert_equal "1999-12-31 19:00:00.000000000 -0500", @twz.to_formatted_s(:inspect) + end + def test_to_s_db - assert_equal "2000-01-01 00:00:00", @twz.to_s(:db) + assert_deprecated do + assert_equal "2000-01-01 00:00:00", @twz.to_s(:db) + end end def test_to_s_inspect - assert_equal "1999-12-31 19:00:00.000000000 -0500", @twz.to_s(:inspect) + assert_deprecated do + assert_equal "1999-12-31 19:00:00.000000000 -0500", @twz.to_s(:inspect) + end + end + + def test_to_s_not_existent + assert_deprecated do + assert_equal "1999-12-31 19:00:00 -0500", @twz.to_s(:not_existent) + end end def test_xmlschema diff --git a/activesupport/test/time_travel_test.rb b/activesupport/test/time_travel_test.rb index c9486a2afc4cd..f9673516dddaa 100644 --- a/activesupport/test/time_travel_test.rb +++ b/activesupport/test/time_travel_test.rb @@ -18,9 +18,9 @@ def test_time_helper_travel expected_time = Time.now + 1.day travel 1.day - assert_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_equal expected_time.to_formatted_s(:db), Time.now.to_formatted_s(:db) assert_equal expected_time.to_date, Date.today - assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) + assert_equal expected_time.to_datetime.to_formatted_s(:db), DateTime.now.to_formatted_s(:db) ensure travel_back end @@ -31,14 +31,14 @@ def test_time_helper_travel_with_block expected_time = Time.now + 1.day travel 1.day do - assert_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_equal expected_time.to_formatted_s(:db), Time.now.to_formatted_s(:db) assert_equal expected_time.to_date, Date.today - assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) + assert_equal expected_time.to_datetime.to_formatted_s(:db), DateTime.now.to_formatted_s(:db) end - assert_not_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_not_equal expected_time.to_formatted_s(:db), Time.now.to_formatted_s(:db) assert_not_equal expected_time.to_date, Date.today - assert_not_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) + assert_not_equal expected_time.to_datetime.to_formatted_s(:db), DateTime.now.to_formatted_s(:db) end end @@ -78,7 +78,7 @@ def test_time_helper_travel_to_with_time_zone expected_time = 5.minutes.ago travel_to 5.minutes.ago do - assert_equal expected_time.to_s(:db), Time.zone.now.to_s(:db) + assert_equal expected_time.to_formatted_s(:db), Time.zone.now.to_formatted_s(:db) end end end @@ -92,7 +92,7 @@ def test_time_helper_travel_to_with_string_for_time_zone expected_time = Time.new(2004, 11, 24, 1, 4, 44) travel_to "2004-11-24 01:04:44" do - assert_equal expected_time.to_s(:db), Time.zone.now.to_s(:db) + assert_equal expected_time.to_formatted_s(:db), Time.zone.now.to_formatted_s(:db) end end end @@ -237,7 +237,7 @@ def test_time_helper_freeze_time freeze_time sleep(1) - assert_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_equal expected_time.to_formatted_s(:db), Time.now.to_formatted_s(:db) ensure travel_back end @@ -248,10 +248,10 @@ def test_time_helper_freeze_time_with_block freeze_time do sleep(1) - assert_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_equal expected_time.to_formatted_s(:db), Time.now.to_formatted_s(:db) end - assert_operator expected_time.to_s(:db), :<, Time.now.to_s(:db) + assert_operator expected_time.to_formatted_s(:db), :<, Time.now.to_formatted_s(:db) end def test_time_helper_unfreeze_time diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index 9f663226cc80b..4674bb398f073 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -1988,84 +1988,84 @@ Enables the formatting of numbers in a variety of ways. Produce a string representation of a number as a telephone number: ```ruby -5551234.to_s(:phone) +5551234.to_formatted_s(:phone) # => 555-1234 -1235551234.to_s(:phone) +1235551234.to_formatted_s(:phone) # => 123-555-1234 -1235551234.to_s(:phone, area_code: true) +1235551234.to_formatted_s(:phone, area_code: true) # => (123) 555-1234 -1235551234.to_s(:phone, delimiter: " ") +1235551234.to_formatted_s(:phone, delimiter: " ") # => 123 555 1234 -1235551234.to_s(:phone, area_code: true, extension: 555) +1235551234.to_formatted_s(:phone, area_code: true, extension: 555) # => (123) 555-1234 x 555 -1235551234.to_s(:phone, country_code: 1) +1235551234.to_formatted_s(:phone, country_code: 1) # => +1-123-555-1234 ``` Produce a string representation of a number as currency: ```ruby -1234567890.50.to_s(:currency) # => $1,234,567,890.50 -1234567890.506.to_s(:currency) # => $1,234,567,890.51 -1234567890.506.to_s(:currency, precision: 3) # => $1,234,567,890.506 +1234567890.50.to_formatted_s(:currency) # => $1,234,567,890.50 +1234567890.506.to_formatted_s(:currency) # => $1,234,567,890.51 +1234567890.506.to_formatted_s(:currency, precision: 3) # => $1,234,567,890.506 ``` Produce a string representation of a number as a percentage: ```ruby -100.to_s(:percentage) +100.to_formatted_s(:percentage) # => 100.000% -100.to_s(:percentage, precision: 0) +100.to_formatted_s(:percentage, precision: 0) # => 100% -1000.to_s(:percentage, delimiter: '.', separator: ',') +1000.to_formatted_s(:percentage, delimiter: '.', separator: ',') # => 1.000,000% -302.24398923423.to_s(:percentage, precision: 5) +302.24398923423.to_formatted_s(:percentage, precision: 5) # => 302.24399% ``` Produce a string representation of a number in delimited form: ```ruby -12345678.to_s(:delimited) # => 12,345,678 -12345678.05.to_s(:delimited) # => 12,345,678.05 -12345678.to_s(:delimited, delimiter: ".") # => 12.345.678 -12345678.to_s(:delimited, delimiter: ",") # => 12,345,678 -12345678.05.to_s(:delimited, separator: " ") # => 12,345,678 05 +12345678.to_formatted_s(:delimited) # => 12,345,678 +12345678.05.to_formatted_s(:delimited) # => 12,345,678.05 +12345678.to_formatted_s(:delimited, delimiter: ".") # => 12.345.678 +12345678.to_formatted_s(:delimited, delimiter: ",") # => 12,345,678 +12345678.05.to_formatted_s(:delimited, separator: " ") # => 12,345,678 05 ``` Produce a string representation of a number rounded to a precision: ```ruby -111.2345.to_s(:rounded) # => 111.235 -111.2345.to_s(:rounded, precision: 2) # => 111.23 -13.to_s(:rounded, precision: 5) # => 13.00000 -389.32314.to_s(:rounded, precision: 0) # => 389 -111.2345.to_s(:rounded, significant: true) # => 111 +111.2345.to_formatted_s(:rounded) # => 111.235 +111.2345.to_formatted_s(:rounded, precision: 2) # => 111.23 +13.to_formatted_s(:rounded, precision: 5) # => 13.00000 +389.32314.to_formatted_s(:rounded, precision: 0) # => 389 +111.2345.to_formatted_s(:rounded, significant: true) # => 111 ``` Produce a string representation of a number as a human-readable number of bytes: ```ruby -123.to_s(:human_size) # => 123 Bytes -1234.to_s(:human_size) # => 1.21 KB -12345.to_s(:human_size) # => 12.1 KB -1234567.to_s(:human_size) # => 1.18 MB -1234567890.to_s(:human_size) # => 1.15 GB -1234567890123.to_s(:human_size) # => 1.12 TB -1234567890123456.to_s(:human_size) # => 1.1 PB -1234567890123456789.to_s(:human_size) # => 1.07 EB +123.to_formatted_s(:human_size) # => 123 Bytes +1234.to_formatted_s(:human_size) # => 1.21 KB +12345.to_formatted_s(:human_size) # => 12.1 KB +1234567.to_formatted_s(:human_size) # => 1.18 MB +1234567890.to_formatted_s(:human_size) # => 1.15 GB +1234567890123.to_formatted_s(:human_size) # => 1.12 TB +1234567890123456.to_formatted_s(:human_size) # => 1.1 PB +1234567890123456789.to_formatted_s(:human_size) # => 1.07 EB ``` Produce a string representation of a number in human-readable words: ```ruby -123.to_s(:human) # => "123" -1234.to_s(:human) # => "1.23 Thousand" -12345.to_s(:human) # => "12.3 Thousand" -1234567.to_s(:human) # => "1.23 Million" -1234567890.to_s(:human) # => "1.23 Billion" -1234567890123.to_s(:human) # => "1.23 Trillion" -1234567890123456.to_s(:human) # => "1.23 Quadrillion" +123.to_formatted_s(:human) # => "123" +1234.to_formatted_s(:human) # => "1.23 Thousand" +12345.to_formatted_s(:human) # => "12.3 Thousand" +1234567.to_formatted_s(:human) # => "1.23 Million" +1234567890.to_formatted_s(:human) # => "1.23 Billion" +1234567890123.to_formatted_s(:human) # => "1.23 Trillion" +1234567890123456.to_formatted_s(:human) # => "1.23 Quadrillion" ``` NOTE: Defined in `active_support/core_ext/numeric/conversions.rb`. @@ -2160,12 +2160,6 @@ The method `to_s` provides a default specifier of "F". This means that a simple BigDecimal(5.00, 6).to_s # => "5.0" ``` -and that symbol specifiers are also supported: - -```ruby -BigDecimal(5.00, 6).to_s(:db) # => "5.0" -``` - Engineering notation is still supported: ```ruby diff --git a/guides/source/configuring.md b/guides/source/configuring.md index ab25abefd4cc3..10a33c8e7e7f8 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -1388,7 +1388,7 @@ Configures deprecation warnings that the Application considers disallowed. This Allows you to disable all deprecation warnings (including disallowed deprecations); it makes `ActiveSupport::Deprecation.warn` a no-op. This is enabled by default in production. -#### `active_support.isolation_level` +#### `config.active_support.isolation_level` Configures the locality of most of Rails internal state. If you use a fiber based server or job processor (e.g. `falcon`), you should set it to `:fiber`. Otherwise it is best to use `:thread` locality. @@ -1420,6 +1420,13 @@ This makes test cases behave closer to an actual request or job. Several features that are normally disabled in test, such as Active Record query cache and asynchronous queries will then be enabled. +#### `config.active_support.disable_to_s_conversion` + +Disables the override of the `#to_s` methods in some Ruby core classes. This config is for applications that want to +take advantage early of a [Ruby 3.1 optimization](https://github.com/ruby/ruby/commit/b08dacfea39ad8da3f1fd7fdd0e4538cc892ec44). +This configuration needs to be set in `config/application.rb` inside the application class, otherwise it will not take +effect. + #### `ActiveSupport::Logger.silencer` Is set to `false` to disable the ability to silence logging in a block. The default is `true`. @@ -1733,6 +1740,7 @@ Accepts a string for the HTML tag used to wrap attachments. Defaults to `"action - `config.active_support.remove_deprecated_time_with_zone_name`: `true` - `config.active_support.executor_around_test_case`: `true` - `config.active_support.use_rfc4122_namespaced_uuids`: `true` +- `config.active_support.disable_to_s_conversion`: `true` - `config.action_dispatch.return_only_request_media_type_on_content_type`: `false` - `config.action_controller.silence_disabled_session_errors`: `false` - `config.action_mailer.smtp_timeout`: `5` @@ -1828,8 +1836,9 @@ Accepts a string for the HTML tag used to wrap attachments. Defaults to `"action - `config.active_support.key_generator_hash_digest_class`: `OpenSSL::Digest::SHA1` - `config.active_support.cache_format_version`: `6.1` - `config.active_support.executor_around_test_case`: `false` -- `active_support.isolation_level`: `:thread` -- ``config.active_support.use_rfc4122_namespaced_uuids``: `false` +- `config.active_support.isolation_level`: `:thread` +- `config.active_support.use_rfc4122_namespaced_uuids`: `false` +- `config.active_support.disable_to_s_conversion`: `false` - `config.action_dispatch.return_only_request_media_type_on_content_type`: `true` - `ActiveSupport.utc_to_local_returns_utc_offset_times`: `false` - `config.action_mailer.smtp_timeout`: `nil` diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md index 70165b8bc65a2..4cfef0b45f15d 100644 --- a/guides/source/debugging_rails_applications.md +++ b/guides/source/debugging_rails_applications.md @@ -496,7 +496,8 @@ will raise a `NameError`. In some cases, Ruby will be able to resolve an uninten If you hit this, please restart your debugging session with eager loading enabled (`config.eager_load = true`). -Stepping commands line `next`, `continue`, etc., do not present this issue. Namespaces defined implictly only by subdirectories are not subject to this issue either. +Stepping commands line `next`, `continue`, etc., do not present this issue. Namespaces defined implicitly only by +subdirectories are not subject to this issue either. See [ruby/debug#408](https://github.com/ruby/debug/issues/408) for details. diff --git a/guides/source/security.md b/guides/source/security.md index 322354731e895..5d5660db33439 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -216,7 +216,7 @@ One possibility is to set the expiry time-stamp of the cookie with the session I ```ruby class Session < ApplicationRecord def self.sweep(time = 1.hour) - where("updated_at < ?", time.ago.to_s(:db)).delete_all + where("updated_at < ?", time.ago.to_formatted_s(:db)).delete_all end end ``` @@ -224,7 +224,7 @@ end The section about session fixation introduced the problem of maintained sessions. An attacker maintaining a session every five minutes can keep the session alive forever, although you are expiring sessions. A simple solution for this would be to add a `created_at` column to the sessions table. Now you can delete sessions that were created a long time ago. Use this line in the sweep method above: ```ruby -where("updated_at < ? OR created_at < ?", time.ago.to_s(:db), 2.days.ago.to_s(:db)).delete_all +where("updated_at < ? OR created_at < ?", time.ago.to_formatted_s(:db), 2.days.ago.to_formatted_s(:db)).delete_all ``` Cross-Site Request Forgery (CSRF) diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index cebd9a8b52548..c45b58229aece 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -14,6 +14,7 @@ module Bootstrap initializer :load_environment_hook, group: :all do end initializer :load_active_support, group: :all do + ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"] = "true" if config.active_support.disable_to_s_conversion require "active_support/all" unless config.active_support.bare end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index d94b1b7b93997..9e997305a9554 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -223,6 +223,7 @@ def load_defaults(target_version) active_support.use_rfc4122_namespaced_uuids = true active_support.executor_around_test_case = true active_support.isolation_level = :thread + active_support.disable_to_s_conversion = true end if respond_to?(:action_mailer) diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb index 0bea88f511e64..cd37be8111b0c 100644 --- a/railties/lib/rails/generators/generated_attribute.rb +++ b/railties/lib/rails/generators/generated_attribute.rb @@ -123,8 +123,8 @@ def default when :integer then 1 when :float then 1.5 when :decimal then "9.99" - when :datetime, :timestamp, :time then Time.now.to_s(:db) - when :date then Date.today.to_s(:db) + when :datetime, :timestamp, :time then Time.now.to_formatted_s(:db) + when :date then Date.today.to_formatted_s(:db) when :string then name == "type" ? "" : "MyString" when :text then "MyText" when :boolean then false diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index dd3c65d248963..60c38d50a5710 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -3435,6 +3435,76 @@ def new(app); self; end assert_equal [], ActionController::Base._wrapper_options.format end + test "deprecated #to_s with format works with the Rails 6.1 defaults" do + remove_from_config '.*config\.load_defaults.*\n' + add_to_config 'config.load_defaults "6.1"' + + app "production" + + assert_deprecated do + assert_equal "21 Feb", Date.new(2005, 2, 21).to_s(:short) + end + assert_deprecated do + assert_equal "2005-02-21 14:30:00", DateTime.new(2005, 2, 21, 14, 30, 0, 0).to_s(:db) + end + assert_deprecated do + assert_equal "555-1234", 5551234.to_s(:phone) + end + assert_deprecated do + assert_equal "BETWEEN 'a' AND 'z'", ("a".."z").to_s(:db) + end + assert_deprecated do + assert_equal "2005-02-21 17:44:30", Time.utc(2005, 2, 21, 17, 44, 30.12345678901).to_s(:db) + end + end + + test "deprecated #to_s with format does not work with the Rails 6.1 defaults and the config set" do + remove_from_config '.*config\.load_defaults.*\n' + add_to_config 'config.load_defaults "6.1"' + + add_to_config <<-RUBY + config.active_support.disable_to_s_conversion = true + RUBY + + app "production" + + assert_raises(ArgumentError) do + Date.new(2005, 2, 21).to_s(:short) + end + assert_raises(ArgumentError) do + DateTime.new(2005, 2, 21, 14, 30, 0, 0).to_s(:db) + end + assert_raises(TypeError) do + 5551234.to_s(:phone) + end + assert_raises(ArgumentError) do + ("a".."z").to_s(:db) + end + assert_raises(ArgumentError) do + Time.utc(2005, 2, 21, 17, 44, 30.12345678901).to_s(:db) + end + end + + test "deprecated #to_s with format does not work with the Rails 7.0 defaults" do + app "production" + + assert_raises(ArgumentError) do + Date.new(2005, 2, 21).to_s(:short) + end + assert_raises(ArgumentError) do + DateTime.new(2005, 2, 21, 14, 30, 0, 0).to_s(:db) + end + assert_raises(TypeError) do + 5551234.to_s(:phone) + end + assert_raises(ArgumentError) do + ("a".."z").to_s(:db) + end + assert_raises(ArgumentError) do + Time.utc(2005, 2, 21, 17, 44, 30.12345678901).to_s(:db) + end + end + private def set_custom_config(contents, config_source = "custom".inspect) app_file "config/custom.yml", contents diff --git a/railties/test/generators/generated_attribute_test.rb b/railties/test/generators/generated_attribute_test.rb index 122d243cba331..7e945128bcafa 100644 --- a/railties/test/generators/generated_attribute_test.rb +++ b/railties/test/generators/generated_attribute_test.rb @@ -91,12 +91,12 @@ def test_default_value_is_decimal def test_default_value_is_datetime %w(datetime timestamp time).each do |attribute_type| - assert_field_default_value attribute_type, Time.now.to_s(:db) + assert_field_default_value attribute_type, Time.now.to_formatted_s(:db) end end def test_default_value_is_date - assert_field_default_value :date, Date.today.to_s(:db) + assert_field_default_value :date, Date.today.to_formatted_s(:db) end def test_default_value_is_string From 28297402f4b02e0981b67cc5f8b9d95720b29550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 6 Dec 2021 20:02:37 +0000 Subject: [PATCH 021/455] Add releases note about the `#to_s` deprecation. --- activesupport/CHANGELOG.md | 5 +++++ guides/source/7_0_release_notes.md | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index d7cb3639c6f56..c7c5af5670a06 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,8 @@ +* Deprecate passing a format to `#to_s` in favor of `#to_formatted_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`, + `BigDecimal`, `Float` and, `Integer`. + + *Rafael Mendonça França* + * Document `ActiveSupport::Testing::Deprecation`. *Sam Bostock & Sam Jordan* diff --git a/guides/source/7_0_release_notes.md b/guides/source/7_0_release_notes.md index c09a34fb8dd16..5642393ffe102 100644 --- a/guides/source/7_0_release_notes.md +++ b/guides/source/7_0_release_notes.md @@ -248,6 +248,16 @@ Please refer to the [Changelog][active-support] for detailed changes. ### Deprecations +* Deprecate passing a format to `#to_s` in favor of `#to_formatted_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`, + `BigDecimal`, `Float` and, `Integer`. + + This deprecation is to allow Rails application to take advantage of a Ruby 3.1 + [optimization][https://github.com/ruby/ruby/commit/b08dacfea39ad8da3f1fd7fdd0e4538cc892ec44] that makes + interpolation of some types of objects faster. + + New applications will not have the `#to_s` method overriden on those classes, existing applications can use + `config.active_support.disable_to_s_conversion`. + ### Notable changes Active Job From 7c10fe108adfb1cd1c35ce44d5fbc0dd820c76d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 6 Dec 2021 21:27:24 +0000 Subject: [PATCH 022/455] Preparing for 7.0.0.rc1 release --- Gemfile.lock | 108 +++++++++--------- RAILS_VERSION | 2 +- 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 +- 19 files changed, 72 insertions(+), 72 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a9570308c8fa2..154c716483645 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -24,82 +24,82 @@ GIT PATH remote: . specs: - actioncable (7.0.0.alpha2) - actionpack (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + actioncable (7.0.0.rc1) + actionpack (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.0.alpha2) - actionpack (= 7.0.0.alpha2) - activejob (= 7.0.0.alpha2) - activerecord (= 7.0.0.alpha2) - activestorage (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + actionmailbox (7.0.0.rc1) + actionpack (= 7.0.0.rc1) + activejob (= 7.0.0.rc1) + activerecord (= 7.0.0.rc1) + activestorage (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) mail (>= 2.7.1) - actionmailer (7.0.0.alpha2) - actionpack (= 7.0.0.alpha2) - actionview (= 7.0.0.alpha2) - activejob (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + actionmailer (7.0.0.rc1) + actionpack (= 7.0.0.rc1) + actionview (= 7.0.0.rc1) + activejob (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (7.0.0.alpha2) - actionview (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + actionpack (7.0.0.rc1) + actionview (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) rack (~> 2.0, >= 2.2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.0.alpha2) - actionpack (= 7.0.0.alpha2) - activerecord (= 7.0.0.alpha2) - activestorage (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + actiontext (7.0.0.rc1) + actionpack (= 7.0.0.rc1) + activerecord (= 7.0.0.rc1) + activestorage (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + actionview (7.0.0.rc1) + activesupport (= 7.0.0.rc1) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + activejob (7.0.0.rc1) + activesupport (= 7.0.0.rc1) globalid (>= 0.3.6) - activemodel (7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) - activerecord (7.0.0.alpha2) - activemodel (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) - activestorage (7.0.0.alpha2) - actionpack (= 7.0.0.alpha2) - activejob (= 7.0.0.alpha2) - activerecord (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + activemodel (7.0.0.rc1) + activesupport (= 7.0.0.rc1) + activerecord (7.0.0.rc1) + activemodel (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) + activestorage (7.0.0.rc1) + actionpack (= 7.0.0.rc1) + activejob (= 7.0.0.rc1) + activerecord (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (7.0.0.alpha2) + activesupport (7.0.0.rc1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - rails (7.0.0.alpha2) - actioncable (= 7.0.0.alpha2) - actionmailbox (= 7.0.0.alpha2) - actionmailer (= 7.0.0.alpha2) - actionpack (= 7.0.0.alpha2) - actiontext (= 7.0.0.alpha2) - actionview (= 7.0.0.alpha2) - activejob (= 7.0.0.alpha2) - activemodel (= 7.0.0.alpha2) - activerecord (= 7.0.0.alpha2) - activestorage (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + rails (7.0.0.rc1) + actioncable (= 7.0.0.rc1) + actionmailbox (= 7.0.0.rc1) + actionmailer (= 7.0.0.rc1) + actionpack (= 7.0.0.rc1) + actiontext (= 7.0.0.rc1) + actionview (= 7.0.0.rc1) + activejob (= 7.0.0.rc1) + activemodel (= 7.0.0.rc1) + activerecord (= 7.0.0.rc1) + activestorage (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) bundler (>= 1.15.0) - railties (= 7.0.0.alpha2) - railties (7.0.0.alpha2) - actionpack (= 7.0.0.alpha2) - activesupport (= 7.0.0.alpha2) + railties (= 7.0.0.rc1) + railties (7.0.0.rc1) + actionpack (= 7.0.0.rc1) + activesupport (= 7.0.0.rc1) method_source rake (>= 12.2) thor (~> 1.0) @@ -245,7 +245,7 @@ GEM fugit (1.5.0) et-orbi (~> 1.1, >= 1.1.8) raabro (~> 1.4) - globalid (0.6.0) + globalid (1.0.0) activesupport (>= 5.0) google-apis-core (0.3.0) addressable (~> 2.5, >= 2.5.1) diff --git a/RAILS_VERSION b/RAILS_VERSION index 08d7939aaeaa0..cc3a17b94753f 100644 --- a/RAILS_VERSION +++ b/RAILS_VERSION @@ -1 +1 @@ -7.0.0.alpha2 +7.0.0.rc1 diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb index 3aa1b9ff8095b..1848be1d33eaa 100644 --- a/actioncable/lib/action_cable/gem_version.rb +++ b/actioncable/lib/action_cable/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actioncable/package.json b/actioncable/package.json index ca0b3194adbe2..f6f096f81ad76 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actioncable", - "version": "7.0.0-alpha2", + "version": "7.0.0-rc1", "description": "WebSocket framework for Ruby on Rails.", "module": "app/assets/javascripts/actioncable.esm.js", "main": "app/assets/javascripts/actioncable.js", diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb index ea928c3915765..545701beac653 100644 --- a/actionmailbox/lib/action_mailbox/gem_version.rb +++ b/actionmailbox/lib/action_mailbox/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" 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 c500dd9472a52..c8d3ecbab8bd2 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" 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 fcf9db41ab131..76b072ec280f0 100644 --- a/actionpack/lib/action_pack/gem_version.rb +++ b/actionpack/lib/action_pack/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" 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 80203dd40c047..1c78ddd549d4d 100644 --- a/actiontext/lib/action_text/gem_version.rb +++ b/actiontext/lib/action_text/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actiontext/package.json b/actiontext/package.json index af645502758a9..fd16a58fe590d 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,6 +1,6 @@ { "name": "@rails/actiontext", - "version": "7.0.0-alpha2", + "version": "7.0.0-rc1", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", "type": "module", diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb index 751478150ba80..f5d2be2c0a6da 100644 --- a/actionview/lib/action_view/gem_version.rb +++ b/actionview/lib/action_view/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionview/package.json b/actionview/package.json index 93bab77c50ce4..7a3e59d489047 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,6 +1,6 @@ { "name": "@rails/ujs", - "version": "7.0.0-alpha2", + "version": "7.0.0-rc1", "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 0dbb3d98df88f..886ee572dfaeb 100644 --- a/activejob/lib/active_job/gem_version.rb +++ b/activejob/lib/active_job/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" 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 970d8e473f8ca..6a49add7abd39 100644 --- a/activemodel/lib/active_model/gem_version.rb +++ b/activemodel/lib/active_model/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" 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 4b0c8b0f2b8d5..990b5423b9859 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" 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 abefb7b19e0b5..d0dd0cda92b09 100644 --- a/activestorage/lib/active_storage/gem_version.rb +++ b/activestorage/lib/active_storage/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activestorage/package.json b/activestorage/package.json index 60e345d1e3668..b9c6b1654206c 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,6 +1,6 @@ { "name": "@rails/activestorage", - "version": "7.0.0-alpha2", + "version": "7.0.0-rc1", "description": "Attach cloud and local files in Rails applications", "module": "app/assets/javascripts/activestorage.esm.js", "main": "app/assets/javascripts/activestorage.js", diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index aa86e15c71056..a3e9e556137e4 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" 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 0db2c52a0fd25..a9a3674d4bbda 100644 --- a/railties/lib/rails/gem_version.rb +++ b/railties/lib/rails/gem_version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/version.rb b/version.rb index 0db2c52a0fd25..a9a3674d4bbda 100644 --- a/version.rb +++ b/version.rb @@ -10,7 +10,7 @@ module VERSION MAJOR = 7 MINOR = 0 TINY = 0 - PRE = "alpha2" + PRE = "rc1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end From 4850a02741c5081da846867e9ebf4edf70cf2ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 6 Dec 2021 21:38:09 +0000 Subject: [PATCH 023/455] Add CHANGELOG header --- actioncable/CHANGELOG.md | 2 ++ actionmailbox/CHANGELOG.md | 2 ++ actionmailer/CHANGELOG.md | 2 ++ actionpack/CHANGELOG.md | 2 ++ actiontext/CHANGELOG.md | 2 ++ actionview/CHANGELOG.md | 2 ++ activejob/CHANGELOG.md | 2 ++ activemodel/CHANGELOG.md | 2 ++ activerecord/CHANGELOG.md | 2 ++ activestorage/CHANGELOG.md | 2 ++ activesupport/CHANGELOG.md | 2 ++ guides/CHANGELOG.md | 5 +++++ railties/CHANGELOG.md | 2 ++ 13 files changed, 29 insertions(+) diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 612fbb3cb365e..6f4473a4be1fd 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * The Action Cable client now ensures successful channel subscriptions: * The client maintains a set of pending subscriptions until either diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md index 610fb7a467b6b..3d740027a17f7 100644 --- a/actionmailbox/CHANGELOG.md +++ b/actionmailbox/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Removed deprecated environment variable `MAILGUN_INGRESS_API_KEY`. *Rafael Mendonça França* diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 57cdf0765e032..4b52f1b34076f 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Remove deprecated `ActionMailer::DeliveryJob` and `ActionMailer::Parameterized::DeliveryJob` in favor of `ActionMailer::MailDeliveryJob`. diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 6c6eccb23b381..006cacab733cd 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * `Rails.application.executor` hooks can now be called around every request in a `ActionController::TestCase` This helps to better simulate request or job local state being reset between requests and prevent state diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md index 17b606d6ad002..468028cb77cea 100644 --- a/actiontext/CHANGELOG.md +++ b/actiontext/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Fix an issue with how nested lists were displayed when converting to plain text *Matt Swanson* diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 9b4891582a8c0..e9d5225993169 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Support `fields model: [@nested, @model]` the same way as `form_with model: [@nested, @model]`. diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 21cc01dd67374..ce3915bc42202 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Remove deprecated `:return_false_on_aborted_enqueue` option. *Rafael Mendonça França* diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index db9082596af32..99661118ee457 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Remove support to Marshal load Rails 5.x `ActiveModel::AttributeSet` format. *Rafael Mendonça França* diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 87ba34e21a9f7..d883d9d9b86ee 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`. *Rafael Mendonça França* diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md index 8fd499fb399b6..92ac56e362338 100644 --- a/activestorage/CHANGELOG.md +++ b/activestorage/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * `Add ActiveStorage::Blob.compose` to concatenate multiple blobs. *Gannon McGibbon* diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index c7c5af5670a06..d60d490e73a22 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Deprecate passing a format to `#to_s` in favor of `#to_formatted_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`, `BigDecimal`, `Float` and, `Integer`. diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index ee61310ffea9e..20f7fd1157929 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,3 +1,8 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + +* No changes. + + ## Rails 7.0.0.alpha2 (September 15, 2021) ## * No changes. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 7330745db5dad..207195267f4a9 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,5 @@ +## Rails 7.0.0.rc1 (December 06, 2021) ## + * Remove deprecated `config` in `dbconsole`. *Rafael Mendonça França* From 85c95dc1c6eda6e4da629b48446642f32d92a88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 6 Dec 2021 17:36:52 -0500 Subject: [PATCH 024/455] Merge pull request #42599 from santib/use-rails-guides-instead-of-edge-guides Use rails guides instead of edge guides [ci skip] --- .../app/controllers/active_storage/blobs/proxy_controller.rb | 2 +- .../app/controllers/active_storage/blobs/redirect_controller.rb | 2 +- .../active_storage/representations/proxy_controller.rb | 2 +- .../active_storage/representations/redirect_controller.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb b/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb index 0073517db3921..cc90c6b94be46 100644 --- a/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb +++ b/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb @@ -5,7 +5,7 @@ # WARNING: All Active Storage controllers are publicly accessible by default. The # generated URLs are hard to guess, but permanent by design. If your files # require a higher level of protection consider implementing -# {Authenticated Controllers}[https://edgeguides.rubyonrails.org/active_storage_overview.html#authenticated-controllers]. +# {Authenticated Controllers}[https://guides.rubyonrails.org/active_storage_overview.html#authenticated-controllers]. class ActiveStorage::Blobs::ProxyController < ActiveStorage::BaseController include ActiveStorage::SetBlob diff --git a/activestorage/app/controllers/active_storage/blobs/redirect_controller.rb b/activestorage/app/controllers/active_storage/blobs/redirect_controller.rb index 8858249030f79..b4466c8b5247d 100644 --- a/activestorage/app/controllers/active_storage/blobs/redirect_controller.rb +++ b/activestorage/app/controllers/active_storage/blobs/redirect_controller.rb @@ -5,7 +5,7 @@ # WARNING: All Active Storage controllers are publicly accessible by default. The # generated URLs are hard to guess, but permanent by design. If your files # require a higher level of protection consider implementing -# {Authenticated Controllers}[https://edgeguides.rubyonrails.org/active_storage_overview.html#authenticated-controllers]. +# {Authenticated Controllers}[https://guides.rubyonrails.org/active_storage_overview.html#authenticated-controllers]. class ActiveStorage::Blobs::RedirectController < ActiveStorage::BaseController include ActiveStorage::SetBlob diff --git a/activestorage/app/controllers/active_storage/representations/proxy_controller.rb b/activestorage/app/controllers/active_storage/representations/proxy_controller.rb index c903b8216cac8..c31c7bd4a4111 100644 --- a/activestorage/app/controllers/active_storage/representations/proxy_controller.rb +++ b/activestorage/app/controllers/active_storage/representations/proxy_controller.rb @@ -5,7 +5,7 @@ # WARNING: All Active Storage controllers are publicly accessible by default. The # generated URLs are hard to guess, but permanent by design. If your files # require a higher level of protection consider implementing -# {Authenticated Controllers}[https://edgeguides.rubyonrails.org/active_storage_overview.html#authenticated-controllers]. +# {Authenticated Controllers}[https://guides.rubyonrails.org/active_storage_overview.html#authenticated-controllers]. class ActiveStorage::Representations::ProxyController < ActiveStorage::Representations::BaseController def show http_cache_forever public: true do diff --git a/activestorage/app/controllers/active_storage/representations/redirect_controller.rb b/activestorage/app/controllers/active_storage/representations/redirect_controller.rb index 1b70182a1761b..d8a0a1988f487 100644 --- a/activestorage/app/controllers/active_storage/representations/redirect_controller.rb +++ b/activestorage/app/controllers/active_storage/representations/redirect_controller.rb @@ -5,7 +5,7 @@ # WARNING: All Active Storage controllers are publicly accessible by default. The # generated URLs are hard to guess, but permanent by design. If your files # require a higher level of protection consider implementing -# {Authenticated Controllers}[https://edgeguides.rubyonrails.org/active_storage_overview.html#authenticated-controllers]. +# {Authenticated Controllers}[https://guides.rubyonrails.org/active_storage_overview.html#authenticated-controllers]. class ActiveStorage::Representations::RedirectController < ActiveStorage::Representations::BaseController def show expires_in ActiveStorage.service_urls_expire_in From d2de22f0ec61effefef0ccf1fdfd134cfb6fee89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 6 Dec 2021 17:39:14 -0500 Subject: [PATCH 025/455] Merge pull request #43637 from alxjrvs/blob-representation-disposition Fix Rails 7 Regression - ActiveStorage Content Disposition --- .../active_storage/blobs/proxy_controller.rb | 2 +- .../representations/proxy_controller.rb | 2 +- .../controllers/blobs/proxy_controller_test.rb | 8 +++++++- .../representations/proxy_controller_test.rb | 15 +++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb b/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb index cc90c6b94be46..7e43b6040394b 100644 --- a/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb +++ b/activestorage/app/controllers/active_storage/blobs/proxy_controller.rb @@ -17,7 +17,7 @@ def show response.headers["Accept-Ranges"] = "bytes" response.headers["Content-Length"] = @blob.byte_size.to_s - send_blob_stream @blob + send_blob_stream @blob, disposition: params[:disposition] end end end diff --git a/activestorage/app/controllers/active_storage/representations/proxy_controller.rb b/activestorage/app/controllers/active_storage/representations/proxy_controller.rb index c31c7bd4a4111..7e98c2184fdf9 100644 --- a/activestorage/app/controllers/active_storage/representations/proxy_controller.rb +++ b/activestorage/app/controllers/active_storage/representations/proxy_controller.rb @@ -9,7 +9,7 @@ class ActiveStorage::Representations::ProxyController < ActiveStorage::Representations::BaseController def show http_cache_forever public: true do - send_blob_stream @representation.image + send_blob_stream @representation.image, disposition: params[:disposition] end end end diff --git a/activestorage/test/controllers/blobs/proxy_controller_test.rb b/activestorage/test/controllers/blobs/proxy_controller_test.rb index 83bcf3f0f867a..443539aded372 100644 --- a/activestorage/test/controllers/blobs/proxy_controller_test.rb +++ b/activestorage/test/controllers/blobs/proxy_controller_test.rb @@ -21,11 +21,17 @@ class ActiveStorage::Blobs::ProxyControllerTest < ActionDispatch::IntegrationTes assert_equal "application/octet-stream", response.headers["Content-Type"] end - test "forcing Content-Disposition to attachment" do + test "forcing Content-Disposition to attachment based on type" do get rails_storage_proxy_url(create_blob(content_type: "application/zip")) assert_match(/^attachment; /, response.headers["Content-Disposition"]) end + test "caller can change disposition to attachment" do + url = rails_storage_proxy_url(create_blob(content_type: "image/jpeg"), disposition: :attachment) + get url + assert_match(/^attachment; /, response.headers["Content-Disposition"]) + end + test "signed ID within expiration date" do get rails_storage_proxy_url(create_file_blob(filename: "racecar.jpg"), expires_in: 1.minute) assert_response :success diff --git a/activestorage/test/controllers/representations/proxy_controller_test.rb b/activestorage/test/controllers/representations/proxy_controller_test.rb index 8ae815ea1db2e..a20d7f2642dd1 100644 --- a/activestorage/test/controllers/representations/proxy_controller_test.rb +++ b/activestorage/test/controllers/representations/proxy_controller_test.rb @@ -8,6 +8,21 @@ class ActiveStorage::Representations::ProxyControllerWithVariantsTest < ActionDi @blob = create_file_blob filename: "racecar.jpg" end + test "showing variant attachment" do + get rails_blob_representation_proxy_url( + disposition: :attachment, + filename: @blob.filename, + signed_blob_id: @blob.signed_id, + variation_key: ActiveStorage::Variation.encode(resize_to_limit: [100, 100])) + + assert_response :ok + assert_match(/^attachment/, response.headers["Content-Disposition"]) + + image = read_image(@blob.variant(resize_to_limit: [100, 100])) + assert_equal 100, image.width + assert_equal 67, image.height + end + test "showing variant inline" do get rails_blob_representation_proxy_url( filename: @blob.filename, From 326e7150a4fc8aca83eb1c2360ba96b29ccfb319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 6 Dec 2021 20:09:41 -0500 Subject: [PATCH 026/455] Merge pull request #43604 from nikonoid/bug/31722 ActiveRecord::Migration next_migration_number should use numeric version comparison. --- activerecord/lib/active_record/migration.rb | 2 +- activerecord/test/cases/migration_test.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 4b571ce68f14a..56384363e8c0e 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -1001,7 +1001,7 @@ def proper_table_name(name, options = {}) # Determines the version number of the next migration. def next_migration_number(number) if ActiveRecord.timestamped_migrations - [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max + [Time.now.utc.strftime("%Y%m%d%H%M%S").to_i, ("%.14d" % number).to_i].max else SchemaMigration.normalize_migration_number(number) end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 530f1f783361e..53555ce3f3ef5 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -148,6 +148,17 @@ def test_migration_version assert_equal 20131219224947, migrator.current_version end + def test_migration_next_migration_number_consistent_across_year_boundary + last_year = Time.now.year - 1 + this_year = Time.now.year + not_a_month = 14 + day_of_month = Time.now.day + time = Time.now.utc.strftime("%H%M%S") + last_year_number = "#{last_year}#{not_a_month}#{day_of_month}#{time}01" + this_year_number = "#{this_year}#{not_a_month}#{day_of_month}#{time}01" + assert_equal ActiveRecord::Migration.new.next_migration_number(last_year_number).to_s, last_year_number + end + def test_create_table_raises_if_already_exists connection = Person.connection connection.create_table :testings, force: true do |t| From 443d8042f9379b74fe592f1d2f892563c8dedea4 Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Tue, 7 Dec 2021 10:58:09 -0300 Subject: [PATCH 027/455] Merge pull request #43790 from NARKOZ/fix-invalid-option-key Remove obsolete option from new Rails 7.0 defaults --- guides/source/configuring.md | 1 - .../config/initializers/new_framework_defaults_7_0.rb.tt | 4 ---- 2 files changed, 5 deletions(-) diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 10a33c8e7e7f8..cc4d4ebbe6d60 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -1742,7 +1742,6 @@ Accepts a string for the HTML tag used to wrap attachments. Defaults to `"action - `config.active_support.use_rfc4122_namespaced_uuids`: `true` - `config.active_support.disable_to_s_conversion`: `true` - `config.action_dispatch.return_only_request_media_type_on_content_type`: `false` -- `config.action_controller.silence_disabled_session_errors`: `false` - `config.action_mailer.smtp_timeout`: `5` - `config.active_storage.video_preview_arguments`: `"-vf 'select=eq(n\\,0)+eq(key\\,1)+gt(scene\\,0.015),loop=loop=-1:size=2,trim=start_frame=1' -frames:v 1 -f image2"` - `config.active_record.automatic_scope_inversing`: `true` diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt index cf5449464801b..a579326e2087f 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt @@ -9,10 +9,6 @@ # Read the Guide for Upgrading Ruby on Rails for more info on each option. # https://guides.rubyonrails.org/upgrading_ruby_on_rails.html -# Raise an error when trying to use forgery protection without a working -# session. -# Rails.application.config.action_controller.silence_disabled_session_errors = false - # `button_to` view helper will render `