Commit Graph

1620 Commits

Author SHA1 Message Date
Rafael Mendonça França
ddd6f8ecfe
Merge pull request #47771 from a5-stable/add-more-storage-units
Add zettabyte to `number_to_human_size`
2023-03-29 11:52:45 -04:00
fatkodima
ba2a26e083 Fix Enumerable#in_order_of to preserve duplicates 2023-03-29 15:15:14 +03:00
a5-stable
b9a5a4bed8 add zetta to number_to_human_size 2023-03-28 19:50:13 +09:00
Jean Boussier
210932662b Also undefine with on Symbol 2023-03-16 11:04:19 +00:00
Jean Boussier
dc6bfecdef Undefine with on NilClass and other common immediate types
with isn't usable on immediates, so we might as well undefine the
method in common immediate classes to avoid potential confusion.
2023-03-16 10:29:54 +00:00
Akira Matsuda
217411564e Implement SafeBuffer#bytesplice
[CVE-2023-28120]
2023-03-13 12:13:31 -07:00
Jonathan Hefner
88c12a7bea Remove obsolete assert_not_deprecated
Follow-up to e9bc620f786d7da9afb82ec13ca3ec249f856c0c and
3ec629784cac7a8b518feb402475153465cd8e96.

`assert_not_deprecated` without any arguments will test against
`ActiveSupport::Deprecation.instance`, whereas `Enumerable#sum` would
use `ActiveSupport.deprecator`.  However, the `Enumerable#sum` override
was removed in 3ec629784cac7a8b518feb402475153465cd8e96, so we can
simply remove `assert_not_deprecated`.
2023-03-10 12:55:30 -06:00
Jean Boussier
1884323574 Implement Object#with
Use case

A very common pattern in Ruby, especially in testing is to save the value of an attribute, set a new value, and then restore the old value in an `ensure` clause.

e.g. in unit tests

```ruby
def test_something_when_enabled
  enabled_was, SomeLibrary.enabled = SomeLibrary.enabled, true
  # test things
ensure
  SomeLibrary.enabled = enabled_was
end
```

Or sometime in actual APIs:

```ruby
def with_something_enabled
  enabled_was = @enabled
  @enabled = true
  yield
ensure
  @enabled = enabled_was
end
```

There is no inherent problem with this pattern, but it can be easy to make a mistake, for instance the unit test example:

```ruby
def test_something_when_enabled
  some_call_that_may_raise
  enabled_was, SomeLibrary.enabled = SomeLibrary.enabled, true
  # test things
ensure
  SomeLibrary.enabled = enabled_was
end
```

In the above if `some_call_that_may_raise` actually raises, `SomeLibrary.enabled` is set back to `nil` rather than its original value. I've seen this mistake quite frequently.

Object#with

I think it would be very useful to have a method on Object to implement this pattern in a correct and easy to use way.

NB: `public_send` is used because I don't think such method should be usable if the accessors are private.

With usage:

```ruby
def test_something_when_enabled
  SomeLibrary.with(enabled: true) do
    # test things
  end
end
```

```ruby
GC.with(measure_total_time: true, auto_compact: false) do
  # do something
end
```

Lots of tests in Rails's codebase could be simplified, e.g.:
  - Changing `Thread.report_on_exception`: 2d2fdc941e/activerecord/test/cases/connection_pool_test.rb (L583-L595)
  - Changing a class attribute: 2d2fdc941e/activerecord/test/cases/associations/belongs_to_associations_test.rb (L136-L150)
2023-03-06 09:02:41 +01:00
Niklas Haeusele
f9868208b5 Fixes #47572
Use triple dots in method_missing to pass on arguments
2023-03-03 20:50:47 +01:00
Rafael Mendonça França
7b4affc78b
Remove deprecated support to generate incorrect RFC 4122 UUIDs 2023-03-03 00:38:36 +00:00
Rafael Mendonça França
f02998d2b5
Remove implicit conversion of objects into String by ActiveSupport::SafeBuffer 2023-03-03 00:38:34 +00:00
Rafael Mendonça França
34e296d492
Remove deprecated override of ActiveSupport::TimeWithZone.name 2023-03-03 00:38:31 +00:00
Rafael Mendonça França
e420c3380e
Remove deprecated option to passing a format to #to_s 2023-03-03 00:38:30 +00:00
Rafael Mendonça França
3ec629784c
Remove deprecated override of Enumerable#sum 2023-03-03 00:38:26 +00:00
zzak
67748d0596
Fix ruby:master re: ruby/feature/18285
ruby/ruby#6950

