This PR does the following:
* Adds `trilogy` to lists of adapters where applicable
* Uses `MySQL` instead of adatper names where applicable
* Splits type information into adapters code so that the adapter is set
correctly.
* Fix tests that were using mysql2 when they should be abstract
* Add load hook for trilogy to match mysql2
This commit adds support for `:message_pack` and `:message_pack_allow_marshal`
as serializers for `config.action_dispatch.cookies_serializer`, just
like `config.active_support.message_serializer`.
The `:message_pack` serializer can fall back to deserializing with
`AS::JSON`, and the `:message_pack_allow_marshal` serializer can fall
back to deserializing with `AS::JSON` or `Marshal`. Additionally, the
`:marshal`, `:json`, and `:hybrid` / `:json_allow_marshal` serializers
can now fall back to deserializing with `AS::MessagePack`. These
behaviors make it easier to migrate between cookies serializers.
This commit adds support for `:message_pack` as a serializer for
`MessageEncryptor` and `MessageVerifier`, and, consequently, as an
option for `config.active_support.message_serializer`.
The `:message_pack` serializer is implemented via
`ActiveSupport::Messages::SerializerWithFallback` and can fall back to
deserializing with `AS::JSON`. Additionally, the `:marshal`, `:json`,
and `:json_allow_marshal` serializers can now fall back to deserializing
with `AS::MessagePack`.
This commit also adds support for `:message_pack_allow_marshal` as a
serializer, which can fall back to deserializing with `Marshal` as well
as `AS::JSON`.
Prior to this commit, `config.load_defaults 7.1` would cause old
messages (or messages from older apps) to become unreadable, and
developers were encouraged to manually set
`config.active_support.message_serializer = :json_allow_marshal` in
order to prevent this.
This commit changes the default message serializer set by
`config.load_defaults 7.1` from `:json` to `:json_allow_marshal` so that
upgraded apps can continue to read old messages without additional
configuration.
The intention is to eventually change the default to `:json` (with no
`Marshal` fallback) in Rails 7.2, after some time has passed with apps
generating JSON-serialized messages.
Apps can opt in to JSON-only serialization before Rails 7.2 by manually
setting `config.active_support.message_serializer = :json`.
Fixes#48118.
In #42843 and #42846, several config settings were added to control the
default serializer for `MessageEncryptor` and `MessageVerifier`, and to
provide a migration path from a default `Marshal` serializer to a
default `JSON` serializer:
* `config.active_support.default_message_encryptor_serializer`
* Supports `:marshal`, `:hybrid`, or `:json`.
* `config.active_support.default_message_verifier_serializer`
* Supports `:marshal`, `:hybrid`, or `:json`.
* `config.active_support.fallback_to_marshal_deserialization`
* Affects `:hybrid` for both `MessageEncryptor` and `MessageVerifier`.
* `config.active_support.use_marshal_serialization`
* Affects `:hybrid` for both `MessageEncryptor` and `MessageVerifier`.
This commit unifies those config settings into a single setting,
`config.active_support.message_serializer`, which supports `:marshal`,
`:json_allow_marshal`, and `:json` values. So, for example,
```ruby
config.active_support.default_message_encryptor_serializer = :hybrid
config.active_support.default_message_verifier_serializer = :hybrid
config.active_support.fallback_to_marshal_deserialization = true
config.active_support.use_marshal_serialization = false
```
becomes
```ruby
config.active_support.message_serializer = :json_allow_marshal
```
and
```ruby
config.active_support.default_message_encryptor_serializer = :hybrid
config.active_support.default_message_verifier_serializer = :hybrid
config.active_support.fallback_to_marshal_deserialization = false
config.active_support.use_marshal_serialization = false
```
becomes
```ruby
config.active_support.message_serializer = :json
```
This commit also replaces `ActiveSupport::JsonWithMarshalFallback` with
`ActiveSupport::Messages::SerializerWithFallback`, which implements a
generic mechanism for serializer fallback. The `:marshal` serializer
uses this mechanism too, so
```ruby
config.active_support.default_message_encryptor_serializer = :hybrid
config.active_support.default_message_verifier_serializer = :hybrid
config.active_support.fallback_to_marshal_deserialization = false
config.active_support.use_marshal_serialization = true
```
becomes
```ruby
config.active_support.message_serializer = :marshal
```
Additionally, the logging behavior of `JsonWithMarshalFallback` has been
replaced with notifications which include the names of the intended and
actual serializers, as well as the serialized and deserialized message
data. This provides a more targeted means of tracking serializer
fallback events. It also allows the user to "silence" such events, if
desired, without an additional config setting.
All of these changes make it easier to add migration paths for new
serializers such as `ActiveSupport::MessagePack`.
This updates two instances of custom initializer examples in the docs to
use the standard "library.name" format. Previously, one used just "name"
which can lead to hard to debug "cyclic dependency" errors, and the
other used "name.library" which is not the suggested format.
I don't know how prevalent this really is, but I heard several time
about users having memory exhaustion issues caused by the query cache
when dealing with long running jobs.
Overall it seems sensible for this cache not to be entirely unbounded.
This adds documentation for the `cache_read_multi.active_support`,
`cache_write_multi.active_support`, and `cache_delete_multi.active_support`
events to the Instrumentation guide.
This commit introduces a performance optimization for cache entries with
bare string values such as view fragments.
A new `7.1` cache format has been added which includes the optimization,
and the `:message_pack` cache format now includes the optimization as
well. (A new cache format is necessary because, during a rolling
deploy, unupgraded servers must be able to read cache entries from
upgraded servers, which means the optimization cannot be enabled for
existing apps by default.)
New apps will use the `7.1` cache format by default, and existing apps
can enable the format by setting `config.load_defaults 7.1`. Cache
entries written using the `6.1` or `7.0` cache formats can be read when
using the `7.1` format.
**Benchmark**
```ruby
# frozen_string_literal: true
require "benchmark/ips"
serializer_7_0 = ActiveSupport::Cache::SerializerWithFallback[:marshal_7_0]
serializer_7_1 = ActiveSupport::Cache::SerializerWithFallback[:marshal_7_1]
entry = ActiveSupport::Cache::Entry.new(Random.bytes(10_000), version: "123")
Benchmark.ips do |x|
x.report("dump 7.0") do
$dumped_7_0 = serializer_7_0.dump(entry)
end
x.report("dump 7.1") do
$dumped_7_1 = serializer_7_1.dump(entry)
end
x.compare!
end
Benchmark.ips do |x|
x.report("load 7.0") do
serializer_7_0.load($dumped_7_0)
end
x.report("load 7.1") do
serializer_7_1.load($dumped_7_1)
end
x.compare!
end
```
```
Warming up --------------------------------------
dump 7.0 5.482k i/100ms
dump 7.1 10.987k i/100ms
Calculating -------------------------------------
dump 7.0 73.966k (± 6.9%) i/s - 367.294k in 5.005176s
dump 7.1 127.193k (±17.8%) i/s - 615.272k in 5.081387s
Comparison:
dump 7.1: 127192.9 i/s
dump 7.0: 73966.5 i/s - 1.72x (± 0.00) slower
Warming up --------------------------------------
load 7.0 7.425k i/100ms
load 7.1 26.237k i/100ms
Calculating -------------------------------------
load 7.0 85.574k (± 1.7%) i/s - 430.650k in 5.034065s
load 7.1 264.877k (± 1.6%) i/s - 1.338M in 5.052976s
Comparison:
load 7.1: 264876.7 i/s
load 7.0: 85573.7 i/s - 3.10x (± 0.00) slower
```
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
This commit adds support for `:message_pack` as an option for
`config.active_support.cache_format_version`.
Cache entries written using the `6.1` or `7.0` formats can be read when
using the `:message_pack` format. Additionally, cache entries written
using the `:message_pack` format can now be read when using the `6.1` or
`7.0` format. These behaviors makes it easy to migrate between formats
without invalidating the entire cache.
`deferrable: true` is deprecated in favor of `deferrable: :immediate`, and
will be removed in Rails 7.2.
Because `deferrable: true` and `deferrable: :deferred` are hard to understand.
Both true and :deferred are truthy values.
This behavior is the same as the deferrable option of the add_unique_key method, added in #46192.
*Hiroyuki Ishii*
Those examples were obsolete, because nowadays using a reloadable
constant in initializers is not just a bad idea, it is indeed not
possible.
The patch updates the examples accordingly.
By linking to the libraries from the headings the anchor links in the
sidebar link directly to the libraries instead of the library's section.
This behaviour is unexpected.
We can link to the libraries in the section instead.
Currently the guides use the h1 tag for the guides logo instead of the
guides title. As the guides title is more important in describing the
content of a guide, the title should use the h1 instead.
This also move every other heading to a more important heading (h3 becomes h2, etc.).
This change should improve SEO for the guides.
Add back Sprockets guide(with remarks) to Asset Pipeline guide
Describe Import Maps in asset pipeline guide
Small rewording to first chapters of Asset Pipeline guide
Remove Sass and CoffeScript from Codin Links to Assets section
Remove Preprocessing section from Asset Pipeline guide
Mention dartsass-rails and rewrite beginning Asset Pipeline guide
Add more details on `rails-importmaps` in Asset Pipeline guide
Add alternative libraries section
Align Asset Pipeline guide Sprockets section for Sprockets V4
Improve the introduction to Asset Pipeline guide
Fix formatting in Importmap-rails section of Asset Pipeline guide
Reword, fix typos and add more context to the Asset Pipeline guide
Style, formatting and cleanup changes for asset pipeline guide
Minor style/typo fixes to Asset Pipeline guide
Remove sections dobuled by mistake from asset pipeline guide
Co-authored-by: Alex Ghiculescu <alex@tanda.co>
Co-authored-by: Breno Gazzola <breno.gazzola@gmail.com>
Co-authored-by: Shozo Hatta <hachi8833@gmail.com>
Fix: https://github.com/rails/rails/issues/47704
Superseed: https://github.com/rails/rails/pull/47722
While the instance variable ordering bug will be fixed in Ruby 3.2.2,
it's not great that we're depending on such brittle implementation detail.
Additionally, Marshalling Active Record instances is currently very inefficient,
the payload include lots of redundant data that shouldn't make it into the cache.
In this new format the serialized payload only contains basic Ruby core or stdlib objects,
reducing the risk of changes in the internal representation of Rails classes.
All other command usage uses two lines for "Usage: rails command".
This updates the usage of generators to do the same.
It also changes the command to `bin/rails`.
This is a follow up to rails#47186, this time for all markdown content.
[markdownlint](https://github.com/markdownlint/markdownlint) is an excellent tool, and I've found it very useful for finding issues in the guides.
Many of the rules are common style issues I'm correcting on PRs, so it will be nice to have that automated.
We should also be able to use the same config with our editors, so that errors show up in real-time 🙏 and will update the contributing docs once this gets merged with how to debug and use mdl appropriately.
Both `ActionText::Record` and `ActionText::RichText` have dedicated `ActiveSupport` load hooks. This adds an
additional hook for `ActionText::EncryptedRichText`, so that external libraries have a similarly simple way
to run code after the subclass is loaded.
In https://github.com/rails/rails/pull/46690 the `db_warnings_action` and `db_warnings_ignore` configs where added. The
`db_warnings_ignore` can take a list of warning messages to match against.
At GitHub we have a subscriber that that does something like this but also filters out error codes. There might also be
other applications that filter via error codes and this could be something they can use instead of just the explicit
messages.
This also refactors the adapter tests in order for mysql2 and postgresql adapters to share the same helper when setting
the db_warnings_action and db_warnings_ignore configs
All methods called on ActiveSupport::Deprecation are delegated to the
singleton instance, but now that each framework has its own Deprecation
instance, it's no longer necessary for internal deprecations.
For external code, instead of using ActiveSupport::Deprecation.warn,
they should create their own instance of the class and call warn on it.
[This blog post](https://dev.to/youngbloodcyb/rake-junior-rails-review-13cc) is about the confusion between `bin/rake` and `bin/rails` commands. The two have mostly [been aliases since Rails 5](3d252a02ae (diff-f5ff9aa07f44111a79d56c09ec37d774b462d97aff68f32490c2e56e74c95783R162)), but this means there's all sorts of advice floating around the internet about which command to use. Is `rake db:migrate` the same as `bin/rails db:migrate`? I know that it is, but I can see why it's confusing for a first timer.
The blog post's suggestion was to have a section in the guides that introduces rake and talks about this distinction. I'm not sure about this. I think if we take up too much space too early in the guide discussing this, it risks confusing people even earlier. But if the advice is hidden away too much, nobody will find it.
Something I think we should do, though, is mention `rake` as little as possible in the guides. Mentions in upgrade guides and release notes are fine, but elsewhere we should avoid using it in places where `bin/rails` does an equivalent job. This PR removes a few `rake` mentions from the guides. Before doing this, I was expecting there to be a lot more, so this PR turned out to be a bit smaller than expected. Still, every little bit helps I think.
* Update Asset Pipeline guide refs to Sass gem
Sassc-rails gem is no longer maintained. Sass is now compiled by Dart. The new dartsass-rails gem wraps the standalone release of the Dart version of Sass.
* Update asset_pipeline.md
---------
Co-authored-by: David Heinemeier Hansson <david@hey.com>
When an attribute is missing the current message is unclear about which
class is missing the attribute, especially when there are multiple
classes that could miss the attribute.
By adding the classs name to the error message it is easier to debug:
```ruby
user = User.first
user.pets.select(:id).first.user_id
=> ActiveModel::MissingAttributeError: missing attribute 'user_id' for Pet
```
This also makes the error message more inline with the
UnknownAttributeError message:
```ruby
=> ActiveModel::UnknownAttributeError: unknown attribute 'name' for Person
```
Co-authored-by: Yasuo Honda <yasuo.honda@gmail.com
Now that we support a way to register custom configurations we need to
allow applications to find those configurations. This change adds a
`config_key` option to `configs_for` to find db configs where the
configuration_hash contains a particular key.
I have also removed the deprecation for `include_replicas` while I was
in here to make the method signature cleaner. I've updated the upgrade
guide with the removal.
All Rails frameworks deprecators have "Rails" as their `gem_name`, and
the `:notify` behavior emits events based on that, so all frameworks
emit their deprecations under the `rails` namespace.
For example: activesupport/lib/active_support/deprecator.rb:5
activesupport/lib/active_support/deprecation.rb:42
activesupport/lib/active_support/deprecation/behaviors.rb:39
Before, it was using the configured by Rails. Having a mechanism to configure it
for Active Record encryption makes sense to prevent problems with encrypted content
when the default in Rails changes.
Additionally, there was a bug making AR encryption use the older SHA1 before
`ActiveSupport.hash_digest_class` got initialized to SHA256. This bug was exposed
by https://github.com/rails/rails/pull/44540. We will now set SHA256 as the standard
for 7.1+, and SHA1 for previous versions.
With the universal adoption of UTF-8 in browsers, user facing text can
use more optimal Unicode typography. In digital and print design, using
RIGHT SINGLE QUOTATION MARK (U+2019) is normally preferred over
APOSTROPHE (U+0027) in contractions.
For details, see the Unicode Standard Section 6.2:
https://www.unicode.org/versions/Unicode13.0.0/ch06.pdf
> Punctuation Apostrophe. U+2019 right single quotation mark is
> preferred where the character is to represent a punctuation mark, as
> for contractions: “We’ve been here before.” In this latter case,
> U+2019 is also referred to as a punctuation apostrophe.
YAML is great for configuration and such, but for serializing arbitrary
data it has many problem, both in term of performance and efficiency
but also in term of security.
As such, we shouldn't let it be the default.
The open question is wether we should provide another default, or
just let users chose what they want based on their own tradeoffs.
Many people would probably suggest JSON as the new default, unfortunately
I don't think it's a good fit either because the parsers available in
Ruby have some wonky behaviors:
```ruby
>> ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(Object.new))
=> {}
>> JSON.load(JSON.dump(Object.new))
=> "#<Object:0x000000012b61a068>"
```
If we were to select another default, I beleive it would need several
properties:
- It should only serialized a safe list of primitive types.
- It should explictly raise if attempting to serialize complex types.
YAML has quite a bit of footguns, as such it's desirable
to be able to substitute it for something else or even
simply to force users to define a serializer explictly for
every serialized columns.