Previously, configuring Rails.logger to output to STDERR would result in
double logs when running the `rails server` command. This was due to the
server command broadcasting the logger to STDOUT if it did not already
output to STDOUT.
This commit fixes the issue by checking that the logger does not output
to STDERR in addition to STDOUT before broadcasting. This aligns it with
a similar broadcast done in the Active Record railtie.
Fixes https://github.com/rails/rails/issues/46103
An issue exists if you set `config.active_record.query_log_tags` to an array that includes `:controller`, `:action`, or `:job`; the relevant item will get duplicated in the log line. This occured because the relevant railties would add the item to `config.active_record.query_log_tags` again during setup. This PR fixes that by only adding those items to the config if they aren't already set.
The issue proposed more documentation to work around this, but I think it's a bug and should be fixed directly.
The `Gemfile` was updated in #46106 to allow Puma 6. Puma v6.0.0 was
released on 2022-10-14. This commit updates `Gemfile.lock` to reflect
the new version.
This commit also updates the Puma version constraint used in generated
apps to allow Puma 6.
The default controller scaffolding currently sends back a 302 for its
destroy action.
Since Hotwire is the default for Rails going forward, this can be
problimatic. Turbo uses the fetch API internally which is particular on
how it handles redirects.
As outlined in this table in this Turbo issue,
https://github.com/hotwired/turbo/issues/84#issuecomment-862656931,
Turbo making a DELETE request (not POST + hidden _method field) and
recieving a 302 back will result in another DELETE request instead of a
GET request for the redirect.
This updates the controller template used for the scaffold generator
to send back the 303 see other status code for the destroy action.
For consistancy-sake, the Action Controller Overview guide examples
were also updated. The main Getting Started guide page already has
see other used in its example destroy action.
For non-Hotwire users, the browser will still properly redirect on
a 303 as it does with a 302.
Overriding the database to :memory: results in a failing test for this
PR: https://github.com/rails/rails/pull/46097 because the database would
be reset at the start of every request in this integration test if/when
the the injected `ActiveRecord::Migration::CheckPending` middleware
re-establishes `ActiveRecord::Base.connection` between each request
I have improved a couple of issues I saw with the assertions in this
test as well, namely:
1. Asserting that the last request actually succeeded, as to avoid
ambiguous test failures
2. Not referencing `Post` from outside the Rack application, because
otherwise our assertion would be invalid (because referencing the
constant actually loads it!!)
We recently let a few very easy to avoid warnings get merged.
The root cause is that locally the test suite doesn't run in
verbose mode unless you explictly pass `-w`.
On CI warnings are enabled, but there is no reason to look at the
build output unless something is failing. And even if one wanted
to do that, that would be particularly work intensive since warnings
may be specific to a Ruby version etc.
Because of this I believe we should:
- Always run the test suite with warnings enabled.
- Raise an error if a warning is unexpected.
We've been using this pattern for a long time at Shopify both in private
and public repositories.
This adds a `Rails.application.deprecators` method that returns a
managed collection of deprecators.
Individual deprecators can be added and retrieved from the collection:
```ruby
Rails.application.deprecators[:my_gem] = ActiveSupport::Deprecation.new("2.0", "MyGem")
Rails.application.deprecators[:other_gem] = ActiveSupport::Deprecation.new("3.0", "OtherGem")
```
And the collection's configuration methods affect all deprecators in the
collection:
```ruby
Rails.application.deprecators.debug = true
Rails.application.deprecators[:my_gem].debug
# => true
Rails.application.deprecators[:other_gem].debug
# => true
```
Additionally, all deprecators in the collection can be silenced for the
duration of a given block:
```ruby
Rails.application.deprecators.silence do
Rails.application.deprecators[:my_gem].warn # => silenced (no warning)
Rails.application.deprecators[:other_gem].warn # => silenced (no warning)
end
```
Building on the new Query Log formatting implemented in #45139, we are now setting the correct defaults for
active_record.query_log_tags_format defaults as well.
Fixes: #46179
Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
Prior to this commit, several tests in `AppGeneratorTest` were testing
app update behavior without actually running `rails app:update`. This
meant the logic in `Rails::AppUpdater#generator_options` that detects
which frameworks and components are installed was not being tested.
Additionally, because `ENV["BUNDLE_GEMFILE"]` is set when tests are run
(by `require "bundler/setup"` in `tools/test.rb`), any tests which did
run `rails app:update` used the Rails repo Gemfile, instead of the
generated app Gemfile. The difference becomes obvious when running
`rails app:update` after generating an app without Sprockets (as in
`test_app_update_does_not_generate_manifest_config_when_propshaft_is_used`),
because `rails app:update` will load the Sprockets railtie (due to
`Bundler.require` using the Rails repo Gemfile), and then exit with a
`Sprockets::Railtie::ManifestNeededError`. However, if
`rails app:update` is run within a `quietly` block, such an error will
be swallowed.
This commit changes all such tests to run `rails app:update` via a
`run_app_update` helper that: (1) overrides the `BUNDLE_GEMFILE`
environment variable to point to the generated app Gemfile, (2) points
the `rails` gem in the generated app Gemfile to the Rails repo
(otherwise the `rails` gem version cannot be resolved), and (3) sets
`exception: true` so that the `system` call will raise an error if
`rails app:update` exits with an error code.
This commit also adds `jbuilder` and `web-console` to the Rails repo
Gemfile to ensure they are already installed when evaluating the
generated app Gemfile.
These changes do add a couple dozen seconds to the test suite run time,
but the thorough test coverage seems worth it.
In Active Record `connection_class` already means "the class in your
application that established the connection" so I would prefer it only
have that one meaning. This change swaps `connection_class` for
`adapter_class` where applicable.
Instead of hosting the connection logic in the command object, the
database adapter should be responsible for connecting to a console session.
This patch moves #find_cmd_and_exec to the adapter and exposes a new API to
lookup the adapter class without instantiating it.
Co-authored-by: Paarth Madan <paarth.madan@shopify.com>
The CHANGELOG entry for #44179 originally focused on
`ActiveSupport::MessageVerifiers` and `ActiveSupport::MessageEncryptors`,
and made sense in `activesupport/CHANGELOG.md`. However, prior to
merge, the focus changed to `Rails.application.message_verifiers`.
Therefore, the CHANGELOG entry should be in `railties/CHANGELOG.md`.
Commit 37d1429ab1 introduced the DummyERB to avoid loading the environment when
running `rake -T`.
The DummyCompiler simply replaced all output from `<%=` with a fixed string and
removed everything else. This worked okay when it was used for YAML values.
When using `<%=` within a YAML key, it caused an error in the YAML parser,
making it impossible to use ERB as you would expect. For example a
`database.yml` file containing the following should be possible:
development:
<% 5.times do |i| %>
shard_<%= i %>:
database: db/development_shard_<%= i %>.sqlite3
adapter: sqlite3
<% end %>
Instead of using a broken ERB compiler we can temporarily use a
`Rails.application.config` that does not raise an error when configurations are
accessed which have not been set as described in #35468.
This change removes the `DummyCompiler` and uses the standard `ERB::Compiler`.
It introduces the `DummyConfig` which delegates all known configurations to the
real `Rails::Application::Configuration` instance and returns a dummy string for
everything else. This restores the full ERB capabilities without compromising on
speed when generating the rake tasks for multiple databases.
Deprecates `config.active_record.suppress_multiple_database_warning`.
Gotta be honest, this is so I can make some hacks. Basically I would
like an engine to specify where to find rescue templates, and currently
there's no way to add search paths to the debug view lookup context.
This commit turns the template path in to an array (that I plan to
mutate, but nobody should do that besides me until we make an actual
good API).
I added the `dup` in `initialize` so in case the array is accidentally
mutated we don't leak memory.
Previously, the app_name in the App Generator would behave differently
when creating a new app and updating an existing app.
When updating an app, app_name is always the Rails::Application class
name underscored. When creating a new app, app_name will use whatever
the user passes in with a few characters replaced.
This isn't necessarily an issue, but it can lead to extra noise when
running app:update. For example, an app generated with `rails new
MyWebSite` will end up with a configuration line like:
```
config.active_job.queue_name_prefix = "MyWebSite_production"
```
and running app:update will change it to
```
config.active_job.queue_name_prefix = "my_web_site_production"
```
By normalizing app_name when creating an application, the amount of
changes when updating is reduced.
Currently, `Rails.application.message_verifier(name)` returns a
`MessageVerifier` instance using a secret derived from the given `name`.
Instances created this way always generate messages using the default
options for `MessageVerifier.new`. Also, if there are older options to
rotate for message verification, each instance created this way must be
configured individually. In cases where Rails itself uses
`Rails.application.message_verifier` (e.g. in Active Storage),
discovering the name of the instance may require digging through
Rails' source code.
To alleviate these issues, this commit adds a `MessageVerifiers` factory
class, which acts as a central point for configuring and creating
`MessageVerifier` instances. Options passed to `MessageVerifiers#rotate`
will be applied to `MessageVerifier` instances that `MessageVerifiers#[]`
creates. So the following:
```ruby
foo_verifier = Rails.application.message_verifier(:foo)
foo_verifier.rotate(old_options)
bar_verifier = Rails.application.message_verifier(:bar)
bar_verifier.rotate(old_options)
```
Can be rewritten as:
```ruby
Rails.application.message_verifiers.rotate(old_options)
foo_verifier = Rails.application.message_verifiers[:foo]
bar_verifier = Rails.application.message_verifiers[:bar]
```
Additionally, `Rails.application.message_verifiers` supports a
`:secret_key_base` option, so old `secret_key_base` values can be
rotated:
```ruby
Rails.application.message_verifiers.rotate(secret_key_base: "old secret_key_base")
```
`MessageVerifiers` memoizes `MessageVerifier` instances. This also
allows `MessageVerifier` instances to be overridden entirely:
```ruby
Rails.application.message_verifiers[:foo] = ActiveSupport::MessageVerifier.new(other_secret)
```
For parity, this commit also adds a `MessageEncryptors` factory class,
which fulfills the same role for `MessageEncryptor` instances.
Previously, generating a plugin inside an application would throw an
error when trying to create a dummy_app due to the generator trying to
reuse the application's name.
This is fixed by extracting the logic used to determine the source of an
application's name, and then only using the existing name as the source
for the app:update task.
Even if tests are "skipped" by `Minitest::Assertions#skip`
`ensure` is executed because tests methods are Ruby methods.
Adding conditions outside of the test methods, entire test methods are
executed only when they are necessary.
`system(.., exception: true)` gives you more information on how the
command failed, e.g.
```
bin/setup:8:in `system': Command failed with exit 1: bundle install (RuntimeError)
bin/setup:8:in `system': No such file or directory - bundle (Errno::ENOENT)
```
In f36c261a44 support for the ssl-mode option was added for MySQL when
using the dbconsole command and MySQLDatabaseTasks.
However, the mysql2 gem uses `ssl_mode` instead of `sslmode`:
ba4d46551d/lib/mysql2/client.rb (L51)
As `ssl_mode` is what should be used in the database.yml configuration
for MySQL we should use it as well for the dbconsole command and
MySQLDatabaseTasks.
Co-authored-by: Chris Gunther <chris@room118solutions.com>
* Add puma app server to Gemfile in order to start test/dummy
* Fix Could not find server '' error for plugin dummy apps
by adding a web server to plugin Gemfile.
In order to run the test/dummy application we add
puma (web_server_gemfile_entry as defined in
`railties/lib/rails/generators/app_base.rb`)
to the engine Gemfile.
* No more need to add puma to Gemfile.
Back to the previous version of the engine guide as
the web server is now present in Gemfile after
`rails plugin new`
[Donapieppo + Rafael Mendonça França]
According to the MySQL documentation, database connections default to
ssl-mode=PREFERRED. But PREFERRED doesn't verify the server's identity:
The default setting, --ssl-mode=PREFERRED, produces an encrypted
connection if the other default settings are unchanged. However, to
help prevent sophisticated man-in-the-middle attacks, it is
important for the client to verify the server’s identity. The
settings --ssl-mode=VERIFY_CA and --ssl-mode=VERIFY_IDENTITY are a
better choice than the default setting to help prevent this type of
attack. VERIFY_CA makes the client check that the server’s
certificate is valid. VERIFY_IDENTITY makes the client check that
the server’s certificate is valid, and also makes the client check
that the host name the client is using matches the identity in the
server’s certificate.
https://dev.mysql.com/doc/refman/8.0/en/using-encrypted-connections.html
However both the Rails::DBConsole command and the MySQLDatabaseTasks
ignore the ssl-mode option, making the connection fallback to PREFERRED.
Adding ssl-mode to the forwarded options makes sure the expected mode is
passed to the connection.
Rubinius has not been maintained since May 2020 and based on the
discussion at https://github.com/rails/rails/pull/44984 ,
I think we can remove Rubinius specific code from Rails.
The --edge option points or the latest stable branch of a release of
rails (eg. rails _7.1_ new my_app --edge would point to 7-1-stable).
When using a prerelease of Rails, main is used instead.
Followup to #45908 to match the same behavior as SchemaMigration
Previously, InternalMetadata inherited from ActiveRecord::Base. This is
problematic for multiple databases and resulted in building the code in
AbstractAdapter that was previously there. Rather than hacking around
the fact that InternalMetadata inherits from Base, this PR makes
InternalMetadata an independent object. Then each connection can get it's
own InternalMetadata object. This change required defining the methods
that InternalMetadata was depending on ActiveRecord::Base for (ex
create!). I reimplemented only the methods called by the framework as
this class is no-doc's so it doesn't need to implement anything beyond
that. Now each connection gets it's own InternalMetadata object which
stores the connection.
This change also required adding a NullInternalMetadata class for cases
when we don't have a connection yet but still need to copy migrations
from the MigrationContext. Ultimately I think this is a little weird -
we need to do so much work to pick up a set of files? Maybe something to
explore in the future.
Aside from removing the hack we added back in #36439 this change will
enable my work to stop clobbering and depending directly on
Base.connection in the rake tasks. While working on this I discovered
that we always have a ActiveRecord::InternalMetadata because the
connection is always on Base in the rake tasks. This will free us up
to do less hacky stuff in the migrations and tasks.
Both schema migration and internal metadata are blockers to removing
`Base.connection` and `Base.establish_connection` from rake tasks, work
that is required to drop the reliance on `Base.connection` which will
enable more robust (and correct) sharding behavior in Rails..
* Corrected hyperlink address by removing the unneccesary bracket
* Update railties/lib/rails/generators/rails/app/app_generator.rb
This correction should work regardless of which hyperlink parser or terminal being used.
Co-authored-by: Rafael Mendonça França <rafael@franca.dev>
Co-authored-by: Rafael Mendonça França <rafael@franca.dev>
When you're looking for annotations, it's possible (albeit extremely unlikely) for it to pick up things that aren't comments (see the added test for an example). If we instead use a parser like ripper, we can filter down to just the comments and only try to extract the annotations from the source file's comments.
Recent Bundler version have fixed version matching of the `ruby` Gemfile
DSL and now prereleases like `Ruby 3.2.0.preview2` will no longer match
Gemfiles specifying exact constraints like `ruby "3.2.0"`.
For the default Gemfile to support prerelease rubies, it needs to use
an exact constraint that considers prereleases, for example, with
`Gem.ruby_version`. Alternatively, the requirement could be relaxed, but
I believe the intention here is to restrict the Gemfile to the exact
Ruby version generating it.
In 7690290, the filter was not finding the end of the methods defined
using the `test do` syntax. This would cause more than 1 test to be
selected depending on the line number passed as argument.
The previous test wasn't failing because the two tests asked to run
where one after the other and the filter, even broken would only
run those two tests. By changing the test definition order we trigger
the bug introduced by that commit.
Previously, SchemaMigration inherited from ActiveRecord::Base. This is
problematic for multiple databases and resulted in building the code in
AbstractAdapter that was previously there. Rather than hacking around
the fact that SchemaMigration inherits from Base, this PR makes
SchemaMigration an independent object. Then each connection can get it's
own SchemaMigration object. This change required defining the methods
that SchemaMigration was depending on ActiveRecord::Base for (ex
create!). I reimplemented only the methods called by the framework as
this class is no-doc's so it doesn't need to implement anything beyond
that. Now each connection gets it's own SchemaMigration object which
stores the connection. I also decided to update the method names (create
-> create_version, delete_by -> delete_version, delete_all ->
delete_all_versions) to be more explicit.
This change also required adding a NullSchemaMigraiton class for cases
when we don't have a connection yet but still need to copy migrations
from the MigrationContext. Ultimately I think this is a little weird -
we need to do so much work to pick up a set of files? Maybe something to
explore in the future.
Aside from removing the hack we added back in #36439 this change will
enable my work to stop clobbering and depending directly on
Base.connection in the rake tasks. While working on this I discovered
that we always have a `ActiveRecord::SchemaMigration` because the
connection is always on `Base` in the rake tasks. This will free us up
to do less hacky stuff in the migrations and tasks.
This PR enables `Minitest/AssertRaisesWithRegexpArgument` cop
and it suppresses the new warning below.
```console
% bundle exec rubocop
(snip)
Offenses:
activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb:111:9: C: Minitest/AssertRaisesWithRegexpArgument:
Do not pass regular expression literals to assert_raises. Test the resulting exception.
assert_raises(ActiveRecord::StatementInvalid, /TypeError/) do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb:628:9: C: Minitest/AssertRaisesWithRegexpArgument:
Do not pass regular expression literals to assert_raises. Test the resulting exception.
assert_raises(ActiveRecord::StatementInvalid, /SQLite3::ReadOnlyException/) do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
railties/test/application/rake/multi_dbs_test.rb:307:13: C: Minitest/AssertRaisesWithRegexpArgument:
Do not pass regular expression literals to assert_raises. Test the resulting exception.
assert_raises RuntimeError, /You're using a multiple database application/ do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
railties/test/application/rake/multi_dbs_test.rb:311:13: C: Minitest/AssertRaisesWithRegexpArgument:
Do not pass regular expression literals to assert_raises. Test the resulting exception.
assert_raises RuntimeError, /You're using a multiple database application/ do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
railties/test/application/rake/multi_dbs_test.rb:336:13: C: Minitest/AssertRaisesWithRegexpArgument:
Do not pass regular expression literals to assert_raises. Test the resulting exception.
assert_raises RuntimeError, /You're using a multiple database application/ do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
railties/test/application/rake/multi_dbs_test.rb:361:13: C: Minitest/AssertRaisesWithRegexpArgument:
Do not pass regular expression literals to assert_raises. Test the resulting exception.
assert_raises RuntimeError, /You're using a multiple database application/ do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
The last argument of `assert_raises` is a custom message string to help explain failures.
So, it's not the argument that `exception.message` is compared to.
`assert_raises` returns a raised exception and can be used to match against a regular expression.
And it updates the dependency version of rubocop-minitest in the Gemfile.
Because `Minitest/AssertRaisesWithRegexpArgument` cop was introduced in minitest 0.22.
https://github.com/rubocop/rubocop-minitest/releases/tag/v0.22.0
"Indicates when to generate api" doesn't make sense:
```
$ bin/rails g scaffold | grep api
[--api], [--no-api] # Indicates when to generate api
```
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
The `method_source` gem was added in
https://github.com/rails/rails/pull/19216. It was used to determine the
last line number of a given test method to support running tests by line
number. But this is not something that requires an external dependency:
Ripper can do this easily, and it has the added advantage of not using
repeated calls to `eval` to do it.
Drop `method_source` and replace it with a simple handler for Ripper's
`on_def` parser event.
I don't believe that there are any mainstream rubies at this point that
can run Rails and don't support Ripper but correct me if I'm wrong.
This change incorporates to Rails a feature called error_highlight that
has been available since Ruby 3.1. This allow Rails' error report screen
to display the fine-grained location where an error occurred (not only a
line number but also beginning and end column numbers of the code
fragment).
For ErrorHighlight, see https://bugs.ruby-lang.org/issues/17930 in
detail.
To use error_highlight, ExceptionWrapper now prefers
`Exception#backtrace_locations` (since Ruby 2.1), which returns an array
of `Thread::Backtrace::Location`s, instead of `Exception#backtrace`.
This is because error_highlight requires `Thread::Backtrace::Location`
to locate the column where an error was raised.
Co-Authored-By: John Hawthorn <john@hawthorn.email>
Co-Authored-By: Jean Boussier <jean.boussier@gmail.com>
This updates The Rails runner command to give a more helpful error
message when given a path as input but the file does not exist.
Instead of the cryptic "undefined local variable or method" the user is
told that the file could not be found.
I've gone for the simplest approach I could think of to identify when
the input is likely a file path: it ends with `".rb"`. This isn't a
perfect approach – there's nothing stopping someone passing a script
without an extension, and it's also possible to have valid Ruby syntax
that ends in `".rb" – but it does feel "good enough" and will make the
Rails runner slightly more user-friendly for those working with file
paths without negatively impacting those that are passing in Ruby
code.
Ref: https://github.com/rails/rails/pull/43550
If `executor_around_test_case` is enabled, all hooks must be
reentrant. However `allow_concurrency = false` register a
`MutexHook` that isn't reentrant.
So this commit replace it by a `Monitor` which does allow
reentrancy.
I deprecated `legacy_connection_handling` setter in 7.0 but then removed
it without setting it to false by default upgraded apps might have this
set to false in their config and still be getting an error. This
confusing behavior came up with one of our apps at work.
To make it less confusing I've redefined `legacy_connection_handling`
setter and am raising an argument error if called. I didn't redefine the
getter because that shouldn't be in a config, it's not useful in that
context.