Co-authored-by: Jean byroot Boussier <jean.boussier+github@shopify.com>
2023-02-22 19:40:52 +09:00
Ignacio Galindo
47b0aa05c3 Add Object#in? support for open date ranges
This leverages Range#cover? to properly handle beginless and endless
range inclusion checks.
2023-02-08 18:32:27 +01:00
Ghouse Mohamed
a16877ac7a Fixes rubocop errors 2023-01-17 20:58:53 +00:00
Rafael Mendonça França
e9bc620f78
Make sure Enumerable#sum works with objects that implement #coerce without deprecation
Closes #46779
2023-01-17 20:51:19 +00:00
Akira Matsuda
8b2f57dc6f
Let delegate define method with proper arity when delegating to a Class / Module
Method delegation with `...` argument is known to be slow because it allocates
redundant Array and Hash objects each time when being called.
see: https://bugs.ruby-lang.org/issues/19165

Current implementation of `delegate` defines all delegation methods in this
slow form regardless of the original method's arity, but in case the delegation
target is a Class or a Module, we can investigate the arity of the original
method in the definition timing, then we can define the delegation in proper
minimal arity.

This makes 3.5 times faster zero arity method delegation as follows:
Warming up --------------------------------------
                 old   811.534k i/100ms
                 new     1.807M i/100ms
Calculating -------------------------------------
                 old      9.809M (± 3.4%) i/s -     49.504M in   5.053355s
                 new     34.360M (± 0.8%) i/s -    173.465M in   5.048692s

Comparison:
                 new: 34360408.4 i/s
                 old:  9809157.4 i/s - 3.50x  (± 0.00) slower
2023-01-11 04:32:08 +09:00
Akira Matsuda
c9875d31cc
Make it clear that SB#[]= takes 3 arguments, and reduce Array allocation
this reduces a redundant Array allocation that used to be created by *.
Plus, added some tests for []= with three arguments.
2023-01-06 03:02:02 +09:00
Jonathan Hefner
e6ab2888c8
Merge pull request #46456 from jonathanhefner/follow-up-46330-and-46337
Add missing `assert_not_deprecated` deprecator args
2022-11-10 16:29:48 -06:00
Jonathan Hefner
8a7aba0c76 Add missing assert_not_deprecated deprecator args
Follow-up to #46330 and #46337.

This adds a deprecator arg to some `assert_not_deprecated` calls that
were missed in #46330 and #46337.
2022-11-09 12:07:29 -06:00
fatkodima
d862dffadd Fix Enumerable#many? to handle previous enumerator methods parameters 2022-11-08 20:53:55 +02:00
Jonathan Hefner
587c3406af Add ActiveSupport.deprecator
This commit adds `ActiveSupport.deprecator` and replaces all usages of
`ActiveSupport::Deprecation.warn` in `activesupport/lib` with
`ActiveSupport.deprecator`.

Additionally, this commit adds `ActiveSupport.deprecator` to
`Rails.application.deprecators` so that it can be configured using e.g.
`config.active_support.report_deprecations`.
2022-10-25 15:06:39 -05:00
Jonathan Hefner
b191a65850 Fix Time#change and #advance around the end of DST
Prior to this commit, when `Time#change` or `Time#advance` constructed a
time inside the final stretch of Daylight Saving Time (DST), the non-DST
offset would always be chosen for local times:

  ```ruby
  # 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:

  ```ruby
  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
  ```

This commit fixes `Time#change` and `Time#advance` to choose the offset
that matches the original time's offset when possible:

  ```ruby
  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
  ```

