This commit addresses CI failure of Active Record isolation tests.
https://buildkite.com/rails/rails/builds/79936
Follow up #41392
* Steps to reproduce
```ruby
$ cd activerecord
$ bin/test test/cases/associations/belongs_to_associations_test.rb test/cases/associations/has_many_associations_test.rb test/cases/associations/has_many_through_disable_joins_associations_test.rb test/cases/associations/has_one_associations_test.rb test/cases/connection_adapters/schema_cache_test.rb test/cases/inheritance_test.rb test/cases/migration_test.rb test/cases/store_test.rb test/cases/strict_loading_test.rb
```
Since the entire output is too long, here is the minimum case fixed by
this commit.
```ruby
$ cd activerecord
$ bin/test test/cases/associations/belongs_to_associations_test.rb:38
Using sqlite3
Run options: --seed 34180
E
Error:
BelongsToAssociationsTest#test_belongs_to:
NameError: Rails couldn't find a valid model for Club association. Please provide the :class_name option on the association declaration. If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:431:in `rescue in compute_class'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:422:in `compute_class'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:372:in `klass'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:722:in `association_primary_key'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/reflection.rb:727:in `join_primary_key'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_row.rb:150:in `block in resolve_sti_reflections'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_row.rb:138:in `each_value'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_row.rb:138:in `resolve_sti_reflections'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_row.rb:92:in `fill_row_model_attributes'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_row.rb:70:in `initialize'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_rows.rb:36:in `new'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_rows.rb:36:in `block in build_table_rows_from'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_rows.rb:35:in `each'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_rows.rb:35:in `map'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_rows.rb:35:in `build_table_rows_from'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixture_set/table_rows.rb:18:in `initialize'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:692:in `new'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:692:in `table_rows'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:633:in `block (2 levels) in insert'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:632:in `each'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:632:in `block in insert'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:629:in `each'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:629:in `insert'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:615:in `read_and_insert'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/fixtures.rb:567:in `create_fixtures'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/test_fixtures.rb:268:in `load_fixtures'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/test_fixtures.rb:122:in `setup_fixtures'
/home/yahonda/src/github.com/rails/rails/activerecord/lib/active_record/test_fixtures.rb:10:in `before_setup'
bin/test test/cases/associations/belongs_to_associations_test.rb:38
Finished in 0.083668s, 11.9520 runs/s, 0.0000 assertions/s.
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
$
```
This leaves Ripper tracker as an optional view dependency tracker, but uses the current ERBTracker by default.
Eventually the default can change to the Ripper tracker, but this makes it an optional update for now
When an engine's migration is installed in a rails application, a
comment is inserted after any magic comments indicating the migration's
source. However, the current implementation does not take into
account whether there is an empty line after magic comments, and the
generated migration will not pass rubocop's
Layout/EmptyLineAfterMagicComment even if the engine's migration did.
This commit changes the implementation to insert the new comment after
a newline occuring after magic comments, if it exists.
Example Engine Migration:
```ruby
# frozen_string_literal: true
# coding: ISO-8859-15
class CurrenciesHaveSymbols < ActiveRecord::Migration::Current
end
```
Before change:
```ruby
# frozen_string_literal: true
# coding: ISO-8859-15
# This migration comes from bukkits (originally 1)
class CurrenciesHaveSymbols < ActiveRecord::Migration::Current
end
```
After change:
```ruby
# frozen_string_literal: true
# coding: ISO-8859-15
# This migration comes from bukkits (originally 1)
class CurrenciesHaveSymbols < ActiveRecord::Migration::Current
end
```
Caching something that shouldn't be cached is a potential source of
bugs and security vulnerabilities. For example, one could write a
form helper that outputs a request-specific auth token, only for
the helper to be used inside of a `cache` block.
In the GitHub application, we implemented a caching? method and used
it to raise an error if a specific code path is being cached that
we don't want to be cached.
I've credited its original author, @btoews.
Co-authored-by: Ben Toews <mastahyeti@gmail.com>
Co-authored-by: John Hawthorn <jhawthorn@github.com>
Co-authored-by: Kasper Timm Hansen <kaspth@gmail.com>
`DEFAULT_EXP` is by far the most common regexp being anchored.
By special casing it, we can re-use the existing `DEFAULT_EXP_ANCHORED`
regexp, and avoid keeping lots of copies of it in memory. Every time
we hit, we also avoid having to compile the regexp, so it's faster.
We also replace the `Regexp.new(/\A#{sym}\Z/)` pattern by just
`/\A#{sym}\Z/`, as it was compiling and instantiating an extra
regexp for no good reason.
This allows you to specify an explicit order that you'd like records
returned in based on a SQL expression. By default, this will be accomplished
using a case statement, as in:
```ruby
Post.in_order_of(:id, [3, 5, 1])
```
will generate the SQL:
```sql
SELECT "posts".* FROM "posts" ORDER BY CASE "posts"."id" WHEN 3 THEN 1 WHEN 5 THEN 2 WHEN 1 THEN 3 ELSE 4 END ASC
```
However, because this functionality is built into MySQL in the form of the
`FIELD` function, that connection adapter will generate the following SQL
instead:
```sql
SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
```
*Kevin Newton*
This commit introduces a new `Journey::Ast` class that wraps the root
node of an ast. The purpose of this class is to reduce the number of
walks through the ast by taking a single pass through each node and
caching values for later use.
To avoid retaining additional memory, we clear out these ast objects
after eager loading.
Benefits
---
* Performance improvements (see benchmarks below)
* Keeps various ast manipulations together in a single class, rather
than scattered throughout
* Adding some names to things will hopefully make this code a little
easier to follow for future readers
Benchmarks
---
We benchmarked loading a real routes file with > 3500 routes.
master was at a9336a67b0 when we ran these. Note that these benchmarks
also include a few small changes that we didn't include in this commit,
but that we will follow up with after this gets merged - these
additional changes do not change the benchmarks significantly.
Time:
```
master - 0.798 ± 0.024 (500 runs)
this branch - 0.695 ± 0.029 (500 runs)
```
Allocations:
```
master - 980149 total allocated objects
this branch - 931357 total allocated objects
```
Stackprof:
Seeing `ActionDispatch::Journey::Visitors::Each#visit` more frequently
on the stack is what led us down this path in the first place. These
changes seem to have done the trick.
```
master:
TOTAL (pct) SAMPLES (pct) FRAME
52 (0.5%) 52 (0.5%) ActionDispatch::Journey::Nodes::Node#symbol?
58 (0.5%) 45 (0.4%) ActionDispatch::Journey::Scanner#scan
45 (0.4%) 45 (0.4%) ActionDispatch::Journey::Nodes::Cat#type
43 (0.4%) 43 (0.4%) ActionDispatch::Journey::Visitors::FunctionalVisitor#terminal
303 (2.7%) 43 (0.4%) ActionDispatch::Journey::Visitors::Each#visit
69 (0.6%) 40 (0.4%) ActionDispatch::Routing::Mapper::Scope#each
this commit:
TOTAL (pct) SAMPLES (pct) FRAME
82 (0.6%) 42 (0.3%) ActionDispatch::Journey::Scanner#next_token
31 (0.2%) 31 (0.2%) ActionDispatch::Journey::Nodes::Node#symbol?
30 (0.2%) 30 (0.2%) ActionDispatch::Journey::Nodes::Node#initialize
```
See also the benchmark script in https://github.com/rails/rails/pull/39935#issuecomment-887791294
Co-authored-by: Eric Milford <ericmilford@gmail.com>
This was originally added in
8d26f875f7,
and then updated to something closer to it's current form in
https://github.com/rails/rails/pull/23140
The purpose was to alter the regexp for symbols surrounded by literals
(for path parameters within path segments like "/foo-:bar" or
"/:foo-bar") so that `default_regexp?` would return `false` for those
symbols. `default_regexp?` was then used to partition the routes (see
6ab985da28/actionpack/lib/action_dispatch/journey/routes.rb (L44)).
But after https://github.com/rails/rails/pull/41024, we're no longer
partitioning routes using `default_regexp?` (in fact we're no longer
using the method at all, so I've removed it). So I think it may now be
possible to remove this.
Prior to https://github.com/rails/rails/pull/41024, removing this code
would have broken the tests added in
https://github.com/rails/rails/pull/23140, but those tests now pass
without it. I also tried this patch with the GitHub monolith and didn't
get any test failures.
Followup: https://github.com/rails/rails/pull/42833
The previous fix wasn't working in practice because the LocalCache
middleware doesn't use `with_local_cache` but directly set a
regular `LocalStore` instance in the registry.
So instead we redecorate it on every access. It may cause some extra
allocations, but since it only happens in 6.1 mode, it's not as
much of a concern.
This commit addresses the CI failures with ruby 3.1.0dev.
https://buildkite.com/rails/rails/builds/79716#ef77b273-93d2-4372-a7fc-165dca6cadef
since Ruby ruby 3.1.0dev bumps the digest gem version to 3.0.1.pre
478f0ddb5f
- Without this commit
```ruby
$ ruby -v
ruby 3.1.0dev (2021-07-29T03:51:10Z master 64adeeadaa) [x86_64-linux]
$ bundle exec blade build
bundler: failed to load command: blade (/home/yahonda/.rbenv/versions/3.1.0-dev/bin/blade)
/home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/runtime.rb:300:in `check_for_activated_spec!': You have already activated digest 3.0.1.pre, but your Gemfile requires digest 3.0.0. Since digest is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports digest as a default gem. (Gem::LoadError)
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/runtime.rb:29:in `block in setup'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/spec_set.rb:158:in `each'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/spec_set.rb:158:in `each'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/runtime.rb:24:in `map'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/runtime.rb:24:in `setup'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler.rb:149:in `setup'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/setup.rb:10:in `block in <top (required)>'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/ui/shell.rb:136:in `with_level'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/ui/shell.rb:88:in `silence'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/setup.rb:10:in `<top (required)>'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/cli/exec.rb:61:in `require_relative'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/cli/exec.rb:61:in `kernel_load'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/cli/exec.rb:28:in `run'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/cli.rb:481:in `exec'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/cli.rb:31:in `dispatch'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/cli.rb:25:in `start'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/bundler-2.3.0.dev/libexec/bundle:49:in `block in <top (required)>'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/3.1.0/bundler/friendly_errors.rb:128:in `with_friendly_errors'
from /home/yahonda/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/bundler-2.3.0.dev/libexec/bundle:37:in `<top (required)>'
from /home/yahonda/.rbenv/versions/3.1.0-dev/bin/bundle:23:in `load'
from /home/yahonda/.rbenv/versions/3.1.0-dev/bin/bundle:23:in `<main>'
$
```
- With this commit
```ruby
$ bundle exec blade build
Building assets…
$
```