Commit Graph

22278 Commits

Author SHA1 Message Date
Petrik
852d8e3591 Expand documentation of strict_loading! [ci-skip]
Add an example of using `strict_loading!(mode: :n_plus_one_only)` and
update the parameters formatting.
2023-02-08 12:16:15 +01:00
Petrik
32aba689ef Use Example heading without semicolon [ci-skip]
Make headers more consistent as we almost never add semicolons to the
headers.
2023-02-08 12:08:37 +01:00
Petrik de Heus
e5522e9cc6
Merge pull request #47253 from p8/activerecord/improve-eager-loading-docs
Clarify how `includes` works [ci-skip]
2023-02-08 10:52:22 +01:00
Petrik
e1ff7b1ee9 Clarify how includes works [ci-skip]
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>
2023-02-07 22:00:49 +01:00
Rafael Mendonça França
4adc62c07a
Move adapter specific tests to the adapter folder
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.
2023-02-07 19:04:23 +00:00
Rafael Mendonça França
6017df6a8e
Change mysql build command to work when a custom socket is set 2023-02-07 15:49:31 +00:00
Petrik
32aaeba0ae Show generated SQL as comment wihout => in all examples [ci-skip]
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.
2023-02-06 18:38:07 +01:00
Petrik de Heus
6de3af6e71
Merge pull request #47276 from p8/docs/more-consistent-sql-docs-output
Make sure SQL output is seen as a comment in docs [ci-skip]
2023-02-06 18:06:28 +01:00
Petrik
6775cc987f Make sure SQL output is seen as a comment in docs [ci-skip]
Some example code blocks show the generated SQL. These should be seen as
comments and not as Ruby code.
2023-02-06 18:01:30 +01:00
Koichi ITO
5726b1d1d7 Use RuboCop Performance 1.16.0
## 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
2023-02-06 13:06:31 +09:00
zzak
7b2087cd28 Split STI link into list to fix paragraph format 2023-02-06 11:56:46 +09:00
Matthew Draper
71a825cb77 Avoid possible reaping during connection pool fairness test
This test is occasionally showing a flaky result in CI... I'm not sure
this is the cause, but it seems like it could be a factor?
2023-02-05 16:32:24 +10:30
Matthew Draper
f8e3bde899
Merge pull request #47247 from matthewd/quote-bound-value
Bring back quote_bound_value & deprecate instead
2023-02-04 20:31:19 +10:30
zzak
66246be8c6 Refer to stable guide for ARel security 2023-02-04 09:01:21 +09:00
zzak
f8544410a2 Use stable guides link for package READMEs
E.g.: These show up here:
https://api.rubyonrails.org/files/actioncable/README_md.html
2023-02-04 09:01:00 +09:00
Matthew Draper
79911133e9 Bring back quote_bound_value & deprecate instead
I misread the module scoping; it's not actually nodoc.