It's worth noting that there is a somewhat dubious case when calling
`advance` with a mix of calendar and clock units (e.g. months + hours).
`advance` adds calendar units first, then adds clock units.  So a
non-DST time may first be advanced to a date within DST before any clock
units are applied.  For example:

  ```ruby
  # DST began on 2021-03-14 in US/Eastern.
  Time.zone = "US/Eastern"

  non_dst = Time.new(2021, 03, 07, 00, 00, 00, Time.zone)
  # => 2021-03-07 00:00:00 -0500

  non_dst.advance(months: 8, hours: 1)
  # => 2021-11-07 01:00:00 -0400
  ```

One could argue that the expected result is `2021-11-07 01:00:00 -0500`.
However, the difference between that and the result for `hours: 0` is
greater than 1 hour:

  ```ruby
  adjusted_result = non_dst.advance(months: 8, hours: 1) + 3600
  # => 2021-11-07 01:00:00 -0500

  adjusted_result - non_dst.advance(months: 8, hours: 0)
  # => 7200.0
  ```

Which might also be unexpected.

Furthermore, it may be difficult (or expensive) to apply such an
adjustment in a consistent way.  For example, the result for `hours: 2`
does have the expected `-0500` offset, so it might seem no adjustment is
necessary, but if we didn't adjust it too, it would conflict with the
adjusted `hours: 1` result:

  ```ruby
  non_dst.advance(months: 8, hours: 2)
  # => 2021-11-07 01:00:00 -0500
  ```

Therefore, the approach in this commit (which produces a `-0400` offset
for `hours: 1`) seems like a reasonable compromise.

Fixes #45055.
Closes #45556.
Closes #46248.

Co-authored-by: Kevin Hall <bigtoe416@yahoo.com>
Co-authored-by: Takayoshi Nishida <takayoshi.nishida@gmail.com>
2022-10-22 14:58:03 -05:00
Aaron Patterson
a7238cbfa4
rubocop 2022-10-09 15:54:42 -07:00
Aaron Patterson
1d39573a9f
Move ERB parsing to core_ext 2022-10-09 14:52:17 -07:00
Jean Boussier
1aa24639f7 Filter reloaded classes in Class#subclasses and Class#descendants core exts
When calling `#descendants` on a non-reloadable class with reloadable
descendants, it can return classes that were unloaded but not yet
garbage collected.

`DescendantsTracker` have been dealing with this for a long time
but the core_ext versions of these methods were never made reloader
aware.

This also refactor `DescendantsTracker` to not be so different when
there is no native `#subclasses` method.
2022-09-28 12:08:58 +02:00
John Bampton
3a32915bbc Fix word case. json -> JSON 2022-09-17 04:11:36 +10:00
Yasuo Honda
349a66ebed Drop Rubinius code
Rubinius has not been maintained since May 2020 and based on the
discussion at https://github.com/rails/rails/pull/44984 ,
I think we can remove Rubinius specific code from Rails.
2022-09-15 23:43:51 +09:00
Mark Schneider
69b550fc88 Add String#downcase_first method
Rails 5 added String#upcase_first, which converts the first letter of a
string to uppercase (returning a duplicate).  This commit adds the
corollary method, converting the first letter to lowercase.
2022-09-08 12:57:31 -04:00
Jonathan Hefner
4ab4144d26
Merge pull request #45918 from jonathanhefner/thread_mattr_accessor-default-require-frozen
Freeze `thread_mattr_accessor` default values
2022-09-01 16:03:18 -05:00
Jonathan Hefner
38a2cfe9fe Freeze thread_mattr_accessor default values
This provides a basic level of protection against different threads
trying to mutate a shared default object.  It is not a bulletproof
solution, because the default may contain nested non-frozen objects, but
it should cover common cases.
2022-09-01 15:41:32 -05:00
Jonathan Hefner
410c6144c6 Support thread_mattr_accessor in anonymous classes
This allows `thread_mattr_accessor` to be used with anonymous classes
when e.g. testing.
2022-09-01 14:37:23 -05:00
Thierry Deo
25faa5466b Fix thread_mattr_accessor default option behavior
This makes the value supplied to the `default` option of
`thread_mattr_accessor` to be set in descendant classes
as well as in any new Thread that starts.

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.

