Reusing the "books" one could cause interferences when fixtures are
loaded in a very specific order such as:
https://buildkite.com/rails/rails/builds/76217#ee4ce591-e6c1-4a0d-a7db-1f83647d141e
Reproduction script:
```
activerecord $ bin/test -v --seed 23607 -n "/^(?:EagerAssociationTest#(?:test_preloading_a_regular_association_with_a_typo_through_a_polymorphic_association_still_raises)|ActiveRecord::Encryption::EncryptableFixtureTest#(?:test_fixtures_get_encrypted_automatically)|ViewWithoutPrimaryKeyTest#(?:test_attributes|test_reading))$/"
```
This implements several changes to encourage deterministic encryption to
remain unchanged. The main motivation is letting you define unique
indexes on deterministically-encrypted columns:
- By default, deterministic encryption will always use the oldest
encryption scheme to encrypt new data, when there are many.
- You can skip this default behavior and make it always use the current
encryption scheme with:
```ruby
deterministic: { fixed: false } # using this should be a rare need
```
- Deterministic encryption still supports previous encryption schemes
normally. So they will be used to add additional values to queries, for
example.
- You can't rotate deterministic encryption keys anymore. We can add
support for that in the future.
This makes for reasonable defaults:
- People using "deterministic: true" will get unique indexes working out
of the box.
- The system will encourage keeping deterministic encryption stable:
- By always using oldest encryption schemes
- By forbidding configuring multiple keys
But you can still opt-out of the default if you need to.
This adds a new class `Scheme` that encapsulates the encryption
properties for a given attribute. This adds a proper code representation
for a domain concept we keep referring to: encryption schemes.
It's in charge of processing the user-passed config properties when
declaring the attribute, as well as of validating those.
This removes the concern of processing properties from
`EncryptableRecord` and `EncryptableAttributeType`. It's also nice to
have a place to group attribute encryption options, versus passing
lists of hashes around.
This is in preparation to upcoming changes that will add new config
options and support for previous encryption schemes.
The .encrypts declaration in `ActionText::Encryption` was making this test
fail. It was failing to load a MySQL error that was being raised when trying
to determine the column limit.
These can be configured as +ActiveRecord::Encryption.config+ keys if you want,
so you can just use your own ENV vars in a config file if you prefer not to use
credentials.
Order is inverted when inlined, which can make things difficult to read.
https://github.com/rails/rails/pull/41659#discussion_r592604925
In this case it doesn't really matter and I think it's better for `Configurable`
to go first, so the change is inverting the previous order deliberately.
[skip ci]
This uses the changes from https://github.com/rails/rails/pull/39929. Instead of doing a manual casting of
the previous value as part of the type, it leverages the existing support to do this now.
It also fixes a problem when loading a class with an encrypt declaration that wasn't backed
by a table was failing.
CC @kaspth
We are not encrypting attributes when loading models with the table
missing. This way we make sure we only load the encrypted models when
necessary during the encryption tests and prevent the problem of missing
encrypted attributes due to having cached the class without them encrypted.