This reverts commit 2f08e611d3fe3c20403b39399b8db68cf961a205.
2023-02-04 08:17:43 +10:30
Matthew Draper
73255bae9e Avoid assuming that save is instant
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.
2023-02-03 14:09:28 +10:30
Eileen M. Uchitelle
5defeececb
Merge pull request #47230 from Shopify/composite-foreign-key-assoc-assignment
Support composite foreign key association assignments
2023-02-02 16:34:41 -05:00
Nikita Vasilevsky
fda7cf37a5 Support composite foreign key association assignments
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.
2023-02-02 21:03:36 +00:00
Rafael Mendonça França
25d52ab782
Fix typo 2023-02-02 17:10:37 +00:00
Rafael Mendonça França
caaafcd4ae
Merge pull request #47220 from rafaelfranca/rm-connection-to-tag-logs
Pass the connection to query transformers
2023-02-02 10:08:25 -05:00
Eileen M. Uchitelle
75bab48ca5
Merge pull request #47224 from zzak/bump-rubocop
Bump rubocop from 1.43.0 to 1.44.1 and fix offenses
2023-02-02 09:14:35 -05:00
Eileen M. Uchitelle
65af1db309
Merge pull request #47223 from fatkodima/explain_test-warning
Fix stubbing method with arguments in `activerecord/test/cases/explain_test.rb`
2023-02-02 08:55:17 -05:00
Eileen M. Uchitelle
b67a9263c9
Merge pull request #47221 from Shopify/remove-unintentionally-added-array-wrap
Remove unintentional array wrap
2023-02-02 08:49:02 -05:00
zzak
9ff1a0496d Bump rubocop from 1.43.0 to 1.44.1 and fix offenses 2023-02-02 12:52:05 +09:00
fatkodima
1aba4b0ae1 Fix stubbing method with arguments in activerecord/test/cases/explain_test.rb 2023-02-02 03:24:34 +02:00
Rafael Mendonça França
892f3261ee
Get the information from the right database
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.
2023-02-01 23:38:55 +00:00
Rafael Mendonça França
d3b41750fb
Passing the connection into the context for query transformers
Sometimes we need to tag the queries with information that are in the
database connection that is making the query, so let's add it to the
context.
2023-02-01 23:38:54 +00:00
Rafael Mendonça França
a4b07c9166
Test cache_query_log_tags behavior using public API 2023-02-01 23:38:53 +00:00
Rafael Mendonça França
9ed7dcb351
Make sure to reset taggings in QueryLogsTest
This will avoid that this test mutates the global state of
ActiveRecord::QueryLogs.taggings and thus affect other tests.
2023-02-01 23:38:52 +00:00
Nikita Vasilevsky
21a53a1002 Remove unintentional array wrap 2023-02-01 23:36:57 +00:00
Rafael Mendonça França
3cdb779ff8
Only call the comment method once
In the case the comment existed we would be calling this method twice
before.
2023-02-01 22:38:50 +00:00
Petrik
6e89ae2d2e Use infinitive form verb for all task descriptions
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>
2023-02-01 22:43:04 +01:00
Jean Boussier
0ff9beba87 ActiveRecord::QueryLogs: handle invalid encoding
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.
2023-02-01 13:48:54 +01:00
Eileen M. Uchitelle
60bc028df8
Merge pull request #46962 from Shopify/foundation-to-support-composite-foreign-keys-in-associations
Support composite foreign keys in associations
2023-01-31 15:11:11 -05:00
Nikita Vasilevsky
734f424247 Support composite foreign keys in associations
Foundations to support associations with composite foreign keys like:
`Comment.belongs_to :blog_post, foreign_key: [:blog_id, :blog_post_id],
primary_key: [:blog_id, :id]`
2023-01-31 17:46:41 +00:00
Matthew Draper
55e4ddde1b
Merge pull request #46600 from matthewd/arel-sql-with-binds
Allow `Arel.sql` to accept bind parameters
2023-01-30 20:41:55 +10:30
Matthew Draper
24b400f55d Accept nodes directly in AbstractAdapter#to_sql
Previously this would generally always see a SelectManager or similar,
but BoundSqlLiteral is reasonable too.
2023-01-29 18:35:32 +10:30
Matthew Draper
fcf3388e74 This test specifically intends a non-insensitive column 2023-01-29 13:41:53 +10:30
Matthew Draper
76a197169d Use a unique type name while testing caching 2023-01-29 13:05:43 +10:30
Matthew Draper
3349c3b931 Wait longer for future results in tests
If this times out, the test will fail. One second doesn't seem to be
long enough for 100% success in CI.
2023-01-29 12:43:26 +10:30
Matthew Draper
f71fc8312b Disallow Arel.sql with mixed named and positional binds
This should be a much closer match to the existing AR sanitize_sql
behaviour.
2023-01-29 08:40:30 +10:30
Matthew Draper
68c5dedea7 Implement + for BoundSqlLiteral too 2023-01-29 08:40:30 +10:30
Matthew Draper
2f08e611d3 Clean up quote_bound_value
It's nodoc, so we can safely remove it without deprecation.
2023-01-29 08:40:30 +10:30
Matthew Draper
e1bb93493e Add tests for cast_bound_value 2023-01-29 08:40:30 +10:30
Matthew Draper
6cc5dc9b23 Inline quote_bound_value
This pushes a little work out to the caller, but should mean we can
avoid an extra API method.
2023-01-29 08:40:30 +10:30
Matthew Draper
6b1b832ea8 Reuse cast_bound_value for quote_bound_value 2023-01-29 08:40:30 +10:30
Matthew Draper
ea36714375 Cast bound values in Arel.sql
This applies the MySQL integer quoting behaviour even when we're using
bind values rather than interpolation.
2023-01-29 08:40:30 +10:30
Matthew Draper
6444ec0d30 Allow Arel.sql to accept bind parameters
Co-authored-by: Ahmed Shahin <codeminator@github.com>
2023-01-29 08:40:30 +10:30
Reid Lynch
f61a679902 ActiveRecord::Relation#explain accepts options
For databases and adapters which support them (currently PostgreSQL
and MySQL), options can be passed to `explain` to provide more
detailed query plan analysis.
2023-01-24 09:24:43 -05:00