For instance:

  ```ruby
  class Processor
    thread_mattr_accessor :mode, default: :smart
  end

  class SubProcessor < Processor
  end

  SubProcessor.mode # => :smart (was `nil` prior to this commit)

  Thread.new do
    Processor.mode # => :smart (was `nil` prior to this commit)
  end.join
  ```

If a non-`nil` default has been specified, there is a small (~7%)
performance decrease when reading non-`nil` values, and a larger (~45%)
performance decrease when reading `nil` values.

Benchmark script:

  ```ruby
  # frozen_string_literal: true
  require "benchmark/ips"
  require "active_support"
  require "active_support/core_ext/module/attribute_accessors_per_thread"

  class MyClass
    thread_mattr_accessor :default_value, default: "default"
    thread_mattr_accessor :string_value, default: "default"
    thread_mattr_accessor :nil_value, default: "default"
  end

  MyClass.string_value = "string"
  MyClass.nil_value = nil

  Benchmark.ips do |x|
    x.report("default_value") { MyClass.default_value }
    x.report("string_value") { MyClass.string_value }
    x.report("nil_value") { MyClass.nil_value }
  end
  ```

Before this commit:

  ```
         default_value      2.075M (± 0.7%) i/s -     10.396M in   5.010585s
          string_value      2.103M (± 0.7%) i/s -     10.672M in   5.074624s
             nil_value      1.777M (± 0.9%) i/s -      8.924M in   5.023058s
  ```

After this commit:

  ```
         default_value      2.008M (± 0.7%) i/s -     10.187M in   5.072990s
          string_value      1.967M (± 0.7%) i/s -      9.891M in   5.028570s
             nil_value      1.144M (± 0.5%) i/s -      5.770M in   5.041630s
  ```

If no default or a `nil` default is specified, there is no performance
impact.

Fixes #43312.

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2022-08-25 11:30:58 -05:00
Ian C. Anderson
d5695001f1 xml_name_escape: Optimize the common case
This came out of a conversation I had with @jhawthorn about how we could further
optimize the performance of `xml_name_escape`, which is a hot path for view
rendering.

This adds an early return to the method that improves the "valid name" case
performance by 2-3x, without adding any measurable overhead to the "invalid
case" (according to the benchmark below).

This also updates the constant names to reflect the fact that the regular
expressions are matching characters that are _not_ valid.

Benchmark results:

