As multiple databases have evolved it's becoming more and more
confusing that we have a `connection_specification_name` that defaults
to "primary" and a `spec_name` on the database objects that defaults to
"primary" (my bad).
Even more confusing is that we use the class name for all
non-ActiveRecord::Base abstract classes that establish connections. For
example connections established on `class MyOtherDatabaseModel <
ApplicationRecord` will use `"MyOtherDatabaseModel"` as it's connection
specification name while `ActiveRecord::Base` uses `"primary"`.
This PR deprecates the use of the name `"primary"` as the
`connection_specification_name` for `ActiveRecord::Base` in favor of
using `"ActiveRecord::Base"`.
In this PR the following is true:
* If `handler.establish_connection(:primary)` is called, `"primary"`
will not throw a deprecation warning and can still be used for the
`connection_specification_name`. This also fixes a bug where using this
method to establish a connection could accidentally overwrite the actual
`ActiveRecord::Base` connection IF that connection was not using a
configuration named `:primary`.
* Calling `handler.retrieve_connection "primary"` when
`handler.establish_connection :primary` has never been called will
return the connection for `ActiveRecord::Base` and throw a deprecation
warning.
* Calling `handler.remove_connection "primary"` when
`handler.establish_connection :primary` has never been called will
remove the connection for `ActiveRecord::Base` and throw a deprecation
warning.
See #38179 for details on more motivations for this change.
Co-authored-by: John Crepezzi <john.crepezzi@gmail.com>
This commit renames `RoleManager` -> `PoolManager` and `Role` ->
`PoolConfig`.
Once we introduced the previous commit, and looking at the existing
code, it's clearer that `Role` and `RoleManager` are not the right names
for these.
Since this PR moves away from swapping the connection handler concepts
around and the role concept will continue existing on the handler level,
we need to rename this.
A `PoolConfig` holds a `connection_specification_name` (we may rename
this down the road), a `db_config`, a `schema_cache`, and a `pool`. It
does feel like `pool` could eventually hold all of these things instead
of having a `PoolConfig` object. This would remove one level of the
object graph and reduce complexity. For now I'm leaving this object to
keep the change churn low and will revisit later.
Co-authored-by: John Crepezzi <seejohnrun@github.com>
While working on another feature for multiple databases (auto-switching)
I observed that in development the first request won't autoload the
application record connection for the primary database and may not yet
know about the replica connection.
In my test application this caused the application to thrown an error if
I tried to send the first request to the replica before the replica was
connected. This wouldn't be an issue in production because the
application is preloaded.
In order to fix this I decided to leave the original error message and
delete the new error message. I updated the original error message to
include the `role` to make it a bit clearer that the connection isn't
established for that particular role.
The error now reads:
```
No connection pool with 'primary' found for the 'reading' role.
```
A single database application will continue uisng the original error
message:
```
No connection pool with 'primary' found.
```
I’m renaming all instances of `use_transcational_fixtures` to
`use_transactional_tests` and “transactional fixtures” to
“transactional tests”.
I’m deprecating `use_transactional_fixtures=`. So anyone who is
explicitly setting this will get a warning telling them to use
`use_transactional_tests=` instead.
I’m maintaining backwards compatibility—both forms will work.
`use_transactional_tests` will check to see if
`use_transactional_fixtures` is set and use that, otherwise it will use
itself. But because `use_transactional_tests` is a class attribute
(created with `class_attribute`) this requires a little bit of hoop
jumping. The writer method that `class_attribute` generates defines a
new reader method that return the value being set. Which means we can’t
set the default of `true` using `use_transactional_tests=` as was done
previously because that won’t take into account anyone using
`use_transactional_fixtures`. Instead I defined the reader method
manually and it checks `use_transactional_fixtures`. If it was set then
it should be used, otherwise it should return the default, which is
`true`. If someone uses `use_transactional_tests=` then it will
overwrite the backwards-compatible method with whatever they set.
Follow-Up to https://github.com/rails/rails/pull/14348
Ensure that SQLCounter.clear_log is called after each test.
This is a step to prevent side effects when running tests. This will allow us to run them in random order.
In the end I think the pain of implementing this seamlessly was not
worth the gain provided.
The intention was that it would allow plain ruby objects that might not
live in your main application to be subclassed and have persistence
mixed in. But I've decided that the benefit of doing that is not worth
the amount of complexity that the implementation introduced.