The Rails guides were migrated from Turbolinks to Turbo in
0f6575a5344246d385d1a724e8b0bb3544ab6478
The PR discussion explains that the file was grabbed from unpkg, and a
decision was made to not run it through a minifier.
This commit adds a rake task to automate the process of grabbing the
turbo js file using Importmap::Packager, which is what importmap-rails
uses for `bin/importmap pin --download`.
The extra Importmap module definition is necessary because the
Importmap::Packager file uses the shorthand module syntax, meaning that
an error is thrown if the Importmap module is not previously defined.
`require "importmap-rails"` would normally define this module, but one
of its dependent requires will not load outside of a Rails application.
The turbo.css file was removed as it appears to be leftover from
Turbolinks and Turbo does not provide any css files in its dist.
There are multiple points of failure when processing a message with
`MessageEncryptor` or `MessageVerifier`, and there several ways we might
want to handle those failures. For example, swallowing a failure with
`MessageVerifier#verified`, or raising a specific exception with
`MessageVerifier#verify`, or conditionally ignoring a failure when
rotations are configured.
Prior to this commit, the _internal_ logic of handling failures was
implemented using a mix of `nil` return values and raised exceptions.
This commit reimplements the internal logic using `throw` and a few
precisely targeted `rescue`s. This accomplishes several things:
* Allow rotation of serializers for `MessageVerifier`. Previously,
errors from a `MessageVerifier`'s initial serializer were never
rescued. Thus, the serializer could not be rotated:
```ruby
old_verifier = ActiveSupport::MessageVerifier.new("secret", serializer: Marshal)
new_verifier = ActiveSupport::MessageVerifier.new("secret", serializer: JSON)
new_verifier.rotate(serializer: Marshal)
message = old_verifier.generate("message")
new_verifier.verify(message)
# BEFORE:
# => raises JSON::ParserError
# AFTER:
# => "message"
```
* Allow rotation of serializers for `MessageEncryptor` when using a
non-standard initial serializer. Similar to `MessageVerifier`, the
serializer could not be rotated when the initial serializer raised an
error other than `TypeError` or `JSON::ParserError`, such as
`Psych::SyntaxError` or a custom error.
* Raise `MessageEncryptor::InvalidMessage` from `decrypt_and_verify`
regardless of cipher. Previously, when a `MessageEncryptor` was using
a non-AEAD cipher such as AES-256-CBC, a corrupt or tampered message
would raise `MessageVerifier::InvalidSignature` due to reliance on
`MessageVerifier` for verification. Now, the verification mechanism
is transparent to the user:
```ruby
encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-gcm")
message = encryptor.encrypt_and_sign("message")
encryptor.decrypt_and_verify(message.next)
# => raises ActiveSupport::MessageEncryptor::InvalidMessage
encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-cbc")
message = encryptor.encrypt_and_sign("message")
encryptor.decrypt_and_verify(message.next)
# BEFORE:
# => raises ActiveSupport::MessageVerifier::InvalidSignature
# AFTER:
# => raises ActiveSupport::MessageEncryptor::InvalidMessage
```
* Support `nil` original value when using `MessageVerifier#verify`.
Previously, `MessageVerifier#verify` did not work with `nil` original
values, though both `MessageVerifier#verified` and
`MessageEncryptor#decrypt_and_verify` do:
```ruby
encryptor = ActiveSupport::MessageEncryptor.new("x" * 32)
message = encryptor.encrypt_and_sign(nil)
encryptor.decrypt_and_verify(message)
# => nil
verifier = ActiveSupport::MessageVerifier.new("secret")
message = verifier.generate(nil)
verifier.verified(message)
# => nil
verifier.verify(message)
# BEFORE:
# => raises ActiveSupport::MessageVerifier::InvalidSignature
# AFTER:
# => nil
```
* Improve performance of verifying a message when it has expired and one
or more rotations have been configured:
```ruby
# frozen_string_literal: true
require "benchmark/ips"
require "active_support/all"
verifier = ActiveSupport::MessageVerifier.new("new secret")
verifier.rotate("old secret")
message = verifier.generate({ "data" => "x" * 100 }, expires_at: 1.day.ago)
Benchmark.ips do |x|
x.report("expired message") do
verifier.verified(message)
end
end
```
__Before__
```
Warming up --------------------------------------
expired message 1.442k i/100ms
Calculating -------------------------------------
expired message 14.403k (± 1.7%) i/s - 72.100k in 5.007382s
```
__After__
```
Warming up --------------------------------------
expired message 1.995k i/100ms
Calculating -------------------------------------
expired message 19.992k (± 2.0%) i/s - 101.745k in 5.091421s
```
Fixes#47185.
This linter parses the Rails::Application::Configuration file and
ensures that
- all configurations are listed alphabetically in Configuring guide
- all framework defaults are listed alphabetically in Configuring guide
- all framework defaults are included in the new_framework_defaults_x_x
template
Optimize `TextHelper.highlight` for large inputs
Co-authored-by: Matthew Draper <matthew@trebex.net>
Co-authored-by: John Hawthorn <john@hawthorn.email>
The state that leaks comes from the table schema cache because the cache never gets cleared when the table gets dropped in a test scenario.
We now clear the schema cache every time a table is dropped in a test scenario.
Co-authored-by: Frederic Ma <frederic.ma@shopify.com>
Related to #45389
Guard against the omission of touching the `updated_at` timestamp in the scenario where attributes are changed by `before` callbacks, but no attributes are changed outside of the callbacks.
This tries to improve the documentation by:
* Explaining what types of queries will be created;
* Explaining the benefits of using separate queries over a simple join;
* Showing the SQL that will be generated.
Co-authored-by: zzak <zzakscott@gmail.com>
This require was added in cfcea1d53ae5ce38a7cbeb41e05958dc009988b0, but
at that time the generated Gemfile did not resolve using the gemspec.
gemspec was added to the plugin's generated Gemfile later in
a74e4736f95befa7a22c208019bf11a155ff7543. Since then, the
Bundler.require in the plugin's generated config/application.rb will
require the plugin and the extra require is unneeded.
The replaced test was added in adfa417fbbf6f670c3d10ed2c32c58bc1dc92c2e
when the plugin generator's application.rb was replaced with the app
generator's. Since the test is only concerned with the file content and
not whether that content is useful, the test was replaced with an
attempt to run the plugin's test, since this would verify that the
plugin can be loaded within the dummy app.
The plugin helpers are added because the generated Gemfile is now used
for resolution instead of Rails'. This makes the tests more accurate
because real plugins will be resolving against their own Gemfiles.
However, this also leads to a few issues solved by the new helpers:
- gemspecs are generated with TODOs that have to be fixed
- commands run in the plugin must have their Bundler environment reset
because processes spawned in Rails' tests inherit BUNDLE_GEMFILE
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
`sql.active_record` should be more commonly used than this more specific
`strict_loading_violation.active_record` one, so move it down in the
guide and leave the `sql` one first.
Also add an info message about that event only being emitted in case the
relevant config is set, otherwise it defaults to raising an error and no
event is instrumented.
[ci skip]