Commit Graph

79365 Commits

Author SHA1 Message Date
fatkodima d13937bab5 Handle nil key for MemCacheStore#normalize_key 2021-02-09 00:56:23 +02:00
Rafael França 8db3fefac0
Merge pull request #41370 from kamipo/serialized_attribute_on_alias_attribute
Allow `serialize` attribute on `alias_attribute`
2021-02-08 15:08:54 -05:00
Vipul A M d9b286bf8a
Merge pull request #40441 from olivierlacan/doc/update-has-secure-password
Update outdated has_secure_password documentation [ci skip]
2021-02-09 01:34:12 +05:30
Rafael França d1416362e6
Merge pull request #41325 from damiann/damiann/autoload_grammar_fix
Fixing grammar in autoloading_and_reloading_constants [ci-skip]
2021-02-08 14:36:23 -05:00
Rafael França b06ea940be
Merge pull request #41374 from f6p/not-significant-significant
not significant significant method
2021-02-08 14:36:10 -05:00
Rafael França 3f435fb9fa
Merge pull request #41363 from ricardotk002/use-enumerator-all-with-classes
Use Enumerator#all? and Enumerator#any? with classes instead of iterations
2021-02-08 14:35:20 -05:00
Eileen M. Uchitelle d75c2a1752
Merge pull request #40037 from Shopify/ar-adapter-async-query
Allow Adapter#select_all to be performed asynchronously from a background thread pool
2021-02-08 14:06:00 -05:00
Rafael França c8acff842c
Merge pull request #41350 from rails/rm-advisory-lock
Add ActiveRecord::Base.connection.with_advisory_lock
2021-02-08 13:22:02 -05:00
Jean Boussier 7fc174aada Allow Adapter#select_all to be performed asynchronously from a background thread pool
Sometimes a controller or a job has to perform multiple independent queries, e.g.:

```
def index
  @posts = Post.published
  @categories = Category.active
end
```

Since these two queries are totally independent, ideally you could
execute them in parallel, so that assuming that each take 50ms, the
total query time would be 50ms rather than 100ms.

A very naive way to do this is to simply call `Relation#to_a` in a
background thread, the problem is that most Rails applications, and
even Rails itself rely on thread local state (`PerThreadRegistry`,
`CurrentAttributes`, etc). So executing such a high level interface
from another thread is likely to lead to many context loss problems
or even thread safety issues.

What we can do instead, is to schedule a much lower level operation
(`Adapter#select_all`) in a thread pool, and return a future/promise.
This way we kepp most of the risky code on the main thread, but perform
the slow IO in background, with very little chance of executing some
code that rely on state stored in thread local storage.

Also since most users are on MRI, only the IO can really be parallelized,
so scheduling more code to be executed in background wouldn't lead
to better performance.
2021-02-08 19:17:52 +01:00
Rafael Mendonça França 1ab4dbf8aa
Add ActiveRecord::Base.connection.with_advisory_lock 2021-02-08 17:59:18 +00:00
Filip Pyda e308213c80 significant method is not significant anymore 2021-02-08 18:21:28 +01:00
Ryuta Kamizono 66ec42946c Allow `build` multiple records even on non association relation
Follow up to #41342.

The reason why the problem of #41342 occurred is that unlike `create`,
`build` did not support the creation of multiple records, so it did not
address the problem.

It is weird that `post.commnets.where(foo: "bar").build([obj1, obj2])`
is allowed but `Comment.where(foo: "bar").build([obj1, obj2])` is not
allowed.

To avoid the confusion, it allows `build` multiple records even on non
association relation.
2021-02-08 21:48:27 +09:00
Ryuta Kamizono 86fdb54da1 Allow `serialize` attribute on `alias_attribute`
Related to #25998.
2021-02-08 20:47:19 +09:00
Ryuta Kamizono 6515d6985d Use `bind_call(obj, ...)` instead of `bind(obj).call(...)`
`bind_call(obj, ...)` is a faster alternative to `bind(obj).call(...)`.

https://bugs.ruby-lang.org/issues/15955

