CHANGELOG.md in activesupport-6.0.6.1 vs CHANGELOG.md in activesupport-6.1.0.rc1

- old
+ new

@@ -1,782 +1,546 @@ -## Rails 6.0.6.1 (January 17, 2023) ## +## Rails 6.1.0.rc1 (November 02, 2020) ## -* No changes. +* Calling `iso8601` on negative durations retains the negative sign on individual + digits instead of prepending it. + This change is required so we can interoperate with PostgreSQL, which prefers + negative signs for each component. -## Rails 6.0.6 (September 09, 2022) ## + Compatibility with other iso8601 parsers which support leading negatives as well + as negatives per component is still retained. -* No changes. + Before: + (-1.year - 1.day).iso8601 + # => "-P1Y1D" -## Rails 6.0.5.1 (July 12, 2022) ## + After: -* No changes. + (-1.year - 1.day).iso8601 + # => "P-1Y-1D" + *Vipul A M* -## Rails 6.0.5 (May 09, 2022) ## +* Remove deprecated `ActiveSupport::Notifications::Instrumenter#end=`. -* No changes. + *Rafael Mendonça França* +* Deprecate `ActiveSupport::Multibyte::Unicode.default_normalization_form`. -## Rails 6.0.4.8 (April 26, 2022) ## + *Rafael Mendonça França* -* Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`. +* Remove deprecated `ActiveSupport::Multibyte::Unicode.pack_graphemes`, + `ActiveSupport::Multibyte::Unicode.unpack_graphemes`, + `ActiveSupport::Multibyte::Unicode.normalize`, + `ActiveSupport::Multibyte::Unicode.downcase`, + `ActiveSupport::Multibyte::Unicode.upcase` and `ActiveSupport::Multibyte::Unicode.swapcase`. - Add the method `ERB::Util.xml_name_escape` to escape dangerous characters - in names of tags and names of attributes, following the specification of XML. + *Rafael Mendonça França* - *Álvaro Martín Fraguas* +* Remove deprecated `ActiveSupport::Multibyte::Chars#consumes?` and `ActiveSupport::Multibyte::Chars#normalize`. + *Rafael Mendonça França* -## Rails 6.0.4.7 (March 08, 2022) ## +* Remove deprecated file `active_support/core_ext/range/include_range`. -* No changes. + *Rafael Mendonça França* +* Remove deprecated file `active_support/core_ext/hash/transform_values`. -## Rails 6.0.4.6 (February 11, 2022) ## + *Rafael Mendonça França* -* Fix Reloader method signature to work with the new Executor signature +* Remove deprecated file `active_support/core_ext/hash/compact`. + *Rafael Mendonça França* -## Rails 6.0.4.5 (February 11, 2022) ## +* Remove deprecated file `active_support/core_ext/array/prepend_and_append`. -* No changes. + *Rafael Mendonça França* +* Remove deprecated file `active_support/core_ext/numeric/inquiry`. -## Rails 6.0.4.4 (December 15, 2021) ## + *Rafael Mendonça França* -* No changes. +* Remove deprecated file `active_support/core_ext/module/reachable`. + *Rafael Mendonça França* -## Rails 6.0.4.3 (December 14, 2021) ## +* Remove deprecated `Module#parent_name`, `Module#parent` and `Module#parents`. -* No changes. + *Rafael Mendonça França* +* Remove deprecated `ActiveSupport::LoggerThreadSafeLevel#after_initialize`. -## Rails 6.0.4.2 (December 14, 2021) ## + *Rafael Mendonça França* -* No changes. +* Remove deprecated `LoggerSilence` constant. + *Rafael Mendonça França* -## Rails 6.0.4.1 (August 19, 2021) ## +* Remove deprecated fallback to `I18n.default_local` when `config.i18n.fallbacks` is empty. -* No changes. + *Rafael Mendonça França* +* Remove entries from local cache on `RedisCacheStore#delete_matched` -## Rails 6.0.4 (June 15, 2021) ## + Fixes #38627 -* Fixed issue in `ActiveSupport::Cache::RedisCacheStore` not passing options - to `read_multi` causing `fetch_multi` to not work properly. + *ojab* - *Rajesh Sharma* +* Speed up `ActiveSupport::SecurityUtils.fixed_length_secure_compare` by using + `OpenSSL.fixed_length_secure_compare`, if available. -* `with_options` copies its options hash again to avoid leaking mutations. + *Nate Matykiewicz* - Fixes #39343. +* `ActiveSupport::Cache::MemCacheStore` now checks `ENV["MEMCACHE_SERVERS"]` before falling back to `"localhost:11211"` if configured without any addresses. - *Eugene Kenny* + ```ruby + config.cache_store = :mem_cache_store + # is now equivalent to -## Rails 6.0.3.7 (May 05, 2021) ## + config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211" -* No changes. + # instead of + config.cache_store = :mem_cache_store, "localhost:11211" # ignores ENV["MEMCACHE_SERVERS"] + ``` -## Rails 6.0.3.6 (March 26, 2021) ## + *Sam Bostock* -* No changes. +* `ActiveSupport::Subscriber#attach_to` now accepts an `inherit_all:` argument. When set to true, + it allows a subscriber to receive events for methods defined in the subscriber's ancestor class(es). + ```ruby + class ActionControllerSubscriber < ActiveSupport::Subscriber + attach_to :action_controller -## Rails 6.0.3.5 (February 10, 2021) ## + def start_processing(event) + info "Processing by #{event.payload[:controller]}##{event.payload[:action]} as #{format}" + end -* No changes. + def redirect_to(event) + info { "Redirected to #{event.payload[:location]}" } + end + end + # We detach ActionControllerSubscriber from the :action_controller namespace so that our CustomActionControllerSubscriber + # can provide its own instrumentation for certain events in the namespace + ActionControllerSubscriber.detach_from(:action_controller) -## Rails 6.0.3.4 (October 07, 2020) ## + class CustomActionControllerSubscriber < ActionControllerSubscriber + attach_to :action_controller, inherit_all: true -* No changes. + def start_processing(event) + info "A custom response to start_processing events" + end + # => CustomActionControllerSubscriber will process events for "start_processing.action_controller" notifications + # using its own #start_processing implementation, while retaining ActionControllerSubscriber's instrumentation + # for "redirect_to.action_controller" notifications + end + ``` -## Rails 6.0.3.3 (September 09, 2020) ## + *Adrianna Chang* -* No changes. +* Allow the digest class used to generate non-sensitive digests to be configured with `config.active_support.hash_digest_class`. + `config.active_support.use_sha1_digests` is deprecated in favour of `config.active_support.hash_digest_class = ::Digest::SHA1`. -## Rails 6.0.3.2 (June 17, 2020) ## + *Dirkjan Bussink* -* No changes. +* Fix bug to make memcached write_entry expire correctly with unless_exist + *Jye Lee* -## Rails 6.0.3.1 (May 18, 2020) ## +* Add `ActiveSupport::Duration` conversion methods -* [CVE-2020-8165] Deprecate Marshal.load on raw cache read in RedisCacheStore + `in_seconds`, `in_minutes`, `in_hours`, `in_days`, `in_weeks`, `in_months`, and `in_years` return the respective duration covered. -* [CVE-2020-8165] Avoid Marshal.load on raw cache value in MemCacheStore + *Jason York* +* Fixed issue in `ActiveSupport::Cache::RedisCacheStore` not passing options + to `read_multi` causing `fetch_multi` to not work properly -## Rails 6.0.3 (May 06, 2020) ## + *Rajesh Sharma* -* `Array#to_sentence` no longer returns a frozen string. +* Fixed issue in `ActiveSupport::Cache::MemCacheStore` which caused duplicate compression, + and caused the provided `compression_threshold` to not be respected. - Before: + *Max Gurewitz* - ['one', 'two'].to_sentence.frozen? - # => true +* Prevent `RedisCacheStore` and `MemCacheStore` from performing compression + when reading entries written with `raw: true`. - After: + *Max Gurewitz* - ['one', 'two'].to_sentence.frozen? - # => false +* `URI.parser` is deprecated and will be removed in Rails 6.2. Use + `URI::DEFAULT_PARSER` instead. - *Nicolas Dular* + *Jean Boussier* -* Update `ActiveSupport::Messages::Metadata#fresh?` to work for cookies with expiry set when - `ActiveSupport.parse_json_times = true`. +* `require_dependency` has been documented to be _obsolete_ in `:zeitwerk` + mode. The method is not deprecated as such (yet), but applications are + encouraged to not use it. - *Christian Gregg* + In `:zeitwerk` mode, semantics match Ruby's and you do not need to be + defensive with load order. Just refer to classes and modules normally. If + the constant name is dynamic, camelize if needed, and constantize. + *Xavier Noria* -## Rails 6.0.2.2 (March 19, 2020) ## +* Add 3rd person aliases of `Symbol#start_with?` and `Symbol#end_with?`. -* No changes. + ```ruby + :foo.starts_with?("f") # => true + :foo.ends_with?("o") # => true + ``` + *Ryuta Kamizono* -## Rails 6.0.2.1 (December 18, 2019) ## +* Add override of unary plus for `ActiveSupport::Duration`. -* No changes. + `+ 1.second` is now identical to `+1.second` to prevent errors + where a seemingly innocent change of formatting leads to a change in the code behavior. + Before: + ```ruby + +1.second.class + # => ActiveSupport::Duration + (+ 1.second).class + # => Integer + ``` -## Rails 6.0.2 (December 13, 2019) ## - -* Eager load translations during initialization. - - *Diego Plentz* - -* Use per-thread CPU time clock on `ActiveSupport::Notifications`. - - *George Claghorn* - - -## Rails 6.0.1 (November 5, 2019) ## - -* `ActiveSupport::SafeBuffer` supports `Enumerator` methods. - - *Shugo Maeda* - -* The Redis cache store fails gracefully when the server returns a "max number - of clients reached" error. - - *Brandon Medenwald* - -* Fixed that mutating a value returned by a memory cache store would - unexpectedly change the cached value. - - *Jonathan Hyman* - -* The default inflectors in `zeitwerk` mode support overrides: - + After: ```ruby - # config/initializers/zeitwerk.rb - Rails.autoloaders.each do |autoloader| - autoloader.inflector.inflect( - "html_parser" => "HTMLParser", - "ssl_error" => "SSLError" - ) - end + +1.second.class + # => ActiveSupport::Duration + (+ 1.second).class + # => ActiveSupport::Duration ``` - That way, you can tweak how individual basenames are inflected without touching Active Support inflection rules, which are global. These inflectors fallback to `String#camelize`, so existing inflection rules are still taken into account for non-overridden basenames. + Fixes #39079. - Please, check the [autoloading guide for `zeitwerk` mode](https://guides.rubyonrails.org/v6.0/autoloading_and_reloading_constants.html#customizing-inflections) if you prefer not to depend on `String#camelize` at all. + *Roman Kushnir* - *Xavier Noria* +* Add subsec to `ActiveSupport::TimeWithZone#inspect`. -* Improve `Range#===`, `Range#include?`, and `Range#cover?` to work with beginless (startless) - and endless range targets. - - *Allen Hsu*, *Andrew Hodgkinson* - -* Don't use `Process#clock_gettime(CLOCK_THREAD_CPUTIME_ID)` on Solaris. - - *Iain Beeston* - - -## Rails 6.0.0 (August 16, 2019) ## - -* Let `require_dependency` in `zeitwerk` mode look the autoload paths up for - better backwards compatibility. - - *Xavier Noria* - -* Let `require_dependency` in `zeitwerk` mode support arguments that respond - to `to_path` for better backwards compatibility. - - *Xavier Noria* - -* Make ActiveSupport::Logger Fiber-safe. Fixes #36752. - - Use `Fiber.current.__id__` in `ActiveSupport::Logger#local_level=` in order - to make log level local to Ruby Fibers in addition to Threads. - - Example: - - logger = ActiveSupport::Logger.new(STDOUT) - logger.level = 1 - p "Main is debug? #{logger.debug?}" - - Fiber.new { - logger.local_level = 0 - p "Thread is debug? #{logger.debug?}" - }.resume - - p "Main is debug? #{logger.debug?}" - Before: - Main is debug? false - Thread is debug? true - Main is debug? true + Time.at(1498099140).in_time_zone.inspect + # => "Thu, 22 Jun 2017 02:39:00 UTC +00:00" + Time.at(1498099140, 123456780, :nsec).in_time_zone.inspect + # => "Thu, 22 Jun 2017 02:39:00 UTC +00:00" + Time.at(1498099140 + Rational("1/3")).in_time_zone.inspect + # => "Thu, 22 Jun 2017 02:39:00 UTC +00:00" After: - Main is debug? false - Thread is debug? true - Main is debug? false + Time.at(1498099140).in_time_zone.inspect + # => "Thu, 22 Jun 2017 02:39:00.000000000 UTC +00:00" + Time.at(1498099140, 123456780, :nsec).in_time_zone.inspect + # => "Thu, 22 Jun 2017 02:39:00.123456780 UTC +00:00" + Time.at(1498099140 + Rational("1/3")).in_time_zone.inspect + # => "Thu, 22 Jun 2017 02:39:00.333333333 UTC +00:00" - *Alexander Varnin* + *akinomaeni* -* Do not delegate missing `marshal_dump` and `_dump` methods via the - `delegate_missing_to` extension. This avoids unintentionally adding instance - variables when calling `Marshal.dump(object)`, should the delegation target of - `object` be a method which would otherwise add them. Fixes #36522. +* Calling `ActiveSupport::TaggedLogging#tagged` without a block now returns a tagged logger. - *Aaron Lipman* + ```ruby + logger.tagged("BCX").info("Funky time!") # => [BCX] Funky time! + ``` + *Eugene Kenny* -## Rails 6.0.0.rc2 (July 22, 2019) ## +* Align `Range#cover?` extension behavior with Ruby behavior for backwards ranges. -* `truncate` would return the original string if it was too short to be truncated - and a frozen string if it were long enough to be truncated. Now truncate will - consistently return an unfrozen string regardless. This behavior is consistent - with `gsub` and `strip`. + `(1..10).cover?(5..3)` now returns `false`, as it does in plain Ruby. - Before: + Also update `#include?` and `#===` behavior to match. - 'foobar'.truncate(5).frozen? - # => true - 'foobar'.truncate(6).frozen? - # => false + *Michael Groeneman* - After: +* Update to TZInfo v2.0.0. - 'foobar'.truncate(5).frozen? - # => false - 'foobar'.truncate(6).frozen? - # => false + This changes the output of `ActiveSupport::TimeZone.utc_to_local`, but + can be controlled with the + `ActiveSupport.utc_to_local_returns_utc_offset_times` config. - *Jordan Thomas* + New Rails 6.1 apps have it enabled by default, existing apps can upgrade + via the config in config/initializers/new_framework_defaults_6_1.rb + See the `utc_to_local_returns_utc_offset_times` documentation for details. -## Rails 6.0.0.rc1 (April 24, 2019) ## + *Phil Ross*, *Jared Beck* -* Speed improvements to `Hash.except` and `HashWithIndifferentAccess#except`. +* Add Date and Time `#yesterday?` and `#tomorrow?` alongside `#today?`. - These methods now unset the `default`/`default_proc` on the returned Hash, compatible with Ruby 3.0’s native implementation. + Aliased to `#prev_day?` and `#next_day?` to match the existing `#prev/next_day` methods. - *Timo Schilling* + *Jatin Dhankhar* -* Introduce `ActiveSupport::ActionableError`. +* Add `Enumerable#pick` to complement `ActiveRecord::Relation#pick`. - Actionable errors let's you dispatch actions from Rails' error pages. This - can help you save time if you have a clear action for the resolution of - common development errors. + *Eugene Kenny* - The de-facto example are pending migrations. Every time pending migrations - are found, a middleware raises an error. With actionable errors, you can - run the migrations right from the error page. Other examples include Rails - plugins that need to run a rake task to setup themselves. They can now - raise actionable errors to run the setup straight from the error pages. +* [Breaking change] `ActiveSupport::Callbacks#halted_callback_hook` now receive a 2nd argument: - Here is how to define an actionable error: + `ActiveSupport::Callbacks#halted_callback_hook` now receive the name of the callback + being halted as second argument. + This change will allow you to differentiate which callbacks halted the chain + and act accordingly. ```ruby - class PendingMigrationError < MigrationError #:nodoc: - include ActiveSupport::ActionableError + class Book < ApplicationRecord + before_save { throw(:abort) } + before_create { throw(:abort) } - action "Run pending migrations" do - ActiveRecord::Tasks::DatabaseTasks.migrate + def halted_callback_hook(filter, callback_name) + Rails.logger.info("Book couldn't be #{callback_name}d") + end + + Book.create # => "Book couldn't be created" + book.save # => "Book couldn't be saved" end - end ``` - To make an error actionable, include the `ActiveSupport::ActionableError` - module and invoke the `action` class macro to define the action. An action - needs a name and a procedure to execute. The name is shown as the name of a - button on the error pages. Once clicked, it will invoke the given - procedure. + *Edouard Chin* - *Vipul A M*, *Yao Jie*, *Genadi Samokovarov* +* Support `prepend` with `ActiveSupport::Concern`. -* Preserve `html_safe?` status on `ActiveSupport::SafeBuffer#*`. + Allows a module with `extend ActiveSupport::Concern` to be prepended. - Before: + module Imposter + extend ActiveSupport::Concern - ("<br />".html_safe * 2).html_safe? #=> nil + # Same as `included`, except only run when prepended. + prepended do + end + end - After: + class Person + prepend Imposter + end - ("<br />".html_safe * 2).html_safe? #=> true + Class methods are prepended to the base class, concerning is also + updated: `concerning :Imposter, prepend: true do`. - *Ryo Nakamura* + *Jason Karns*, *Elia Schito* -* Calling test methods with `with_info_handler` method to allow minitest-hooks - plugin to work. +* Deprecate using `Range#include?` method to check the inclusion of a value + in a date time range. It is recommended to use `Range#cover?` method + instead of `Range#include?` to check the inclusion of a value + in a date time range. - *Mauri Mustonen* + *Vishal Telangre* -* The Zeitwerk compatibility interface for `ActiveSupport::Dependencies` no - longer implements `autoloaded_constants` or `autoloaded?` (undocumented, - anyway). Experience shows introspection does not have many use cases, and - troubleshooting is done by logging. With this design trade-off we are able - to use even less memory in all environments. +* Support added for a `round_mode` parameter, in all number helpers. (See: `BigDecimal::mode`.) - *Xavier Noria* + ```ruby + number_to_currency(1234567890.50, precision: 0, round_mode: :half_down) # => "$1,234,567,890" + number_to_percentage(302.24398923423, precision: 5, round_mode: :down) # => "302.24398%" + number_to_rounded(389.32314, precision: 0, round_mode: :ceil) # => "390" + number_to_human_size(483989, precision: 2, round_mode: :up) # => "480 KB" + number_to_human(489939, precision: 2, round_mode: :floor) # => "480 Thousand" -* Depends on Zeitwerk 2, which stores less metadata if reloading is disabled - and hence uses less memory when `config.cache_classes` is `true`, a standard - setup in production. + 485000.to_s(:human, precision: 2, round_mode: :half_even) # => "480 Thousand" + ``` - *Xavier Noria* + *Tom Lord* -* In `:zeitwerk` mode, eager load directories in engines and applications only - if present in their respective `config.eager_load_paths`. +* `Array#to_sentence` no longer returns a frozen string. - A common use case for this is adding `lib` to `config.autoload_paths`, but - not to `config.eager_load_paths`. In that configuration, for example, files - in the `lib` directory should not be eager loaded. - - *Xavier Noria* - -* Fix bug in Range comparisons when comparing to an excluded-end Range - Before: - (1..10).cover?(1...11) # => false + ['one', 'two'].to_sentence.frozen? + # => true After: - (1..10).cover?(1...11) # => true + ['one', 'two'].to_sentence.frozen? + # => false - With the same change for `Range#include?` and `Range#===`. + *Nicolas Dular* - *Owen Stephens* +* When an instance of `ActiveSupport::Duration` is converted to an `iso8601` duration string, if `weeks` are mixed with `date` parts, the `week` part will be converted to days. + This keeps the parser and serializer on the same page. -* Use weak references in descendants tracker to allow anonymous subclasses to - be garbage collected. + ```ruby + duration = ActiveSupport::Duration.build(1000000) + # 1 week, 4 days, 13 hours, 46 minutes, and 40.0 seconds - *Edgars Beigarts* + duration_iso = duration.iso8601 + # P11DT13H46M40S -* Update `ActiveSupport::Notifications::Instrumenter#instrument` to make - passing a block optional. This will let users use - `ActiveSupport::Notifications` messaging features outside of - instrumentation. + ActiveSupport::Duration.parse(duration_iso) + # 11 days, 13 hours, 46 minutes, and 40 seconds - *Ali Ibrahim* + duration = ActiveSupport::Duration.build(604800) + # 1 week -* Fix `Time#advance` to work with dates before 1001-03-07 + duration_iso = duration.iso8601 + # P1W - Before: - - Time.utc(1001, 3, 6).advance(years: -1) # => 1000-03-05 00:00:00 UTC - - After - - Time.utc(1001, 3, 6).advance(years: -1) # => 1000-03-06 00:00:00 UTC - - Note that this doesn't affect `DateTime#advance` as that doesn't use a proleptic calendar. - - *Andrew White* - -* In Zeitwerk mode, engines are now managed by the `main` autoloader. Engines may reference application constants, if the application is reloaded and we do not reload engines, they won't use the reloaded application code. - - *Xavier Noria* - -* Add support for supplying `locale` to `transliterate` and `parameterize`. - - I18n.backend.store_translations(:de, i18n: { transliterate: { rule: { "ü" => "ue" } } }) - - ActiveSupport::Inflector.transliterate("ü", locale: :de) # => "ue" - "Fünf autos".parameterize(locale: :de) # => "fuenf-autos" - ActiveSupport::Inflector.parameterize("Fünf autos", locale: :de) # => "fuenf-autos" - - *Kaan Ozkan*, *Sharang Dashputre* - -* Allow `Array#excluding` and `Enumerable#excluding` to deal with a passed array gracefully. - - [ 1, 2, 3, 4, 5 ].excluding([4, 5]) # => [ 1, 2, 3 ] - - *DHH* - -* Renamed `Array#without` and `Enumerable#without` to `Array#excluding` and `Enumerable#excluding`, to create parity with - `Array#including` and `Enumerable#including`. Retained the old names as aliases. - - *DHH* - -* Added `Array#including` and `Enumerable#including` to conveniently enlarge a collection with more members using a method rather than an operator: - - [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ] - post.authors.including(Current.person) # => All the authors plus the current person! - - *DHH* - - -## Rails 6.0.0.beta3 (March 11, 2019) ## - -* No changes. - - -## Rails 6.0.0.beta2 (February 25, 2019) ## - -* New autoloading based on [Zeitwerk](https://github.com/fxn/zeitwerk). - - *Xavier Noria* - -* Revise `ActiveSupport::Notifications.unsubscribe` to correctly handle Regex or other multiple-pattern subscribers. - - *Zach Kemp* - -* Add `before_reset` callback to `CurrentAttributes` and define `after_reset` as an alias of `resets` for symmetry. - - *Rosa Gutierrez* - -* Remove the `` Kernel#` `` override that suppresses ENOENT and accidentally returns nil on Unix systems. - - *Akinori Musha* - -* Add `ActiveSupport::HashWithIndifferentAccess#assoc`. - - `assoc` can now be called with either a string or a symbol. - - *Stefan Schüßler* - -* Add `Hash#deep_transform_values`, and `Hash#deep_transform_values!`. - - *Guillermo Iguaran* - - -## Rails 6.0.0.beta1 (January 18, 2019) ## - -* Remove deprecated `Module#reachable?` method. - - *Rafael Mendonça França* - -* Remove deprecated `#acronym_regex` method from `Inflections`. - - *Rafael Mendonça França* - -* Fix `String#safe_constantize` throwing a `LoadError` for incorrectly cased constant references. - - *Keenan Brock* - -* Preserve key order passed to `ActiveSupport::CacheStore#fetch_multi`. - - `fetch_multi(*names)` now returns its results in the same order as the `*names` requested, rather than returning cache hits followed by cache misses. - - *Gannon McGibbon* - -* If the same block is `included` multiple times for a Concern, an exception is no longer raised. - - *Mark J. Titorenko*, *Vlad Bokov* - -* Fix bug where `#to_options` for `ActiveSupport::HashWithIndifferentAccess` - would not act as alias for `#symbolize_keys`. - - *Nick Weiland* - -* Improve the logic that detects non-autoloaded constants. - - *Jan Habermann*, *Xavier Noria* - -* Deprecate `ActiveSupport::Multibyte::Unicode#pack_graphemes(array)` and `ActiveSupport::Multibyte::Unicode#unpack_graphemes(string)` - in favor of `array.flatten.pack("U*")` and `string.scan(/\X/).map(&:codepoints)`, respectively. - - *Francesco Rodríguez* - -* Deprecate `ActiveSupport::Multibyte::Chars.consumes?` in favor of `String#is_utf8?`. - - *Francesco Rodríguez* - -* Fix duration being rounded to a full second. + ActiveSupport::Duration.parse(duration_iso) + # 1 week ``` - time = DateTime.parse("2018-1-1") - time += 0.51.seconds - ``` - Will now correctly add 0.51 second and not 1 full second. - *Edouard Chin* + *Abhishek Sarkar* -* Deprecate `ActiveSupport::Multibyte::Unicode#normalize` and `ActiveSupport::Multibyte::Chars#normalize` - in favor of `String#unicode_normalize` +* Add block support to `ActiveSupport::Testing::TimeHelpers#travel_back`. - *Francesco Rodríguez* + *Tim Masliuchenko* -* Deprecate `ActiveSupport::Multibyte::Unicode#downcase/upcase/swapcase` in favor of - `String#downcase/upcase/swapcase`. +* Update `ActiveSupport::Messages::Metadata#fresh?` to work for cookies with expiry set when + `ActiveSupport.parse_json_times = true`. - *Francesco Rodríguez* + *Christian Gregg* -* Add `ActiveSupport::ParameterFilter`. +* Support symbolic links for `content_path` in `ActiveSupport::EncryptedFile`. - *Yoshiyuki Kinjo* + *Takumi Shotoku* -* Rename `Module#parent`, `Module#parents`, and `Module#parent_name` to - `module_parent`, `module_parents`, and `module_parent_name`. +* Improve `Range#===`, `Range#include?`, and `Range#cover?` to work with beginless (startless) + and endless range targets. - *Gannon McGibbon* + *Allen Hsu*, *Andrew Hodgkinson* -* Deprecate the use of `LoggerSilence` in favor of `ActiveSupport::LoggerSilence` +* Don't use `Process#clock_gettime(CLOCK_THREAD_CPUTIME_ID)` on Solaris. - *Edouard Chin* + *Iain Beeston* -* Deprecate using negative limits in `String#first` and `String#last`. +* Prevent `ActiveSupport::Duration.build(value)` from creating instances of + `ActiveSupport::Duration` unless `value` is of type `Numeric`. - *Gannon McGibbon*, *Eric Turner* + Addresses the errant set of behaviours described in #37012 where + `ActiveSupport::Duration` comparisons would fail confusingly + or return unexpected results when comparing durations built from instances of `String`. -* Fix bug where `#without` for `ActiveSupport::HashWithIndifferentAccess` would fail - with symbol arguments + Before: - *Abraham Chan* + small_duration_from_string = ActiveSupport::Duration.build('9') + large_duration_from_string = ActiveSupport::Duration.build('100000000000000') + small_duration_from_int = ActiveSupport::Duration.build(9) -* Treat `#delete_prefix`, `#delete_suffix` and `#unicode_normalize` results as non-`html_safe`. - Ensure safety of arguments for `#insert`, `#[]=` and `#replace` calls on `html_safe` Strings. + large_duration_from_string > small_duration_from_string + # => false - *Janosch Müller* + small_duration_from_string == small_duration_from_int + # => false -* Changed `ActiveSupport::TaggedLogging.new` to return a new logger instance instead - of mutating the one received as parameter. + small_duration_from_int < large_duration_from_string + # => ArgumentError (comparison of ActiveSupport::Duration::Scalar with ActiveSupport::Duration failed) - *Thierry Joyal* + large_duration_from_string > small_duration_from_int + # => ArgumentError (comparison of String with ActiveSupport::Duration failed) -* Define `unfreeze_time` as an alias of `travel_back` in `ActiveSupport::Testing::TimeHelpers`. + After: - The alias is provided for symmetry with `freeze_time`. + small_duration_from_string = ActiveSupport::Duration.build('9') + # => TypeError (can't build an ActiveSupport::Duration from a String) - *Ryan Davidson* + *Alexei Emam* -* Add support for tracing constant autoloads. Just throw +* Add `ActiveSupport::Cache::Store#delete_multi` method to delete multiple keys from the cache store. - ActiveSupport::Dependencies.logger = Rails.logger - ActiveSupport::Dependencies.verbose = true + *Peter Zhu* - in an initializer. +* Support multiple arguments in `HashWithIndifferentAccess` for `merge` and `update` methods, to + follow Ruby 2.6 addition. - *Xavier Noria* + *Wojciech Wnętrzak* -* Maintain `html_safe?` on html_safe strings when sliced. +* Allow initializing `thread_mattr_*` attributes via `:default` option. - string = "<div>test</div>".html_safe - string[-1..1].html_safe? # => true - - *Elom Gomez*, *Yumin Wong* - -* Add `Array#extract!`. - - The method removes and returns the elements for which the block returns a true value. - If no block is given, an Enumerator is returned instead. - - numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9] - numbers # => [0, 2, 4, 6, 8] - - *bogdanvlviv* - -* Support not to cache `nil` for `ActiveSupport::Cache#fetch`. - - cache.fetch('bar', skip_nil: true) { nil } - cache.exist?('bar') # => false - - *Martin Hong* - -* Add "event object" support to the notification system. - Before this change, end users were forced to create hand made artisanal - event objects on their own, like this: - - ActiveSupport::Notifications.subscribe('wait') do |*args| - @event = ActiveSupport::Notifications::Event.new(*args) + class Scraper + thread_mattr_reader :client, default: Api::Client.new end - ActiveSupport::Notifications.instrument('wait') do - sleep 1 - end + *Guilherme Mansur* - @event.duration # => 1000.138 +* Add `compact_blank` for those times when you want to remove #blank? values from + an Enumerable (also `compact_blank!` on Hash, Array, ActionController::Parameters). - After this change, if the block passed to `subscribe` only takes one - parameter, the framework will yield an event object to the block. Now - end users are no longer required to make their own: + *Dana Sherson* - ActiveSupport::Notifications.subscribe('wait') do |event| - @event = event - end +* Make ActiveSupport::Logger Fiber-safe. - ActiveSupport::Notifications.instrument('wait') do - sleep 1 - end + Use `Fiber.current.__id__` in `ActiveSupport::Logger#local_level=` in order + to make log level local to Ruby Fibers in addition to Threads. - p @event.allocations # => 7 - p @event.cpu_time # => 0.256 - p @event.idle_time # => 1003.2399 + Example: - Now you can enjoy event objects without making them yourself. Neat! + logger = ActiveSupport::Logger.new(STDOUT) + logger.level = 1 + puts "Main is debug? #{logger.debug?}" - *Aaron "t.lo" Patterson* + Fiber.new { + logger.local_level = 0 + puts "Thread is debug? #{logger.debug?}" + }.resume -* Add cpu_time, idle_time, and allocations to Event. + puts "Main is debug? #{logger.debug?}" - *Eileen M. Uchitelle*, *Aaron Patterson* + Before: -* RedisCacheStore: support key expiry in increment/decrement. + Main is debug? false + Thread is debug? true + Main is debug? true - Pass `:expires_in` to `#increment` and `#decrement` to set a Redis EXPIRE on the key. + After: - If the key is already set to expire, RedisCacheStore won't extend its expiry. + Main is debug? false + Thread is debug? true + Main is debug? false - Rails.cache.increment("some_key", 1, expires_in: 2.minutes) + Fixes #36752. - *Jason Lee* + *Alexander Varnin* -* Allow `Range#===` and `Range#cover?` on Range. +* Allow the `on_rotation` proc used when decrypting/verifying a message to be + passed at the constructor level. - `Range#cover?` can now accept a range argument like `Range#include?` and - `Range#===`. `Range#===` works correctly on Ruby 2.6. `Range#include?` is moved - into a new file, with these two methods. + Before: - *Requiring active_support/core_ext/range/include_range is now deprecated.* - *Use `require "active_support/core_ext/range/compare_range"` instead.* + crypt = ActiveSupport::MessageEncryptor.new('long_secret') + crypt.decrypt_and_verify(encrypted_message, on_rotation: proc { ... }) + crypt.decrypt_and_verify(another_encrypted_message, on_rotation: proc { ... }) - *utilum* + After: -* Add `index_with` to Enumerable. + crypt = ActiveSupport::MessageEncryptor.new('long_secret', on_rotation: proc { ... }) + crypt.decrypt_and_verify(encrypted_message) + crypt.decrypt_and_verify(another_encrypted_message) - Allows creating a hash from an enumerable with the value from a passed block - or a default argument. + *Edouard Chin* - %i( title body ).index_with { |attr| post.public_send(attr) } - # => { title: "hey", body: "what's up?" } +* `delegate_missing_to` would raise a `DelegationError` if the object + delegated to was `nil`. Now the `allow_nil` option has been added to enable + the user to specify they want `nil` returned in this case. - %i( title body ).index_with(nil) - # => { title: nil, body: nil } + *Matthew Tanous* - Closely linked with `index_by`, which creates a hash where the keys are extracted from a block. +* `truncate` would return the original string if it was too short to be truncated + and a frozen string if it were long enough to be truncated. Now truncate will + consistently return an unfrozen string regardless. This behavior is consistent + with `gsub` and `strip`. - *Kasper Timm Hansen* + Before: -* Fix bug where `ActiveSupport::TimeZone.all` would fail when tzinfo data for - any timezone defined in `ActiveSupport::TimeZone::MAPPING` is missing. + 'foobar'.truncate(5).frozen? + # => true + 'foobar'.truncate(6).frozen? + # => false - *Dominik Sander* + After: -* Redis cache store: `delete_matched` no longer blocks the Redis server. - (Switches from evaled Lua to a batched SCAN + DEL loop.) + 'foobar'.truncate(5).frozen? + # => false + 'foobar'.truncate(6).frozen? + # => false - *Gleb Mazovetskiy* + *Jordan Thomas* -* Fix bug where `ActiveSupport::Cache` will massively inflate the storage - size when compression is enabled (which is true by default). This patch - does not attempt to repair existing data: please manually flush the cache - to clear out the problematic entries. - *Godfrey Chan* - -* Fix bug where `URI.unescape` would fail with mixed Unicode/escaped character input: - - URI.unescape("\xe3\x83\x90") # => "バ" - URI.unescape("%E3%83%90") # => "バ" - URI.unescape("\xe3\x83\x90%E3%83%90") # => Encoding::CompatibilityError - - *Ashe Connor*, *Aaron Patterson* - -* Add `before?` and `after?` methods to `Date`, `DateTime`, - `Time`, and `TimeWithZone`. - - *Nick Holden* - -* `ActiveSupport::Inflector#ordinal` and `ActiveSupport::Inflector#ordinalize` now support - translations through I18n. - - # locale/fr.rb - - { - fr: { - number: { - nth: { - ordinals: lambda do |_key, number:, **_options| - if number.to_i.abs == 1 - 'er' - else - 'e' - end - end, - - ordinalized: lambda do |_key, number:, **_options| - "#{number}#{ActiveSupport::Inflector.ordinal(number)}" - end - } - } - } - } - - - *Christian Blais* - -* Add `:private` option to ActiveSupport's `Module#delegate` - in order to delegate methods as private: - - class User < ActiveRecord::Base - has_one :profile - delegate :date_of_birth, to: :profile, private: true - - def age - Date.today.year - date_of_birth.year - end - end - - # User.new.age # => 29 - # User.new.date_of_birth - # => NoMethodError: private method `date_of_birth' called for #<User:0x00000008221340> - - *Tomas Valent* - -* `String#truncate_bytes` to truncate a string to a maximum bytesize without - breaking multibyte characters or grapheme clusters like 👩‍👩‍👦‍👦. - - *Jeremy Daer* - -* `String#strip_heredoc` preserves frozenness. - - "foo".freeze.strip_heredoc.frozen? # => true - - Fixes that frozen string literals would inadvertently become unfrozen: - - # frozen_string_literal: true - - foo = <<-MSG.strip_heredoc - la la la - MSG - - foo.frozen? # => false !?? - - *Jeremy Daer* - -* Rails 6 requires Ruby 2.5.0 or newer. - - *Jeremy Daer*, *Kasper Timm Hansen* - -* Adds parallel testing to Rails. - - Parallelize your test suite with forked processes or threads. - - *Eileen M. Uchitelle*, *Aaron Patterson* - - -Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/activesupport/CHANGELOG.md) for previous changes. +Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activesupport/CHANGELOG.md) for previous changes.