ActiveRecord::Type::Registry doesn't need to inherit from
ActiveModel::Type::Registry, and it makes both classes more simple.
Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com>
This deprecates `legacy_connection_handling` via the
`connection_handlers` setter. This is called from the ActiveRecord
Railtie on boot and since most applications don't set this themselves
this will prevent the deprecation from being raised multiple times for a
test run or in development.
I've also updated the guides to include a migration path for
applications using the deprecated methods. The majority of applications
won't need to make any changes.
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))$/"
```
I noticed in profiles of simple queries (like `Post.where(id: 1).first`)
we're spending lots of time looking up the current thread. I couldn't
find any way to speed this up in Ruby, so I thought maybe we could call
`Thread.current` fewer times per query.
This patch should eliminate 4 calls to `Thread.current` per query.
For this benchmark:
```ruby
StackProf.run(mode: :wall, out: 'out.dump') do
8000.times { Post.where(id: id).first }
end
```
`Thread.current` goes from 7% to 4.7% of time:
```
==================================
Mode: wall(1000)
Samples: 1633 (0.00% miss rate)
GC: 51 (3.12%)
==================================
TOTAL (pct) SAMPLES (pct) FRAME
140 (8.6%) 140 (8.6%) String#sub!
114 (7.0%) 114 (7.0%) Thread.current
```
```
==================================
Mode: wall(1000)
Samples: 1719 (0.00% miss rate)
GC: 51 (2.97%)
==================================
TOTAL (pct) SAMPLES (pct) FRAME
134 (7.8%) 134 (7.8%) String#sub!
99 (5.8%) 99 (5.8%) Module#===
81 (4.7%) 81 (4.7%) Thread.current
```
This isn't huge, but I think we need to find more sources of
Thread.current. It's surprising to me that we spend so much time
looking up the current thread when doing a query that is so "easy"
We're spending time validating symbol parameters of the ScopeRegistry.
It's an internal class, and we can stop validating symbols by converting
to methods (you'll automatically get an error if you try to call a
method that doesn't exist). Second, since we only have 3 things to keep
track of, rather than keep those things in a hash, just break it out in
to 3 instance variables. (This is absolutely not a memory bottleneck,
but technically this patch will save some memory as the 3 ivars will be
embedded in the object rather than require a full st_table for the
original wrapper hash)
This examines all the association branches we are being asked to preload
and will delay loading an association if it's likely that we find a
similar association later and can batch them together.
For example, when loading
Author.preload(:posts, favorite_authors: :posts).first
The preloader now knows to delay loading the top level posts so that it
can load both the top level :posts and the :posts from the favourite
authors associations together.
Co-authored-by: Dinah Shi <dinahshi@github.com>
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]