This tries to improve the documentation of `includes` by:
* Explaining what types of queries will be created;
* Explaining the benefits of using separate queries over a simple join;
* Renaming `relationships` to the more commonly used `associations`;
* Showing the SQL that will be generated.
These changes borrow from the documentation of
`ActiveRecord::Associations::Preloader.
Co-authored-by: zzak <zzakscott@gmail.com>
Since #46865, sqlite3 specific tests were running for all adapter.
That happened because the `current_adapter?(:SQLite3Adapter)` check was
moved to the test case class but not for all of them.
To avoid this issue to happen again, just move those tests to each
adapter.
If we show the generated SQL in a Ruby code block, some examples used:
* a hash rocket `=>` (about 29 times)
* no hash rocket (about 124 times)
The hash rocket is shown in IRB to show the return value of the last
statement. As SQL is never returned this way, and for consistency the
hash rocket has been removed.
## Summary
This PR bumps RuboCop Performance to 1.16.0 and suppresses the following new offenses:
```console
% bundle exec rubocop
(snip)
Offenses:
actionpack/lib/action_dispatch/routing/mapper.rb:309:16:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
if /#/.match?(to)
^^^^^^^^^^^^^^
actionpack/lib/action_dispatch/routing/mapper.rb:1643:18:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
if /#/.match?(to)
^^^^^^^^^^^^^^
actionpack/lib/action_dispatch/routing/route_set.rb:887:67:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
path = Journey::Router::Utils.normalize_path(path) unless %r{://}.match?(path)
^^^^^^^^^^^^^^^^^^^^
actionpack/lib/action_dispatch/testing/assertions/routing.rb:86:12:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
if %r{://}.match?(expected_path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
actionpack/lib/action_dispatch/testing/assertions/routing.rb:205:14:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
if %r{://}.match?(path)
^^^^^^^^^^^^^^^^^^^^
actionpack/lib/action_dispatch/testing/integration.rb:235:12:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
if %r{://}.match?(path)
^^^^^^^^^^^^^^^^^^^^
actiontext/bin/webpack:18:6:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 150))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
actiontext/bin/webpack-dev-server:18:6:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 150))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb:120:64:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
elsif column.type == :uuid && value.is_a?(String) && /\(\)/.match?(value)
^^^^^^^^^^^^^^^^^^^^
railties/lib/rails/commands/secrets/secrets_command.rb:28:12:
C: [Correctable] Performance/StringInclude: Use String#include? instead of a regex match with literal-only pattern.
if /secrets\.yml\.enc/.match?(error.message)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3088 files inspected, 10 offenses detected, 10 offenses autocorrectable
```
## Additional Information
This behavior change is based on:
https://github.com/rubocop/rubocop-performance/pull/332
When unlucky, it can take a few milliseconds, and if particularly
unlucky that plus precision truncation can push us outside the previous
1s window.
Instead, we'll accept a +/- 1s buffer around the whole time that was
spent doing the save. This test is only about ensuring that some vaguely
CURRENT_TIMESTAMP-shaped value (i.e. the column's default) was stored,
and isn't actually so concerned about the specifics, anyway.
This test is still technically at risk of failure if the test-running
system's time disagrees with the database server's, or if the system
clock is adjusted mid-run... but those still seem acceptably ignorable;
I'm just reacting to a flaky failure in CI.
Given a model with a composite primary key, it is possible to assign
the association associated with the model by the composite foreign key.
For example, given two `Sharded::BlogPost` and `Sharded::Comment` models
that are associated using a composite foreign key so that:
`Sharded::BlogPost.has_many :comments, foreign_key: [:blog_id, :blog_post_id]`,
it is possible to assign an instance of `Comment` to an instance of
`BlogPost` like `blog_post.comments << comment`.
The same applies to the opposing `:belongs_to` association.
Previous this tag would get the information only from ActiveRecord::Base
connection, which in a multi-database application would be wrong.
This get the information from the connection that is going to be used to
execute the query.
We also had to change the NullPool to make this work.
It is only required because when checking out a connection form the pool,
we first create the object, check if the database version satisfies the
requirements, and then we assign the pool to the connection.
When we are checking the database version, we are doing a query, so we
try to annotate the query with the tags, but the pool isn't assigned yet,
so `pool.db_config` would return an exception.
This is because the NullPool doesn't satisfy the ConnectionPool
interface, which we should fix.
As the only queries that happen without a pool are very likely internal
queries we are retuning an object that respond to anything, without
caring if that object have the same interface of the real configs.
All the common rails commands and some extended commands use the
infinitive form for the verb in the description. This changes the
remaining tasks to use the infinitive form verb as well, for
consistency.
__Before__
```console
$ bin/rails --help
...
action_mailbox:install Installs Action Mailbox and its dependencies
...
app:template Applies the template supplied by LOCATION=(/path/to/template) or URL
...
credentials:diff Enrolls/disenrolls in decrypted diffs of credentials using git
credentials:edit Opens the decrypted credentials in `$EDITOR` for editing
credentials:show Shows the decrypted credentials
db:create Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use...
db:drop Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use d...
...
db:fixtures:load Loads fixtures into the current environment's database
db:migrate Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
db:migrate:down Runs the "down" for a given migration VERSION
db:migrate:redo Rolls back the database one migration and re-migrates up (options: STEP=x, VERSION=x)
db:migrate:up Runs the "up" for a given migration VERSION
db:prepare Runs setup if database does not exist, or runs migrations if it does
db:reset Drops and recreates all databases from their schema for the current environment and loads th...
db:rollback Rolls the schema back to the previous version (specify steps w/ STEP=n)
db:schema:cache:clear Clears a db/schema_cache.yml file
db:schema:cache:dump Creates a db/schema_cache.yml file
db:schema:dump Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['...
db:schema:load Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SC...
db:seed Loads the seed data from db/seeds.rb
db:seed:replant Truncates tables of each database for current environment and loads the seeds
db:setup Creates all databases, loads all schemas, and initializes with the seed data (use db:reset t...
db:system:change Changes `config/database.yml` and your database gem to the target database
db:version Retrieves the current schema version number
destroy Removes code generated by `bin/rails generate`
dev:cache Toggles development mode caching on/off
encrypted:edit Opens the decrypted file in `$EDITOR` for editing
encrypted:show Shows the decrypted contents of the file
...
log:clear Truncates all/specified *.log files in log/ to zero bytes (specify which logs with LOGS=test...
middleware Prints out your Rack middleware stack
notes Shows comments in your code annotated with FIXME, OPTIMIZE, and TODO
...
routes Lists all the defined routes
runner Runs Ruby code in the context of your application
...
secrets:edit Opens the secrets in `$EDITOR` for editing
secrets:show Shows the decrypted secrets
...
tmp:create Creates tmp directories for cache, sockets, and pids
version Shows the Rails version
...
zeitwerk:check Checks project structure for Zeitwerk compatibility
```
__After__
```console
$ bin/rails --help
...
action_mailbox:install Install Action Mailbox and its dependencies
...
app:template Apply the template supplied by LOCATION=(/path/to/template) or URL
...
credentials:diff Enrolls/disenrolls in decrypted diffs of credentials using git
credentials:edit Opens the decrypted credentials in `$EDITOR` for editing
credentials:show Shows the decrypted credentials
db:create Create the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use ...
db:drop Drop the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db...
...
db:fixtures:load Load fixtures into the current environment's database
db:migrate Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
db:migrate:down Run the "down" for a given migration VERSION
db:migrate:redo Roll back the database one migration and re-migrate up (options: STEP=x, VERSION=x)
db:migrate:status Display status of migrations
db:migrate:up Run the "up" for a given migration VERSION
db:prepare Run setup if database does not exist, or run migrations if it does
db:reset Drop and recreate all databases from their schema for the current environment and load the s...
db:rollback Roll the schema back to the previous version (specify steps w/ STEP=n)
db:schema:cache:clear Clear a db/schema_cache.yml file
db:schema:cache:dump Create a db/schema_cache.yml file
db:schema:dump Create a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['S...
db:schema:load Load a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCH...
db:seed Load the seed data from db/seeds.rb
db:seed:replant Truncate tables of each database for current environment and load the seeds
db:setup Create all databases, load all schemas, and initialize with the seed data (use db:reset to a...
db:system:change Change `config/database.yml` and your database gem to the target database
db:version Retrieve the current schema version number
destroy Remove code generated by `bin/rails generate`
dev:cache Toggle development mode caching on/off
encrypted:edit Open the decrypted file in `$EDITOR` for editing
encrypted:show Show the decrypted contents of the file
...
log:clear Truncate all/specified *.log files in log/ to zero bytes (specify which logs with LOGS=test...
middleware Print out your Rack middleware stack
notes Show comments in your code annotated with FIXME, OPTIMIZE, and TODO
...
routes List all the defined routes
runner Run Ruby code in the context of your application
...
secrets:edit Open the secrets in `$EDITOR` for editing
secrets:show Show the decrypted secrets
...
tmp:create Create tmp directories for cache, sockets, and pids
version Show the Rails version
...
zeitwerk:check Check project structure for Zeitwerk compatibility
```
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
It can sometimes happen that `sql` is encoded in UTF-8 but contains
some invalid binary data of some sort.
When this happens `strip` end up raising an EncodingError.
Overall I think this strip is quite wasteful, so we might as well
just skip it.
For databases and adapters which support them (currently PostgreSQL
and MySQL), options can be passed to `explain` to provide more
detailed query plan analysis.