```
============================ Common tag name short =============================

Warming up --------------------------------------
     xml_name_escape   159.671k i/100ms
fast_xml_name_escape   343.621k i/100ms
one_regex_xml_name_escape
                       353.869k i/100ms
Calculating -------------------------------------
     xml_name_escape      1.582M (± 3.8%) i/s -      7.984M in   5.055645s
fast_xml_name_escape      3.341M (± 4.7%) i/s -     16.837M in   5.051945s
one_regex_xml_name_escape
                          3.489M (± 4.9%) i/s -     17.693M in   5.085095s

Comparison:
one_regex_xml_name_escape:  3488934.6 i/s
fast_xml_name_escape:  3341149.3 i/s - same-ish: difference falls within error
     xml_name_escape:  1581604.8 i/s - 2.21x  (± 0.00) slower

============================= Common tag name long =============================

Warming up --------------------------------------
     xml_name_escape    76.117k i/100ms
fast_xml_name_escape   266.879k i/100ms
one_regex_xml_name_escape
                       257.459k i/100ms
Calculating -------------------------------------
     xml_name_escape    826.616k (± 4.3%) i/s -      4.186M in   5.074708s
fast_xml_name_escape      2.751M (± 5.0%) i/s -     13.878M in   5.060281s
one_regex_xml_name_escape
                          2.545M (± 5.6%) i/s -     12.873M in   5.077729s

Comparison:
fast_xml_name_escape:  2751129.4 i/s
one_regex_xml_name_escape:  2544673.8 i/s - same-ish: difference falls within error
     xml_name_escape:   826616.2 i/s - 3.33x  (± 0.00) slower

=============================== Custom tag name ================================

Warming up --------------------------------------
     xml_name_escape    78.065k i/100ms
fast_xml_name_escape   242.412k i/100ms
one_regex_xml_name_escape
                       231.727k i/100ms
Calculating -------------------------------------
     xml_name_escape    767.433k (± 6.5%) i/s -      3.825M in   5.012273s
fast_xml_name_escape      2.463M (± 4.3%) i/s -     12.363M in   5.030648s
one_regex_xml_name_escape
                          2.239M (± 6.5%) i/s -     11.355M in   5.095769s

Comparison:
fast_xml_name_escape:  2462694.6 i/s
one_regex_xml_name_escape:  2238947.7 i/s - same-ish: difference falls within error
     xml_name_escape:   767432.9 i/s - 3.21x  (± 0.00) slower

========================== Custom tag name non-ascii ===========================

Warming up --------------------------------------
     xml_name_escape    66.959k i/100ms
fast_xml_name_escape    63.131k i/100ms
one_regex_xml_name_escape
                       206.018k i/100ms
Calculating -------------------------------------
     xml_name_escape    686.496k (± 4.9%) i/s -      3.482M in   5.085224s
fast_xml_name_escape    643.266k (± 4.5%) i/s -      3.220M in   5.016957s
one_regex_xml_name_escape
                          2.010M (± 4.8%) i/s -     10.095M in   5.034582s

Comparison:
one_regex_xml_name_escape:  2010415.6 i/s
     xml_name_escape:   686496.1 i/s - 2.93x  (± 0.00) slower
fast_xml_name_escape:   643266.0 i/s - 3.13x  (± 0.00) slower

================================ Bad tag name 1 ================================

Warming up --------------------------------------
     xml_name_escape    40.491k i/100ms
fast_xml_name_escape    40.465k i/100ms
one_regex_xml_name_escape
                        38.244k i/100ms
Calculating -------------------------------------
     xml_name_escape    393.998k (± 6.7%) i/s -      1.984M in   5.062913s
fast_xml_name_escape    386.906k (± 5.2%) i/s -      1.942M in   5.035445s
one_regex_xml_name_escape
                        377.664k (± 6.6%) i/s -      1.912M in   5.088602s

Comparison:
     xml_name_escape:   393998.2 i/s
fast_xml_name_escape:   386906.4 i/s - same-ish: difference falls within error
one_regex_xml_name_escape:   377663.7 i/s - same-ish: difference falls within error

================================ Bad tag name 2 ================================

Warming up --------------------------------------
     xml_name_escape    15.627k i/100ms
fast_xml_name_escape    15.165k i/100ms
one_regex_xml_name_escape
                        16.028k i/100ms
Calculating -------------------------------------
     xml_name_escape    161.988k (± 5.5%) i/s -    812.604k in   5.032083s
fast_xml_name_escape    161.438k (± 5.7%) i/s -    818.910k in   5.090467s
one_regex_xml_name_escape
                        160.224k (± 5.1%) i/s -    801.400k in   5.016219s

Comparison:
     xml_name_escape:   161987.9 i/s
fast_xml_name_escape:   161437.6 i/s - same-ish: difference falls within error
one_regex_xml_name_escape:   160224.2 i/s - same-ish: difference falls within error
```

Benchmark code:

```ruby

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "rails", github: "rails/rails", branch: "main"
  gem "benchmark-ips"
end

require "active_support"
require "active_support/core_ext/string/output_safety"

class ERB
  module Util
    TAG_NAME_COMMON_CASE = /\A[a-z][a-z\-]*\z/

    def fast_xml_name_escape(name)
      name = name.to_s
      return "" if name.blank?
      return name if name.match?(TAG_NAME_COMMON_CASE)

      starting_char = name[0]
      starting_char.gsub!(TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR)

      return starting_char if name.size == 1

      following_chars = name[1..-1]
      following_chars.gsub!(TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR)

      starting_char << following_chars
    end
    module_function :fast_xml_name_escape

    TAG_NAME_FOLLOWING_REGEXP_SET = "#{TAG_NAME_START_REGEXP_SET}\-.0-9\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}"
    SAFE_XML_TAG_NAME_REGEXP = /\A[#{TAG_NAME_START_REGEXP_SET}][#{TAG_NAME_FOLLOWING_REGEXP_SET}]*\z/

    def one_regex_xml_name_escape(name)
      name = name.to_s
      return "" if name.blank?
      return name if name.match?(SAFE_XML_TAG_NAME_REGEXP)

      starting_char = name[0]
      starting_char.gsub!(TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR)

      return starting_char if name.size == 1

      following_chars = name[1..-1]
      following_chars.gsub!(TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR)

      starting_char << following_chars
    end
    module_function :one_regex_xml_name_escape
  end
end

SCENARIOS = {
  "Common tag name short" => "p",
  "Common tag name long"  => "textarea",
  "Custom tag name"       => "super-custom",
  "Custom tag name non-ascii" => "süper-custom",
  "Bad tag name 1"        => "1abc",
  "Bad tag name 2"        => "1 < 2 & 3",
}

SCENARIOS.each_pair do |name, value|
  puts
  puts " #{name} ".center(80, "=")
  puts

  Benchmark.ips do |x|
    x.report("xml_name_escape")      { ERB::Util.xml_name_escape(value) }
    x.report("fast_xml_name_escape") { ERB::Util.fast_xml_name_escape(value) }
    x.report("one_regex_xml_name_escape") { ERB::Util.one_regex_xml_name_escape(value) }
    x.compare!
  end
end
```
2022-08-18 20:21:56 +00:00
matt swanson
959d46ef87
Add quarter method to date/time (#45009)
Co-authored-by: David Heinemeier Hansson <david@hey.com>
2022-07-14 16:43:52 -07:00
Gannon McGibbon
90c0bde47c Rename behaviour to behavior in test case names 2022-05-26 17:14:18 -04:00
Alvaro Martin Fraguas
649516ce0f
Fix and add protections for XSS in names.
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.

Use that method in the tag helpers of ActionView::Helpers. Rename the option
:escape_attributes to :escape, to simplify by applying the option to the whole
tag.
2022-04-26 12:34:42 -07:00
Gannon McGibbon
8d791726e1 Fix style in test/core_ext/enumerable_test.rb 2022-04-06 13:21:49 -04:00
Jean Boussier
94884da8f8 Handle renaming of global_constant_state in Ruby 3.2
Ref: https://github.com/ruby/ruby/pull/5766
2022-04-06 09:22:00 +02:00
John Bampton
2d55c05c37 Fix case of YAML 2022-03-29 16:04:19 +10:00
Donatas Povilaitis
49fa92bb32 Fix Range#overlaps? for beginless ranges
- `#first` raises an error when called on a beginless range.
  Using `#begin` to get the first element instead.
- Adding additional equality condition to cover the case when both
  ranges are beginless
2022-03-23 22:40:24 +02:00
Andrew White
1943962a10
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.
2022-03-20 10:07:59 +00:00
Kaíque Kandy Koga
d78f266d19 Use duck_string instead of string 2022-03-18 20:28:33 -03:00
Ghouse Mohamed
5fa817241d Extends test cases for Object in activesupport 2022-03-18 15:34:04 +05:30
Jean Boussier
25396b1c2a Avoid adding constants to Enumerable
Ref: https://github.com/aws/aws-sdk-ruby/pull/2670

Some gems like aws-sdk-core use `Object#extend(Enumerable)`.
It's not a very good pattern, but it's somehwat handled ok by Ruby.

However if Enumerable has constants, then any time the module is
extended, the global constant cache is flushed and this has a very
negative impact on performance for the virtual machine, and even
worse for JITs.
2022-03-04 13:33:17 +01:00
Jean Boussier
0ac4c04143 Pathname.blank? only returns true for Pathname.new("")
Fix: https://github.com/rails/rails/issues/44452

We don't ignore blank path strings because as surprising as it is, they
are valid paths:

```ruby
>> path = Pathname.new(" ")
=> #<Pathname: >
>> path.write("test")
=> 4
>> path.exist?
=> true
```

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.
2022-02-19 09:54:58 +01:00
Nikita Vasilevsky
4219696649 [Active Support] Add explicit assertions to tests with no assertions 2022-02-15 23:44:25 +00:00
Rafael Mendonça França
0dfcd54052
Keep to_formatted_s working as before and add tests for it 2022-02-08 16:22:35 +00:00