Follow-up to #47942.
This commit simplifies the normalization of regexp test filters.
Instead of modifying a given regexp to match a union of whitespace and
underscores, the regexp is unioned with the underscore-normalized
version of itself. This allows filters that include escaped spaces,
such as `/foo\ bar/`.
This commit also fixes `Rails::LineFiltering#run` such that
normalization isn't reapplied for every test suite. Thus
`normalize_declarative_test_filter` is no longer required to be
idempotent.
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
Follow-up to [#47420][]
With the changes made in [#47420][], `has_secure_token` declarations can
be configured to execute in an `after_initialize` callback. This commit
proposed a new Rails 7.1 default: generate all `has_secure_token` values
when their corresponding models are initialized.
To preserve pre-7.1 behavior, applications can set
`config.active_record.generate_secure_token_on = :create`.
By default, generate the value when the model is initialized:
```ruby
class User < ApplicationRecord
has_secure_token
end
record = User.new
record.token # => "fwZcXX6SkJBJRogzMdciS7wf"
```
With `config.active_record.generate_secure_token_on = :create`, generate
the value when the model is created:
```ruby
# config/application.rb
config.active_record.generate_secure_token_on = :create
# app/models/user.rb
class User < ApplicationRecord
has_secure_token on: :create
end
record = User.new
record.token # => nil
record.save!
record.token # => "fwZcXX6SkJBJRogzMdciS7wf"
```
[#47420]: https://github.com/rails/rails/pull/47420
Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
`Kernel#caller` has linear performance based on how deep the
stack is. While this is a development only feature, it can end
up being quite slow.
Ruby 3.2 introduced `Thread.each_caller_location`, which lazily
yield `Backtrace::Location` objects.
Ref: https://bugs.ruby-lang.org/issues/16663
This is perfect for this use case as we are searching for the
closest frame that matches a pattern, saving us from collecting
the entire backtrace.
When we're editing the contents of encrypted files, we should use the
`Tempfile` class because it creates temporary files with restrictive
permissions. This prevents other users on the same system from reading
the contents of those files while the user is editing them.
[CVE-2023-38037]
To avoid accidental writing to the production database, I always start
rails console in sandbox mode. I only start rails console in non-sandbox
mode when I'm sure I want to write to the production database.
`sandbox_by_default` option is added to start rails console in sandbox
mode by default. With this option turned on, `--no-sandbox` must be
specified to start rails in non-sandbox mode.
Note that this option is ignored when rails environment is development
or test.
This `#use_puma?` check was [introduced][1] because Rails could
potentially display the wrong server URL in development if another host
or port is configured in `config/puma.rb`.
However, in Rack 3 the the name of the server class changed from
`Rack::Handler::Puma` to `Rackup::Handler::Puma`, which means that the
served_url is being logged again.
This commit fixes the check to accept either version of the class.
Additionally, puma was updated in Gemfile.lock because Puma 6.0.x prints
a deprecation warning about Rack::Handler that's fixed in 6.1.0.
[1]: 29648ff60e66c674b3cc49151df15dc100ffb4f4
Follow-up to #47178.
RDoc's Markdown parser requires multi-line list items to use a hanging
indent of at least four spaces. Otherwise, trailing lines will be
rendered as an independent paragraph, and the next list item will start
a new list.
While these are valid Rack Handler names, their handler name is not the
same as their gem name.
| handler | gem |
| ------- | ---------- |
| fastcgi | fcgi |
| lsws | ruby-lsapi |
We cannot compare paths directly to strings or that might fail on
different operating system. In this case, comparing to `/` fails on
Windows and we end up in endless recursion. We need to use
`Pathname#root?` to check if we reached the root of the folder structure
When an application defines mailers without any corresponding previews,
requests to `GET /rails/mailers` return a page with a blank `<body>`
element.
This entirely empty page can be confusing, since it's difficult to
distinguish the "success" state with an empty list and a "failure" state
with swallowed errors.
Similarly, when an `ActionMailer::Preview` subclass is defined, but
doesn't declare any actions, the response contains a mostly empty page.
This commit renders empty-state messaging for both scenarios, and links
to the [Action Mailer Basics][] guides.
To effectively cover that behavior, this commit also expands the Mailer
Preview test coverage to utilize [rails-dom-testing][] assertions.
[Action Mailer Basics]: https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails
[rails-dom-testing]: http://github.com/rails/rails-dom-testing
This was originally added in #47781:
> ...rails logo hover on welcome page is being triggered on square instead of round image.
However, on Safari the border is being cut-off.
I'm not sure there is another workaround, but I am willing to accept a larger (square) clickable area to have a consistent drop shadow.
which controls the HTML parser used by rails-dom-testing assertions.
The config parameter is set to :html5 in Rails 7.1 if the Nokogiri
HTML5 parser is supported.
As of Selenium 4.6, [the Selenium Manager is capable of managing Chrome
Driver installations and integrations][readme]. As of Selenium 4.11, the
Selenium Manager is capable of [capable of resolving the Chrome for
Testing installation][] path.
By omitting the `gem` declaration from the `Gemfile.tt`, newly generated
applications and applications updating their `Gemfile` in lockstep with
newer Rails versions can shed the dependency and avoid test failures
introduced by newly released Chrome versions (like, for example,
[titusfortner/webdrivers#247][]).
[readme]: 43f8ac436c (update-selenium-manager)
[titusfortner/webdrivers#247]: https://github.com/titusfortner/webdrivers/issues/247
[capable of resolving the Chrome for Testing installation]: https://github.com/rails/rails/pull/48847#issuecomment-1656756862
Co-authored-by: Titus Fortner <titusfortner@users.noreply.github.com>
This adds additional test coverage to PermissionsPolicy::Middleware to
validate that it conforms to the Rack SPEC.
The only changes necessary were to use the appropriate header casing for
Content-Type and Feature-Policy. Since this was the only usage of the
CONTENT_TYPE constant, I opted to remove it, but I can replace it with a
DeprecatedConstantProxy if that's more desirable.
This commit adds support for replacing the compressor used for
serialized cache entries. Custom compressors must respond to `deflate`
and `inflate`. For example:
```ruby
module MyCompressor
def self.deflate(string)
# compression logic...
end
def self.inflate(compressed)
# decompression logic...
end
end
config.cache_store = :redis_cache_store, { compressor: MyCompressor }
```
As part of this work, cache stores now also support a `:serializer`
option. Similar to the `:coder` option, serializers must respond to
`dump` and `load`. However, serializers are only responsible for
serializing a cached value, whereas coders are responsible for
serializing the entire `ActiveSupport::Cache::Entry` instance.
Additionally, the output from serializers can be automatically
compressed, whereas coders are responsible for their own compression.
Specifying a serializer instead of a coder also enables performance
optimizations, including the bare string optimization introduced by cache
format version 7.1.
The new syntax allows you to filter tests by line ranges. For example, the
following command runs tests between line 10 to 20.
```bash
$ rails test test/models/user_test.rb:10-20
```
Co-authored-by: Seonggi Yang <seonggi.yang@gmail.com>
Co-authored-by: Ryohei UEDA <ueda@anipos.co.jp>
Co-authored-by: oljfte <oljfte@gmail.com>
Followup: https://github.com/rails/rails/pull/48743
After careful consideration, unless users have a schema cache dump loaded
and `check_schema_cache_dump_version = false`, we have no choice but
to arbitrate between resiliency and performance.
If we define attribute methods during boot, we allow them to be shared
between forked workers, and prevent the first requests to be slower.
However, by doing so we'd trigger a connection to the datase, which
if it's unresponsive could lead to workers not being able to restart
triggering a cascading failure.
Previously Rails used to be in some sort of middle-ground where
it would define attribute methods during boot if for some reason
it was already connected to the database at this point.
But this is now deemed undesirable, as an application initializer
inadvertantly establishing the database connection woudl lead to
a readically different behavior.
Followup: https://github.com/rails/rails/pull/48716
`model.connection_pool.schema_reflection` is never falsy, so that `if`
was pointless.
Instead we more properly check if the schema cache contains that table.
I also added some more comments to explain why the initializer tries
so hard not to touch the database.
A big problem with the current `SchemaCache` implementation is that it holds
a reference to a connection, and uses it to lazily query the schema when the
information is missing.
This cause issues in multi-threaded contexts because all the connections
of a pool share the same schema, so they are constantly setting themselves
as the connection the schema cache should use, and you can end up in
situation where Thread#1 query the schema cache, which end up using the
connection currently attributed to Thread#2.
For a very long time this worked more or less by accident, because all
connection adapters would have an internal Monitor.
However in https://github.com/rails/rails/pull/46519 we got rid of this
synchronization, revealing the pre-existing issue. Previously it would
work™, but still wasn't ideal because of unexpected the connection
sharing between threads.
The idea here is to refactor the schema cache so that it doesn't hold a
reference onto any connection.
And instead of a `SchemaCache`, connections now have access to a
`SchemaReflection`. Now the connection that needs a schema information
is always provided as an argument, so that in case of a miss, it can be
used to populate the cache.
That should fix the database thread safety issues that were witnessed.
However note that at this stage, the underlying `SchemaCache` isn't
synchronized, so in case of a race condition, the same schema query
can be performed more than once. It could make sense to add synchronization
in a followup.
This refactoring also open the door to query the cache without a connection,
making it easier to eagerly define model attribute methods on boot without
establishing a connection to the database.
Co-Authored-By: Jean Boussier <jean.boussier@gmail.com>
Co-Authored-By: zzak <zzakscott@gmail.com>
Fix: https://github.com/rails/rails/issues/45017
Ref: https://github.com/rails/rails/pull/29333
Ref: https://github.com/ruby/timeout/pull/30
Historically only raised errors would trigger a rollback, but in Ruby `2.3`, the `timeout` library
started using `throw` to interupt execution which had the adverse effect of committing open transactions.
To solve this, in Active Record 6.1 the behavior was changed to instead rollback the transaction as it was safer
than to potentially commit an incomplete transaction.
Using `return`, `break` or `throw` inside a `transaction` block was essentially deprecated from Rails 6.1 onwards.
However with the release of `timeout 0.4.0`, `Timeout.timeout` now raises an error again, and Active Record is able
to return to its original, less surprising, behavior.
This test uses sqlite3 in production mode which results in a warning in
the test output. This change sets the config option for silencing this
warning so we don't see it in test output.
Fixes 2 bugs in parallel testing.
The first bug was related to changes made in #45450 which meant that we were
no longer replacing the connection in parallel testing because the
config object is equal (we simply merge a new db name but the object id
of the config stays the same). This bug only manifested in mysql and
sqlite3 interestingly. It would fail on the internal metadata tables
because they were missing in the schema version check.
To fix this I introduced a `clobber: true` kwarg onto the connection
handler that allows us to bypass the functionality that won't make a new
connection if the config is the same. This is an easy way to fall back
to the old behavior from before this change. I only added `clobber`
to the `reconstruct_from_schema` call because we need to actually
replace the connection for these. It's not safe to add everywhere since
we don't always want to replace the connection.
After implementing this fix I was still seeing failures in the mysql
demo app I made due to the fact that `purge` was not re-establishing the
connection to a config that had a database defined. Neither sqlite3 or
postgresql were missing this.
I added a test for mysql2 so we don't have regressions in the future. I
think this was missed because sqlite3 only demonstrates the bug if it
was never successful on that worker and postgresql was fine.
Fixes#48547