14 KiB
-
ActiveSupport::CurrentAttributes.resets
now accepts a method nameThe block API is still the recommended approach, but now both APIs are supported:
class Current < ActiveSupport::CurrentAttributes resets { Time.zone = nil } resets :clear_time_zone end
Alex Ghiculescu
-
Ensure
ActiveSupport::Testing::Isolation::Forking
closes pipesPreviously,
Forking.run_in_isolation
opened two ends of a pipe. The fork process closed the read end, wrote to it, and then terminated (which presumably closed the file descriptors on its end). The parent process closed the write end, read from it, and returned, never closing the read end.This resulted in an accumulation of open file descriptors, which could cause errors if the limit is reached.
Sam Bostock
-
Fix
Time#change
andTime#advance
for times around the end of Daylight Saving Time.Previously, when
Time#change
orTime#advance
constructed a time inside the final stretch of Daylight Saving Time (DST), the non-DST offset would always be chosen for local times:# DST ended just before 2021-11-07 2:00:00 AM in US/Eastern. ENV["TZ"] = "US/Eastern" time = Time.local(2021, 11, 07, 00, 59, 59) + 1 # => 2021-11-07 01:00:00 -0400 time.change(day: 07) # => 2021-11-07 01:00:00 -0500 time.advance(seconds: 0) # => 2021-11-07 01:00:00 -0500 time = Time.local(2021, 11, 06, 01, 00, 00) # => 2021-11-06 01:00:00 -0400 time.change(day: 07) # => 2021-11-07 01:00:00 -0500 time.advance(days: 1) # => 2021-11-07 01:00:00 -0500
And the DST offset would always be chosen for times with a
TimeZone
object:Time.zone = "US/Eastern" time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600 # => 2021-11-07 01:00:00 -0500 time.change(day: 07) # => 2021-11-07 01:00:00 -0400 time.advance(seconds: 0) # => 2021-11-07 01:00:00 -0400 time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone) # => 2021-11-08 01:00:00 -0500 time.change(day: 07) # => 2021-11-07 01:00:00 -0400 time.advance(days: -1) # => 2021-11-07 01:00:00 -0400
Now,
Time#change
andTime#advance
will choose the offset that matches the original time's offset when possible:ENV["TZ"] = "US/Eastern" time = Time.local(2021, 11, 07, 00, 59, 59) + 1 # => 2021-11-07 01:00:00 -0400 time.change(day: 07) # => 2021-11-07 01:00:00 -0400 time.advance(seconds: 0) # => 2021-11-07 01:00:00 -0400 time = Time.local(2021, 11, 06, 01, 00, 00) # => 2021-11-06 01:00:00 -0400 time.change(day: 07) # => 2021-11-07 01:00:00 -0400 time.advance(days: 1) # => 2021-11-07 01:00:00 -0400 Time.zone = "US/Eastern" time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600 # => 2021-11-07 01:00:00 -0500 time.change(day: 07) # => 2021-11-07 01:00:00 -0500 time.advance(seconds: 0) # => 2021-11-07 01:00:00 -0500 time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone) # => 2021-11-08 01:00:00 -0500 time.change(day: 07) # => 2021-11-07 01:00:00 -0500 time.advance(days: -1) # => 2021-11-07 01:00:00 -0500
Kevin Hall, Takayoshi Nishida, and Jonathan Hefner
-
Fix MemoryStore to preserve entries TTL when incrementing or decrementing
This is to be more consistent with how MemCachedStore and RedisCacheStore behaves.
Jean Boussier
-
Rails.error.handle
andRails.error.record
filter now by multiple error classes.Rails.error.handle(IOError, ArgumentError) do 1 + '1' # raises TypeError end 1 + 1 # TypeErrors are not IOErrors or ArgumentError, so this will *not* be handled
Martin Spickermann
-
Class#subclasses
andClass#descendants
now automatically filter reloaded classes.Previously they could return old implementations of reloadable classes that have been dereferenced but not yet garbage collected.
They now automatically filter such classes like
DescendantTracker#subclasses
andDescendantTracker#descendants
.Jean Boussier
-
Rails.error.report
now marks errors as reported to avoid reporting them twice.In some cases, users might want to report errors explicitly with some extra context before letting it bubble up.
This also allows to safely catch and report errors outside of the execution context.
Jean Boussier
-
Add
assert_error_reported
andassert_no_error_reported
Allows to easily asserts an error happened but was handled
report = assert_error_reported(IOError) do # ... end assert_equal "Oops", report.error.message assert_equal "admin", report.context[:section] assert_equal :warning, report.severity assert_predicate report, :handled?
Jean Boussier
-
ActiveSupport::Deprecation
behavior callbacks can now receive the deprecator instance as an argument. This makes it easier for such callbacks to change their behavior based on the deprecator's state. For example, based on the deprecator'sdebug
flag.3-arity and splat-args callbacks such as the following will now be passed the deprecator instance as their third argument:
->(message, callstack, deprecator) { ... }
->(*args) { ... }
->(message, *other_args) { ... }
2-arity and 4-arity callbacks such as the following will continue to behave the same as before:
->(message, callstack) { ... }
->(message, callstack, deprecation_horizon, gem_name) { ... }
->(message, callstack, *deprecation_details) { ... }
Jonathan Hefner
-
ActiveSupport::Deprecation#disallowed_warnings
now affects the instance on which it is configured.This means that individual
ActiveSupport::Deprecation
instances can be configured with their own disallowed warnings, and the globalActiveSupport::Deprecation.disallowed_warnings
now only affects the globalActiveSupport::Deprecation.warn
.Before
ActiveSupport::Deprecation.disallowed_warnings = ["foo"] deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem") deprecator.disallowed_warnings = ["bar"] ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar" deprecator.warn("foo") # => raise ActiveSupport::DeprecationException deprecator.warn("bar") # => print "DEPRECATION WARNING: bar"
After
ActiveSupport::Deprecation.disallowed_warnings = ["foo"] deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem") deprecator.disallowed_warnings = ["bar"] ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar" deprecator.warn("foo") # => print "DEPRECATION WARNING: foo" deprecator.warn("bar") # => raise ActiveSupport::DeprecationException
Jonathan Hefner
-
Add italic and underline support to
ActiveSupport::LogSubscriber#color
Previously, only bold text was supported via a positional argument. This allows for bold, italic, and underline options to be specified for colored logs.
info color("Hello world!", :red, bold: true, underline: true)
Gannon McGibbon
-
Add
String#downcase_first
method.This method is the corollary of
String#upcase_first
.Mark Schneider
-
thread_mattr_accessor
will call.dup.freeze
on non-frozen default values.This provides a basic level of protection against different threads trying to mutate a shared default object.
Jonathan Hefner
-
Add
raise_on_invalid_cache_expiration_time
config toActiveSupport::Cache::Store
Specifies if an
ArgumentError
should be raised ifRails.cache
fetch
orwrite
are given an invalidexpires_at
orexpires_in
time.Options are
true
, andfalse
. Iffalse
, the exception will be reported ashandled
and logged instead. Defaults totrue
ifconfig.load_defaults >= 7.1
.Trevor Turk
-
ActiveSupport::Cache:Store#fetch
now passes an options accessor to the block.It makes possible to override cache options:
Rails.cache.fetch("3rd-party-token") do |name, options| token = fetch_token_from_remote # set cache's TTL to match token's TTL options.expires_in = token.expires_in token end
Andrii Gladkyi, Jean Boussier
-
default
option ofthread_mattr_accessor
now applies through inheritance and also across new threads.Previously, the
default
value provided was set only at the moment of defining the attribute writer, which would cause the attribute to be uninitialized in descendants and in other threads.Fixes #43312.
Thierry Deo
-
Redis cache store is now compatible with redis-rb 5.0.
Jean Boussier
-
Add
skip_nil:
support toActiveSupport::Cache::Store#fetch_multi
.Daniel Alfaro
-
Add
quarter
method to date/timeMatt Swanson
-
Fix
NoMethodError
on customActiveSupport::Deprecation
behavior.ActiveSupport::Deprecation.behavior=
was supposed to accept any object that responds tocall
, but in fact its internal implementation assumed that this object could respond toarity
, so it was restricted to onlyProc
objects.This change removes this
arity
restriction of custom behaviors.Ryo Nakamura
-
Support
:url_safe
option forMessageEncryptor
.The
MessageEncryptor
constructor now accepts a:url_safe
option, similar to theMessageVerifier
constructor. When enabled, this option ensures that messages use a URL-safe encoding.Jonathan Hefner
-
Add
url_safe
option toActiveSupport::MessageVerifier
initializerActiveSupport::MessageVerifier.new
now takes optionalurl_safe
argument. It can generate URL-safe strings by passingurl_safe: true
.verifier = ActiveSupport::MessageVerifier.new(url_safe: true) message = verifier.generate(data) # => URL-safe string
This option is
false
by default to be backwards compatible.Shouichi Kamiya
-
Enable connection pooling by default for
MemCacheStore
andRedisCacheStore
.If you want to disable connection pooling, set
:pool
option tofalse
when configuring the cache store:config.cache_store = :mem_cache_store, "cache.example.com", pool: false
fatkodima
-
Add
force:
support toActiveSupport::Cache::Store#fetch_multi
.fatkodima
-
Deprecated
:pool_size
and:pool_timeout
options for configuring connection pooling in cache stores.Use
pool: true
to enable pooling with default settings:config.cache_store = :redis_cache_store, pool: true
Or pass individual options via
:pool
option:config.cache_store = :redis_cache_store, pool: { size: 10, timeout: 2 }
fatkodima
-
Allow #increment and #decrement methods of
ActiveSupport::Cache::Store
subclasses to set new values.Previously incrementing or decrementing an unset key would fail and return nil. A default will now be assumed and the key will be created.
Andrej Blagojević, Eugene Kenny
-
Add
skip_nil:
support toRedisCacheStore
Joey Paris
-
ActiveSupport::Cache::MemoryStore#write(name, val, unless_exist:true)
now correctly writes expired keys.Alan Savage
-
ActiveSupport::ErrorReporter
now accepts and forward asource:
parameter.This allow libraries to signal the origin of the errors, and reporters to easily ignore some sources.
Jean Boussier
-
Fix and add protections for XSS in
ActionView::Helpers
andERB::Util
.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.Álvaro Martín Fraguas
-
Respect
ActiveSupport::Logger.new
's:formatter
keyword argumentThe stdlib
Logger::new
allows passing a:formatter
keyword argument to set the logger's formatter. PreviouslyActiveSupport::Logger.new
ignored that argument by always setting the formatter to an instance ofActiveSupport::Logger::SimpleFormatter
.Steven Harman
-
Deprecate preserving the pre-Ruby 2.4 behavior of
to_time
With Ruby 2.4+ the default for +to_time+ changed from converting to the local system time to preserving the offset of the receiver. At the time Rails supported older versions of Ruby so a compatibility layer was added to assist in the migration process. From Rails 5.0 new applications have defaulted to the Ruby 2.4+ behavior and since Rails 7.0 now only supports Ruby 2.7+ this compatibility layer can be safely removed.
To minimize any noise generated the deprecation warning only appears when the setting is configured to
false
as that is the only scenario where the removal of the compatibility layer has any effect.Andrew White
-
Pathname.blank?
only returns true forPathname.new("")
Previously it would end up calling
Pathname#empty?
which returned true if the path existed and was an empty directory or file.That behavior was unlikely to be expected.
Jean Boussier
-
Deprecate
Notification::Event
's#children
and#parent_of?
John Hawthorn
-
Change default serialization format of
MessageEncryptor
fromMarshal
toJSON
for Rails 7.1.Existing apps are provided with an upgrade path to migrate to
JSON
as described inguides/source/upgrading_ruby_on_rails.md
Zack Deveau and Martin Gingras
-
Add
ActiveSupport::TestCase#stub_const
to stub a constant for the duration of a yield.DHH
-
Fix
ActiveSupport::EncryptedConfiguration
to be compatible with Psych 4Stephen Sugden
-
Improve
File.atomic_write
error handlingDaniel Pepper
-
Fix
Class#descendants
andDescendantsTracker#descendants
compatibility with Ruby 3.1.The native
Class#descendants
was reverted prior to Ruby 3.1 release, butClass#subclasses
was kept, breaking the feature detection.Jean Boussier
Please check 7-0-stable for previous changes.