Also, enable `Performance/BindCall` cop to detect those in the future.
2021-02-08 17:01:23 +09:00
Ryuta Kamizono 25af5e9ff8
Merge pull request #41369 from aweglteo/remove-check-defined-bind_call
Remove check for UnboundMethod#method_defined? bind_call
2021-02-08 16:47:53 +09:00
aweglteo 74b16dfe4f Remove check for UnboundMethod#method_defined? bind_call
Rails 7.0 requires Ruby 2.7+ now so these checks should't be needed.
2021-02-08 16:12:17 +09:00
Vipul A M b1f1879a50
Merge pull request #40995 from garrettdimon/patch-1
Add note for ActionText models that use UUID's [ci skip]
2021-02-08 12:03:28 +05:30
Ryuta Kamizono 18aec64934
Merge pull request #41365 from ricardotk002/deprecate-range-cover
Use native Range#cover? which accepts a Range argument since Ruby 2.6
2021-02-08 12:46:10 +09:00
Ricardo Díaz 6af2355203 Use native Range#cover? which accepts Range arguments since Ruby 2.6
Commit: 9ca7389272
Discussion: https://bugs.ruby-lang.org/issues/14473

It seems to be compatible with the original ActiveSupport's
implementation, at least based on the test suite.

It also works faster:

```
Warming up --------------------------------------
 Ruby's Range#cover?     1.196M i/100ms
ActiveSupport's Range#cover?
                       396.369k i/100ms
Calculating -------------------------------------
 Ruby's Range#cover?     11.889M (± 1.7%) i/s -     59.820M in   5.033066s
ActiveSupport's Range#cover?
                          3.951M (± 1.2%) i/s -     19.818M in   5.017176s

Comparison:
 Ruby's Range#cover?: 11888979.3 i/s
ActiveSupport's Range#cover?:  3950671.0 i/s - 3.01x  (± 0.00) slower
```

Benchmark script:

```ruby
require "minitest/autorun"
require "benchmark/ips"

module ActiveSupportRange
  def active_support_cover?(value)
    if value.is_a?(::Range)
      is_backwards_op = value.exclude_end? ? :>= : :>
      return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
      # 1...10 covers 1..9 but it does not cover 1..10.
      # 1..10 covers 1...11 but it does not cover 1...12.
      operator = exclude_end? && !value.exclude_end? ? :< : :<=
      value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
      cover?(value.first) && (self.end.nil? || value_max.public_send(operator, last))
    else
      cover?
    end
  end
end

class BugTest < Minitest::Test
  def test_range_cover
    Range.prepend(ActiveSupportRange)

    range = (1..10000)

    Benchmark.ips do |x|
      x.report("Ruby's Range#cover?") do
        range.cover?((100..20))
      end

      x.report("ActiveSupport's Range#cover?") do
        range.active_support_cover?((100..20))
      end

      x.compare!
    end
  end
end
```
2021-02-07 22:21:17 -05:00
Ryuta Kamizono 493d357b83
Merge pull request #41357 from andrehjr/dedup-redundant-frozen-check
Remove redundant check for frozen keys on deep dup
2021-02-08 12:10:44 +09:00
Ryuta Kamizono 507c1895a4
Merge pull request #41366 from ricardotk002/remove-ruby-2-5-code
Remove checks for Module#method_defined? arity
2021-02-08 11:54:12 +09:00
Ryuta Kamizono 14e5ef9609
Merge pull request #41367 from andrehjr/remove-symbol-start-end-with
Removes Symbol#start_with? and Symbol#end_with? since they are defined in Ruby 2.7
2021-02-08 11:51:04 +09:00
André Luis Leal Cardoso Junior ce01aafb82 Removes Symbol#start_with? and Symbol#end_with? since they are defined in Ruby 2.7
This commit just removes the implementation of those methods and leaves the aliases for `starts_with` and `ends_with?`.
2021-02-07 21:47:25 -03:00
Ricardo Díaz 0ba14c7430 Remove checks for Module#method_defined? arity
The method signature has changed in Ruby 2.6:

https://bugs.ruby-lang.org/issues/14944

Rails 7.0 requires Ruby 2.7+ now and these checks/monkey patches
shouldn't be needed.
2021-02-07 19:30:43 -05:00
Ryuta Kamizono a33334ada1
Merge pull request #41359 from andrehjr/remove-2-6-ruby-code
Removing Ruby 2.6 monkeypatch from active_support/core_ext/uri
2021-02-08 03:46:07 +09:00
André Luis Leal Cardoso Junior 52363d9586 Removing monkeypatched `URI#unescape` since main branch follows ruby 2.7 2021-02-07 08:20:17 -03:00
Ricardo Díaz 93cbc30f34 Use Enumerator#all? and Enumerator#any? with classes instead of iterations
These methods have changed in Ruby 2.5 to be more akin to grep:

https://bugs.ruby-lang.org/issues/11286

Using classes seems to be faster (and a bit more expressive) than iterating over
the collection items:

```
Warming up --------------------------------------
    #all? with class   504.000  i/100ms
     #all? with proc   189.000  i/100ms
Calculating -------------------------------------
    #all? with class      4.960k (± 1.6%) i/s -     25.200k in   5.082049s
     #all? with proc      1.874k (± 2.8%) i/s -      9.450k in   5.047866s

Comparison:
    #all? with class:     4959.9 i/s
     #all? with proc:     1873.8 i/s - 2.65x  (± 0.00) slower
```

Benchmark script:

```ruby
require "minitest/autorun"
require "benchmark/ips"

class BugTest < Minitest::Test
  def test_enumerators_with_classes
    arr = (1..10000).to_a << nil

    assert_equal arr.all?(Integer), arr.all? { |v| v.is_a?(Integer) }

    Benchmark.ips do |x|
      x.report("#all? with class") do
        arr.all?(Integer)
      end

      x.report("#all? with proc") do
        arr.all? { |v| v.is_a?(Integer) }
      end

      x.compare!
    end
  end
end
```
2021-02-07 01:29:50 -05:00
Ryuta Kamizono 39e49edaf9 Remove the code for older Rubies `RUBY_VERSION < "2.7"` in the codebase 2021-02-07 12:20:18 +09:00
Ryuta Kamizono f9cc3c8b1c Use arguments forwarding in the delegate code generation 2021-02-07 12:08:16 +09:00
Ryuta Kamizono 978308ac87 Fix markup in CHANGELOGs [ci skip] 2021-02-07 05:45:53 +09:00
Ryuta Kamizono f8b354bf3b Fix typo s/adapaters/adapters/ [ci skip] 2021-02-07 05:41:07 +09:00
Vipul A M 99c1112b42
Some grammar passes around guides [ci skip] (#41358) 2021-02-07 00:42:51 +05:30
Vipul A M d6d3fe6fa0
Merge pull request #40724 from clayton-shopify/fix-user-cookie-with-metadata-docs
Fix the documentation for use_cookies_with_metadata
2021-02-07 00:03:02 +05:30
André Luis Leal Cardoso Junior 96c52a9d3c Remove redundant check for frozen keys on deep dup
On Ruby 2.7+ all keys are frozen, so no need for the extra check. It seems slightly faster.

```ruby

require "bundler/inline"

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

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

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

require 'active_support/core_ext/object/deep_dup'

class Hash
  def deep_dup_skip_frozen_check
    hash = dup
    each_pair do |key, value|
      if ::String === key || ::Symbol === key
        hash[key] = value.deep_dup
      else
        hash.delete(key)
        hash[key.deep_dup] = value.deep_dup
      end
    end
    hash
  end
end

data_symbols = Hash[('aaa'..'zzz').map {|k| [k.to_sym, k]}]
data_strings = Hash[('aaa'..'zzz').map {|k| [k, k]}]

Benchmark.ips do |x|
  x.report("data_symbols.deep_dup")                  { data_symbols.deep_dup  }
  x.report("data_symbols.deep_dup_skip_frozen_check") { data_symbols.deep_dup_skip_frozen_check }
  x.compare!
end

Benchmark.ips do |x|
  x.report("data_strings.deep_dup")                  { data_strings.deep_dup  }
  x.report("data_strings.deep_dup_skip_frozen_check") { data_strings.deep_dup_skip_frozen_check }
  x.compare!
end

```

Result:

```
Warming up --------------------------------------
data_symbols.deep_dup
                        17.000  i/100ms
data_symbols.deep_dup_skip_frozen_check
                        18.000  i/100ms
Calculating -------------------------------------
data_symbols.deep_dup
                        177.807  (±12.4%) i/s -    884.000  in   5.067841s
data_symbols.deep_dup_skip_frozen_check
                        192.254  (± 3.1%) i/s -    972.000  in   5.060775s

Comparison:
data_symbols.deep_dup_skip_frozen_check:      192.3 i/s
data_symbols.deep_dup:      177.8 i/s - same-ish: difference falls within error

Warming up --------------------------------------
data_strings.deep_dup
                        18.000  i/100ms
data_strings.deep_dup_skip_frozen_check
                        19.000  i/100ms
Calculating -------------------------------------
data_strings.deep_dup
                        184.347  (± 2.7%) i/s -    936.000  in   5.081570s
data_strings.deep_dup_skip_frozen_check
                        197.728  (± 2.0%) i/s -      1.007k in   5.095122s

Comparison:
data_strings.deep_dup_skip_frozen_check:      197.7 i/s
data_strings.deep_dup:      184.3 i/s - 1.07x  (± 0.00) slower
```

Co-authored-by: Daniel Pepper <pepper.daniel@gmail.com>
2021-02-06 14:28:57 -03:00
Ryuta Kamizono 46fdd809d9
Merge pull request #41354 from andrehjr/remove-extra-require-on-associations
Remove unused requires on lib/active_record/associations.rb
2021-02-07 01:08:56 +09:00
André Luis Leal Cardoso Junior 07392f50d4 Remove unused requires on lib/active_record/associations.rb
"active_support/core_ext/string/conversions" was added on 3f1cdb85b8 for `constantize`.

Also, "active_support/core_ext/string/conversions" does not define `constantize` anymore.

"active_support/core_ext/enumerable" was added on ea290e77e6 for `index_by`.

Moved the require to 'lib/active_record/associations/collection_association.rb' where it's still used

Both usages of `index_by` and `constantize` at this file were removed at 52f8e4b9da (diff-7c2226b7a4aa7f86f7d9e5e16b10686056c02efc725a60e378b5f9d7e52e8403)
2021-02-06 12:54:22 -03:00
Rafael França 2828d6b955
Merge pull request #41191 from djmortonShopify/handle_block_on_perform_later
Communicate enqueue failures to callers of perform_later
2021-02-05 17:23:20 -05:00
eileencodes 1aa8190c66
Set `ApplicationRecord` to `primary_abstract_class`
Followup on https://github.com/rails/rails/pull/41258#discussion_r570441592

This makes sure that newly generated applications get their
`ApplicationRecord` set to `primary_abstract_class`. Existing applications
can opt-in to this if they're using multiple databases or have changed
their `ApplicationRecord` to a class with a different name.

Co-authored-by: John Crepezzi <john.crepezzi@gmail.com>
2021-02-05 17:02:08 -05:00
Rafael França 7f2d44f019
Merge pull request #41347 from ricardotk002/use-string-grapheme-clusters
Use String#grapheme_clusters instead of String#scan
2021-02-05 16:58:59 -05:00
Ricardo Díaz 95f8bfea79 Fix examples for ActiveSupport::Multibyte::Chars methods [ci skip]
They show the wrong return values. These were recalculated in Ruby
2.7.1 and Rails 7.0.0.alpha.
2021-02-05 16:45:29 -05:00
Daniel Morton ee60ce5606 Communicate enqueue failures to callers of perform_later
There is presently no clean way of telling a caller of `perform_later`
the reason why a job failed to enqueue. When the job is enqueued
successfully, the job object itself is returned, but when the job can
not be enqueued, only `false` is returned. This does not allow callers
to distinguish between classes of failures.

One important class of failures is when the job backend experiences a
network partition when communicating with its underlying datastore. It
is entirely possible for that network partition to recover and as such,
code attempting to enqueue a job may wish to take action to reenqueue
that job after a brief delay. This is distinguished from the class of
failures where due a business rule defined in a callback in the
application, a job fails to enqueue and should not be retried.

This PR changes the following:

- Allows a block to be passed to the `perform_later` method. After the
  `enqueue` method is executed, but before the result is returned, the
  job will be yielded to the block. This allows the code invoking the
  `perform_later` method to inspect the job object, even in failure
  scenarios.

- Adds an exception `EnqueueError` which job adapters can raise if they
  detect a problem specific to their underlying implementation or
  infrastructure during the enqueue process.

- Adds two properties to the job base class: `successfully_enqueued` and
  `enqueue_error`. `enqueue_error` will be populated by the `enqueue`
  method if it rescues an `EnqueueError` raised by the job backend.
  `successfully_enqueued` will be true if the job is not rejected by
  callbacks and does not cause the job backend to raise an
  `EnqueueError` and will be `false` otherwise.

This will allow developers to do something like the following:

    MyJob.perform_later do |job|
      unless job.successfully_enqueued?
        if job.enqueue_error&.message == "Redis was unavailable"
          # invoke some code that will retry the job after a delay
        end
      end
    end
2021-02-05 16:32:43 -05:00
Gannon McGibbon c8a86d361c
Merge pull request #41339 from gmcgibbon/break_up_abstract_connection_pool
Break up abstract connection pool
2021-02-05 16:01:48 -05:00
Rafael França abff811725
Merge pull request #40254 from prateekkish/default-main
Change default branch for new Rails projects and plugins to main
2021-02-05 15:23:40 -05:00
Ricardo Díaz 8d0ca1a141 Use String#grapheme_clusters and String#each_grapheme_cluster
Both methods were introduced in Ruby 2.5 and are faster than scanning
unicode graphemes with String#scan

```
Warming up --------------------------------------
           scan(/X/)    43.127k i/100ms
   grapheme_clusters   103.348k i/100ms
Calculating -------------------------------------
           scan(/X/)    427.853k (± 2.4%) i/s -      2.156M in   5.042967s
   grapheme_clusters      1.045M (± 0.8%) i/s -      5.271M in   5.042360s

Comparison:
   grapheme_clusters:  1045353.5 i/s
           scan(/X/):   427852.8 i/s - 2.44x  (± 0.00) slower
```

Benchmark script:

```ruby
require "minitest/autorun"
require "benchmark/ips"

class BugTest < Minitest::Test
  def test_grapheme_clusters
    string = [0x0924, 0x094D, 0x0930].pack("U*") # "त्र"
    # string = [0x000D, 0x000A].pack("U*") # cr lf
    # string = "こにちわ"

    assert string.scan(/\X/) == string.grapheme_clusters

    Benchmark.ips do |x|
      x.report("scan(/\X/)") do
        string.scan(/\X/)
      end

      x.report("grapheme_clusters") do
        string.grapheme_clusters
      end

      x.compare!
    end
  end
end
```

String#grapheme_clusters had a bug with CRLF which was fixed in Ruby
2.6: https://bugs.ruby-lang.org/issues/15337

Now that Rails requires Ruby 2.7+, it shouldn't be an issue.
2021-02-05 13:29:56 -05:00
Gannon McGibbon 7ae35f02e2 Move ActiveRecord::ConnectionAdapters::ConnectionPool::Repaer to separate file 2021-02-05 12:20:05 -05:00
Rafael França d7ff7646c1
Merge pull request #41343 from lordon/remove-parts-of-js-confirm-guide
Remove confusing part of JavaScript guide regarding confirmations [ci skip]
2021-02-05 12:09:24 -05:00
David Heinemeier Hansson 9cb09411e1
Enumerable#in_order_of (#41333)
* Add Enumerable#in_order_of

* Explain behavior further

* Use Enumerable#in_order_of

* Use Ruby 2.7 #filter_map

* Update activesupport/lib/active_support/core_ext/enumerable.rb

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

* No need for explaining variable

* Add CHANGELOG entry

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2021-02-05 17:28:50 +01:00
Rafael França 9e8824036d
Merge pull request #41340 from kamipo/remove_version_check_in_tests
Remove all version checking for older Rubies in tests
2021-02-05 11:22:55 -05:00
Ryuta Kamizono 0f43f55be6
Merge pull request #41342 from kamipo/fix_build_on_association_relation
Fix `build` multiple records on association relation to not lose scope values
2021-02-05 18:59:02 +09:00
Elias Saalmann 4ed3411ba8 Remove confirmations part of JavaScript guide since it causes confusion 2021-02-05 10:22:12 +01:00