diff --git a/CHANGELOG.md b/CHANGELOG.md
index 176f115ddf..fb96f43400 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@
## master (unreleased)
+## 2.27.0 (2024-10-26)
+
### Bug fixes
* [#1377](https://github.com/rubocop/rubocop-rails/issues/1377): Fix an error for `Rails/EnumSyntax` when positional arguments are used and options are not passed as keyword arguments. ([@koic][])
diff --git a/docs/antora.yml b/docs/antora.yml
index 9e0ff48acb..f011548566 100644
--- a/docs/antora.yml
+++ b/docs/antora.yml
@@ -2,6 +2,6 @@ name: rubocop-rails
title: RuboCop Rails
# We always provide version without patch here (e.g. 1.1),
# as patch versions should not appear in the docs.
-version: ~
+version: '2.27'
nav:
- modules/ROOT/nav.adoc
diff --git a/docs/modules/ROOT/pages/cops_rails.adoc b/docs/modules/ROOT/pages/cops_rails.adoc
index b9892b58eb..af8158a478 100644
--- a/docs/modules/ROOT/pages/cops_rails.adoc
+++ b/docs/modules/ROOT/pages/cops_rails.adoc
@@ -6,6 +6,7 @@
= Rails
+[#railsactioncontrollerflashbeforerender]
== Rails/ActionControllerFlashBeforeRender
|===
@@ -21,11 +22,13 @@
Using `flash` assignment before `render` in Rails controllers will persist the message for too long.
Check https://guides.rubyonrails.org/action_controller_overview.html#flash-now
+[#safety-railsactioncontrollerflashbeforerender]
=== Safety
This cop's autocorrection is unsafe because it replaces `flash` by `flash.now`.
Even though it is usually a mistake, it might be used intentionally.
+[#examples-railsactioncontrollerflashbeforerender]
=== Examples
[source,ruby]
@@ -47,8 +50,11 @@ class HomeController < ApplicationController
end
----
+[#railsactioncontrollertestcase]
== Rails/ActionControllerTestCase
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -63,11 +69,13 @@ Using `ActionController::TestCase` is discouraged and should be replaced by
`ActionDispatch::IntegrationTest`. Controller tests are too close to the
internals of a controller whereas integration tests mimic the browser/user.
+[#safety-railsactioncontrollertestcase]
=== Safety
This cop's autocorrection is unsafe because the API of each test case class is different.
Make sure to update each test of your controller test cases after changing the superclass.
+[#examples-railsactioncontrollertestcase]
=== Examples
[source,ruby]
@@ -81,6 +89,7 @@ class MyControllerTest < ActionDispatch::IntegrationTest
end
----
+[#configurable-attributes-railsactioncontrollertestcase]
=== Configurable attributes
|===
@@ -91,11 +100,13 @@ end
| Array
|===
+[#references-railsactioncontrollertestcase]
=== References
* https://rails.rubystyle.guide/#integration-testing
* https://api.rubyonrails.org/classes/ActionController/TestCase.html
+[#railsactionfilter]
== Rails/ActionFilter
|===
@@ -116,8 +127,10 @@ something_filter methods or the newer something_action methods.
IMPORTANT: This cop is deprecated. Because the `*_filter` methods were removed in Rails 4.2,
and that Rails version is no longer supported by RuboCop Rails. This cop will be removed in RuboCop Rails 3.0.
+[#examples-railsactionfilter]
=== Examples
+[#enforcedstyle_-action-_default_-railsactionfilter]
==== EnforcedStyle: action (default)
[source,ruby]
@@ -133,6 +146,7 @@ append_around_action :do_stuff
skip_after_action :do_stuff
----
+[#enforcedstyle_-filter-railsactionfilter]
==== EnforcedStyle: filter
[source,ruby]
@@ -148,6 +162,7 @@ append_around_filter :do_stuff
skip_after_filter :do_stuff
----
+[#configurable-attributes-railsactionfilter]
=== Configurable attributes
|===
@@ -162,6 +177,7 @@ skip_after_filter :do_stuff
| Array
|===
+[#railsactionorder]
== Rails/ActionOrder
|===
@@ -193,6 +209,7 @@ defined before actions not specified.
- destroy
----
+[#examples-railsactionorder]
=== Examples
[source,ruby]
@@ -208,6 +225,7 @@ def show; end
def destroy; end
----
+[#configurable-attributes-railsactionorder]
=== Configurable attributes
|===
@@ -222,6 +240,7 @@ def destroy; end
| Array
|===
+[#railsactiverecordaliases]
== Rails/ActiveRecordAliases
|===
@@ -237,11 +256,13 @@ def destroy; end
Checks that ActiveRecord aliases are not used. The direct method names
are more clear and easier to read.
+[#safety-railsactiverecordaliases]
=== Safety
This cop is unsafe because custom `update_attributes` method call was changed to
`update` but the method name remained same in the method definition.
+[#examples-railsactiverecordaliases]
=== Examples
[source,ruby]
@@ -253,6 +274,7 @@ book.update_attributes!(author: 'Alice')
book.update!(author: 'Alice')
----
+[#railsactiverecordcallbacksorder]
== Rails/ActiveRecordCallbacksOrder
|===
@@ -268,6 +290,7 @@ book.update!(author: 'Alice')
Checks that Active Record callbacks are declared
in the order in which they will be executed.
+[#examples-railsactiverecordcallbacksorder]
=== Examples
[source,ruby]
@@ -285,6 +308,7 @@ class Person < ApplicationRecord
end
----
+[#configurable-attributes-railsactiverecordcallbacksorder]
=== Configurable attributes
|===
@@ -295,10 +319,12 @@ end
| Array
|===
+[#references-railsactiverecordcallbacksorder]
=== References
* https://rails.rubystyle.guide/#callbacks-order
+[#railsactiverecordoverride]
== Rails/ActiveRecordOverride
|===
@@ -314,6 +340,7 @@ end
Checks for overriding built-in Active Record methods instead of using
callbacks.
+[#examples-railsactiverecordoverride]
=== Examples
[source,ruby]
@@ -336,6 +363,7 @@ class Book < ApplicationRecord
end
----
+[#configurable-attributes-railsactiverecordoverride]
=== Configurable attributes
|===
@@ -350,6 +378,7 @@ end
| Array
|===
+[#railsactivesupportaliases]
== Rails/ActiveSupportAliases
|===
@@ -365,6 +394,7 @@ end
Checks that ActiveSupport aliases to core ruby methods
are not used.
+[#examples-railsactivesupportaliases]
=== Examples
[source,ruby]
@@ -382,6 +412,7 @@ are not used.
[1, 2, 'a'].prepend('b')
----
+[#railsactivesupportonload]
== Rails/ActiveSupportOnLoad
|===
@@ -397,11 +428,13 @@ are not used.
Checks for Rails framework classes that are patched directly instead of using Active Support load hooks. Direct
patching forcibly loads the framework referenced, using hooks defers loading until it's actually needed.
+[#safety-railsactivesupportonload]
=== Safety
While using lazy load hooks is recommended, it changes the order in which is code is loaded and may reveal
load order dependency bugs.
+[#examples-railsactivesupportonload]
=== Examples
[source,ruby]
@@ -413,11 +446,13 @@ ActiveRecord::Base.include(MyClass)
ActiveSupport.on_load(:active_record) { include MyClass }
----
+[#references-railsactivesupportonload]
=== References
* https://api.rubyonrails.org/classes/ActiveSupport/LazyLoadHooks.html
* https://guides.rubyonrails.org/engines.html#available-load-hooks
+[#railsaddcolumnindex]
== Rails/AddColumnIndex
|===
@@ -435,6 +470,7 @@ key. `add_column` does not accept `index`, but also does not raise an
error for extra keys, so it is possible to mistakenly add the key without
realizing it will not actually add an index.
+[#examples-railsaddcolumnindex]
=== Examples
[source,ruby]
@@ -447,6 +483,7 @@ add_column :table, :column, :integer
add_index :table, :column
----
+[#configurable-attributes-railsaddcolumnindex]
=== Configurable attributes
|===
@@ -457,6 +494,7 @@ add_index :table, :column
| Array
|===
+[#railsaftercommitoverride]
== Rails/AfterCommitOverride
|===
@@ -473,6 +511,7 @@ Enforces that there is only one call to `after_commit`
(and its aliases - `after_create_commit`, `after_update_commit`,
and `after_destroy_commit`) with the same callback name per model.
+[#examples-railsaftercommitoverride]
=== Examples
[source,ruby]
@@ -501,6 +540,7 @@ after_create_commit :log_create_action
after_update_commit :log_update_action
----
+[#railsapplicationcontroller]
== Rails/ApplicationController
|===
@@ -515,11 +555,13 @@ after_update_commit :log_update_action
Checks that controllers subclass `ApplicationController`.
+[#safety-railsapplicationcontroller]
=== Safety
This cop's autocorrection is unsafe because it may let the logic from `ApplicationController`
sneak into a controller that is not purposed to inherit logic common among other controllers.
+[#examples-railsapplicationcontroller]
=== Examples
[source,ruby]
@@ -535,8 +577,11 @@ class MyController < ActionController::Base
end
----
+[#railsapplicationjob]
== Rails/ApplicationJob
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -549,11 +594,13 @@ end
Checks that jobs subclass `ApplicationJob` with Rails 5.0.
+[#safety-railsapplicationjob]
=== Safety
This cop's autocorrection is unsafe because it may let the logic from `ApplicationJob`
sneak into a job that is not purposed to inherit logic common among other jobs.
+[#examples-railsapplicationjob]
=== Examples
[source,ruby]
@@ -569,8 +616,11 @@ class Rails4Job < ActiveJob::Base
end
----
+[#railsapplicationmailer]
== Rails/ApplicationMailer
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -583,11 +633,13 @@ end
Checks that mailers subclass `ApplicationMailer` with Rails 5.0.
+[#safety-railsapplicationmailer]
=== Safety
This cop's autocorrection is unsafe because it may let the logic from `ApplicationMailer`
sneak into a mailer that is not purposed to inherit logic common among other mailers.
+[#examples-railsapplicationmailer]
=== Examples
[source,ruby]
@@ -603,8 +655,11 @@ class MyMailer < ActionMailer::Base
end
----
+[#railsapplicationrecord]
== Rails/ApplicationRecord
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -621,12 +676,14 @@ It is a common practice to define models inside migrations in order to retain fo
compatibility by avoiding loading any application code. And so migration files are excluded
by default for this cop.
+[#safety-railsapplicationrecord]
=== Safety
This cop's autocorrection is unsafe because it may let the logic from `ApplicationRecord`
sneak into an Active Record model that is not purposed to inherit logic common among other
Active Record models.
+[#examples-railsapplicationrecord]
=== Examples
[source,ruby]
@@ -642,6 +699,7 @@ class Rails4Model < ActiveRecord::Base
end
----
+[#configurable-attributes-railsapplicationrecord]
=== Configurable attributes
|===
@@ -652,6 +710,7 @@ end
| Array
|===
+[#railsarelstar]
== Rails/ArelStar
|===
@@ -671,6 +730,7 @@ quoted asterisk (e.g. `my_model`.`*`). This causes the
database to look for a column named `*` (or `"*"`) as opposed
to expanding the column list as one would likely expect.
+[#safety-railsarelstar]
=== Safety
This cop's autocorrection is unsafe because it turns a quoted `*` into
@@ -678,6 +738,7 @@ an SQL `*`, unquoted. `*` is a valid column name in certain databases
supported by Rails, and even though it is usually a mistake,
it might denote legitimate access to a column named `*`.
+[#examples-railsarelstar]
=== Examples
[source,ruby]
@@ -689,6 +750,7 @@ MyTable.arel_table["*"]
MyTable.arel_table[Arel.star]
----
+[#railsassertnot]
== Rails/AssertNot
|===
@@ -703,6 +765,7 @@ MyTable.arel_table[Arel.star]
Use `assert_not` instead of `assert !`.
+[#examples-railsassertnot]
=== Examples
[source,ruby]
@@ -714,6 +777,7 @@ assert !x
assert_not x
----
+[#configurable-attributes-railsassertnot]
=== Configurable attributes
|===
@@ -724,6 +788,7 @@ assert_not x
| Array
|===
+[#railsattributedefaultblockvalue]
== Rails/AttributeDefaultBlockValue
|===
@@ -741,6 +806,7 @@ which value is an array, string literal or method call without a block.
It will accept all other values, such as string, symbol, integer and float literals
as well as constants.
+[#examples-railsattributedefaultblockvalue]
=== Examples
[source,ruby]
@@ -797,6 +863,7 @@ class User < ApplicationRecord
end
----
+[#configurable-attributes-railsattributedefaultblockvalue]
=== Configurable attributes
|===
@@ -807,8 +874,11 @@ end
| Array
|===
+[#railsbelongsto]
== Rails/BelongsTo
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -843,6 +913,7 @@ superfluous `optional: false`). Therefore, in the cases we're using
`required: true`, we'll simply invert it to `optional: false` and the
user can remove depending on their defaults.
+[#examples-railsbelongsto]
=== Examples
[source,ruby]
@@ -868,11 +939,13 @@ class Post < ApplicationRecord
end
----
+[#references-railsbelongsto]
=== References
* https://guides.rubyonrails.org/5_0_release_notes.html
* https://github.com/rails/rails/pull/18937
+[#railsblank]
== Rails/Blank
|===
@@ -893,14 +966,17 @@ The configuration of `NotPresent` will not produce an offense in the
context of `unless else` if `Style/UnlessElse` is enabled. This is
to prevent interference between the autocorrection of the two cops.
+[#safety-railsblank]
=== Safety
This cop is unsafe autocorrection, because `' '.empty?` returns false,
but `' '.blank?` returns true. Therefore, autocorrection is not compatible
if the receiver is a non-empty blank string, tab, or newline meta characters.
+[#examples-railsblank]
=== Examples
+[#nilorempty_-true-_default_-railsblank]
==== NilOrEmpty: true (default)
[source,ruby]
@@ -915,6 +991,7 @@ foo == nil || foo.empty?
foo.blank?
----
+[#notpresent_-true-_default_-railsblank]
==== NotPresent: true (default)
[source,ruby]
@@ -928,6 +1005,7 @@ foo.blank?
foo.blank?
----
+[#unlesspresent_-true-_default_-railsblank]
==== UnlessPresent: true (default)
[source,ruby]
@@ -956,6 +1034,7 @@ def blank?
end
----
+[#configurable-attributes-railsblank]
=== Configurable attributes
|===
@@ -974,6 +1053,7 @@ end
| Boolean
|===
+[#railsbulkchangetable]
== Rails/BulkChangeTable
|===
@@ -1000,6 +1080,7 @@ when the `Database` option is not set.
If the adapter is not `mysql2`, `trilogy`, `postgresql`, or `postgis`,
this Cop ignores offenses.
+[#examples-railsbulkchangetable]
=== Examples
[source,ruby]
@@ -1053,6 +1134,7 @@ def change
end
----
+[#configurable-attributes-railsbulkchangetable]
=== Configurable attributes
|===
@@ -1067,13 +1149,17 @@ end
| Array
|===
+[#references-railsbulkchangetable]
=== References
* https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-change_table
* https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
+[#railscompactblank]
== Rails/CompactBlank
+NOTE: Required Rails version: 6.1
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -1086,6 +1172,7 @@ end
Checks if collection can be blank-compacted with `compact_blank`.
+[#safety-railscompactblank]
=== Safety
It is unsafe by default because false positives may occur in the
@@ -1100,6 +1187,7 @@ And `compact_blank!` has different implementations for `Array`, `Hash`, and
`Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`.
If the cop makes a mistake, autocorrected code may get unexpected behavior.
+[#examples-railscompactblank]
=== Examples
[source,ruby]
@@ -1125,8 +1213,11 @@ collection.keep_if { |_k, v| v.present? } # Same behavior as `Array#compact_blan
collection.compact_blank!
----
+[#railscontenttag]
== Rails/ContentTag
+NOTE: Required Rails version: 5.1
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -1143,6 +1234,7 @@ NOTE: Allow `tag` when the first argument is a variable because
`tag(name)` is simpler rather than `tag.public_send(name)`.
And this cop will be renamed to something like `LegacyTag` in the future. (e.g. RuboCop Rails 3.0)
+[#examples-railscontenttag]
=== Examples
[source,ruby]
@@ -1157,6 +1249,7 @@ tag.br(class: 'classname')
tag(name, class: 'classname')
----
+[#configurable-attributes-railscontenttag]
=== Configurable attributes
|===
@@ -1167,12 +1260,14 @@ tag(name, class: 'classname')
| Array
|===
+[#references-railscontenttag]
=== References
* https://github.com/rubocop/rubocop-rails/issues/260
* https://github.com/rails/rails/issues/25195
* https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag
+[#railscreatetablewithtimestamps]
== Rails/CreateTableWithTimestamps
|===
@@ -1191,6 +1286,7 @@ In many cases, timestamps are useful information and should be added.
NOTE: Allow `timestamps` not written when `id: false` because this emphasizes respecting
user's editing intentions.
+[#examples-railscreatetablewithtimestamps]
=== Examples
[source,ruby]
@@ -1235,6 +1331,7 @@ create_table :users, articles, id: false do |t|
end
----
+[#configurable-attributes-railscreatetablewithtimestamps]
=== Configurable attributes
|===
@@ -1249,6 +1346,7 @@ end
| Array
|===
+[#railsdangerouscolumnnames]
== Rails/DangerousColumnNames
|===
@@ -1265,6 +1363,7 @@ Avoid dangerous column names.
Some column names are considered dangerous because they would overwrite methods already defined.
+[#examples-railsdangerouscolumnnames]
=== Examples
[source,ruby]
@@ -1276,6 +1375,7 @@ add_column :users, :save
add_column :users, :saved
----
+[#configurable-attributes-railsdangerouscolumnnames]
=== Configurable attributes
|===
@@ -1290,6 +1390,7 @@ add_column :users, :saved
| Array
|===
+[#railsdate]
== Rails/Date
|===
@@ -1321,12 +1422,15 @@ When `EnforcedStyle` is `flexible` then only `Date.today` is prohibited.
And you can set a warning for `to_time` with `AllowToTime: false`.
`AllowToTime` is `true` by default to prevent false positive on `DateTime` object.
+[#safety-railsdate]
=== Safety
This cop's autocorrection is unsafe because it may change handling time.
+[#examples-railsdate]
=== Examples
+[#enforcedstyle_-flexible-_default_-railsdate]
==== EnforcedStyle: flexible (default)
[source,ruby]
@@ -1342,6 +1446,7 @@ Date.yesterday
date.in_time_zone
----
+[#enforcedstyle_-strict-railsdate]
==== EnforcedStyle: strict
[source,ruby]
@@ -1356,6 +1461,7 @@ Time.zone.today
Time.zone.today - 1.day
----
+[#allowtotime_-true-_default_-railsdate]
==== AllowToTime: true (default)
[source,ruby]
@@ -1364,6 +1470,7 @@ Time.zone.today - 1.day
date.to_time
----
+[#allowtotime_-false-railsdate]
==== AllowToTime: false
[source,ruby]
@@ -1372,6 +1479,7 @@ date.to_time
date.to_time
----
+[#configurable-attributes-railsdate]
=== Configurable attributes
|===
@@ -1386,6 +1494,7 @@ date.to_time
| Boolean
|===
+[#railsdefaultscope]
== Rails/DefaultScope
|===
@@ -1400,6 +1509,7 @@ date.to_time
Looks for uses of `default_scope`.
+[#examples-railsdefaultscope]
=== Examples
[source,ruby]
@@ -1421,6 +1531,7 @@ def self.published
end
----
+[#railsdelegate]
== Rails/Delegate
|===
@@ -1445,6 +1556,7 @@ using the target object as a prefix of the method name
without using the `delegate` method will be a violation.
When set to `false`, this case is legal.
+[#examples-railsdelegate]
=== Examples
[source,ruby]
@@ -1477,6 +1589,7 @@ def bar
end
----
+[#enforceforprefixed_-true-_default_-railsdelegate]
==== EnforceForPrefixed: true (default)
[source,ruby]
@@ -1490,6 +1603,7 @@ end
delegate :bar, to: :foo, prefix: true
----
+[#enforceforprefixed_-false-railsdelegate]
==== EnforceForPrefixed: false
[source,ruby]
@@ -1503,6 +1617,7 @@ end
delegate :bar, to: :foo, prefix: true
----
+[#configurable-attributes-railsdelegate]
=== Configurable attributes
|===
@@ -1513,6 +1628,7 @@ delegate :bar, to: :foo, prefix: true
| Boolean
|===
+[#railsdelegateallowblank]
== Rails/DelegateAllowBlank
|===
@@ -1529,6 +1645,7 @@ Looks for delegations that pass :allow_blank as an option
instead of :allow_nil. :allow_blank is not a valid option to pass
to ActiveSupport#delegate.
+[#examples-railsdelegateallowblank]
=== Examples
[source,ruby]
@@ -1540,6 +1657,7 @@ delegate :foo, to: :bar, allow_blank: true
delegate :foo, to: :bar, allow_nil: true
----
+[#railsdeprecatedactivemodelerrorsmethods]
== Rails/DeprecatedActiveModelErrorsMethods
|===
@@ -1555,12 +1673,14 @@ delegate :foo, to: :bar, allow_nil: true
Checks direct manipulation of ActiveModel#errors as hash.
These operations are deprecated in Rails 6.1 and will not work in Rails 7.
+[#safety-railsdeprecatedactivemodelerrorsmethods]
=== Safety
This cop is unsafe because it can report `errors` manipulation on non-ActiveModel,
which is obviously valid.
The cop has no way of knowing whether a variable is an ActiveModel or not.
+[#examples-railsdeprecatedactivemodelerrorsmethods]
=== Examples
[source,ruby]
@@ -1586,6 +1706,7 @@ user.errors.keys.include?(:attr)
user.errors.attribute_names.include?(:attr)
----
+[#configurable-attributes-railsdeprecatedactivemodelerrorsmethods]
=== Configurable attributes
|===
@@ -1596,6 +1717,7 @@ user.errors.attribute_names.include?(:attr)
| String
|===
+[#railsdotseparatedkeys]
== Rails/DotSeparatedKeys
|===
@@ -1612,6 +1734,7 @@ Enforces the use of dot-separated locale keys instead of specifying the `:scope`
with an array or a single symbol in `I18n` translation methods.
Dot-separated notation is easier to read and trace the hierarchy.
+[#examples-railsdotseparatedkeys]
=== Examples
[source,ruby]
@@ -1625,10 +1748,12 @@ I18n.t 'activerecord.errors.messages.record_invalid'
I18n.t :record_invalid, scope: 'activerecord.errors.messages'
----
+[#references-railsdotseparatedkeys]
=== References
* https://rails.rubystyle.guide/#dot-separated-keys
+[#railsduplicateassociation]
== Rails/DuplicateAssociation
|===
@@ -1647,6 +1772,7 @@ When an association is defined multiple times on a model, Active Record override
previously defined association with the new one. Because of this, this cop's autocorrection
simply keeps the last of any duplicates and discards the rest.
+[#examples-railsduplicateassociation]
=== Examples
[source,ruby]
@@ -1670,6 +1796,7 @@ has_many :bar, class_name: 'Foo'
has_one :foo
----
+[#configurable-attributes-railsduplicateassociation]
=== Configurable attributes
|===
@@ -1680,6 +1807,7 @@ has_one :foo
| String
|===
+[#railsduplicatescope]
== Rails/DuplicateScope
|===
@@ -1695,6 +1823,7 @@ has_one :foo
Checks for multiple scopes in a model that have the same `where` clause. This
often means you copy/pasted a scope, updated the name, and forgot to change the condition.
+[#examples-railsduplicatescope]
=== Examples
[source,ruby]
@@ -1708,6 +1837,7 @@ scope :visible, -> { where(visible: true) }
scope :hidden, -> { where(visible: false) }
----
+[#configurable-attributes-railsduplicatescope]
=== Configurable attributes
|===
@@ -1718,6 +1848,7 @@ scope :hidden, -> { where(visible: false) }
| String
|===
+[#railsdurationarithmetic]
== Rails/DurationArithmetic
|===
@@ -1732,6 +1863,7 @@ scope :hidden, -> { where(visible: false) }
Checks if a duration is added to or subtracted from `Time.current`.
+[#examples-railsdurationarithmetic]
=== Examples
[source,ruby]
@@ -1750,10 +1882,12 @@ created_at - 1.minute
2.days.from_now
----
+[#references-railsdurationarithmetic]
=== References
* https://rails.rubystyle.guide#duration-arithmetic
+[#railsdynamicfindby]
== Rails/DynamicFindBy
|===
@@ -1770,11 +1904,13 @@ Checks dynamic `find_by_*` methods.
Use `find_by` instead of dynamic method.
See. https://rails.rubystyle.guide#find_by
+[#safety-railsdynamicfindby]
=== Safety
It is certainly unsafe when not configured properly, i.e. user-defined `find_by_xxx`
method is not added to cop's `AllowedMethods`.
+[#examples-railsdynamicfindby]
=== Examples
[source,ruby]
@@ -1790,6 +1926,7 @@ User.find_by(name: name, email: email)
User.find_by!(email: email)
----
+[#allowedmethods_-__find_by_sql__-_find_by_token_for__-_default_-railsdynamicfindby]
==== AllowedMethods: ['find_by_sql', 'find_by_token_for'] (default)
[source,ruby]
@@ -1803,6 +1940,7 @@ User.find_by_sql(users_sql)
User.find_by_token_for(:password_reset, token)
----
+[#allowedreceivers_-__gem__specification__-_page__-_default_-railsdynamicfindby]
==== AllowedReceivers: ['Gem::Specification', 'page'] (default)
[source,ruby]
@@ -1816,6 +1954,7 @@ Gem::Specification.find_by_name('backend').gem_dir
page.find_by_id('a_dom_id').click
----
+[#configurable-attributes-railsdynamicfindby]
=== Configurable attributes
|===
@@ -1834,10 +1973,12 @@ page.find_by_id('a_dom_id').click
| Array
|===
+[#references-railsdynamicfindby]
=== References
* https://rails.rubystyle.guide#find_by
+[#railseagerevaluationlogmessage]
== Rails/EagerEvaluationLogMessage
|===
@@ -1860,6 +2001,7 @@ arguments passed as method arguments. Passing a block to
`Rails.logger.debug` prevents costly evaluation of interpolated strings
when no output would be produced anyway.
+[#examples-railseagerevaluationlogmessage]
=== Examples
[source,ruby]
@@ -1871,10 +2013,12 @@ Rails.logger.debug "The time is #{Time.zone.now}."
Rails.logger.debug { "The time is #{Time.zone.now}." }
----
+[#references-railseagerevaluationlogmessage]
=== References
* https://guides.rubyonrails.org/debugging_rails_applications.html#impact-of-logs-on-performance
+[#railsenumhash]
== Rails/EnumHash
|===
@@ -1894,6 +2038,7 @@ position other than the last causes all previous
definitions to shift. Explicitly specifying the
value for each key prevents this from happening.
+[#examples-railsenumhash]
=== Examples
[source,ruby]
@@ -1911,6 +2056,7 @@ enum status: [:active, :archived]
enum status: { active: 0, archived: 1 }
----
+[#configurable-attributes-railsenumhash]
=== Configurable attributes
|===
@@ -1921,14 +2067,18 @@ enum status: { active: 0, archived: 1 }
| Array
|===
+[#references-railsenumhash]
=== References
* https://rails.rubystyle.guide#enums
+[#railsenumsyntax]
== Rails/EnumSyntax
NOTE: Required Ruby version: 3.0
+NOTE: Required Rails version: 7.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -1944,6 +2094,7 @@ Looks for enums written with keyword arguments syntax.
Defining enums with keyword arguments syntax is deprecated and will be removed in Rails 8.0.
Positional arguments should be used instead:
+[#examples-railsenumsyntax]
=== Examples
[source,ruby]
@@ -1955,6 +2106,7 @@ enum status: { active: 0, archived: 1 }, _prefix: true
enum :status, { active: 0, archived: 1 }, prefix: true
----
+[#configurable-attributes-railsenumsyntax]
=== Configurable attributes
|===
@@ -1969,6 +2121,7 @@ enum :status, { active: 0, archived: 1 }, prefix: true
| Array
|===
+[#railsenumuniqueness]
== Rails/EnumUniqueness
|===
@@ -1983,6 +2136,7 @@ enum :status, { active: 0, archived: 1 }, prefix: true
Looks for duplicate values in enum declarations.
+[#examples-railsenumuniqueness]
=== Examples
[source,ruby]
@@ -2012,6 +2166,7 @@ enum status: [:active, :archived, :active]
enum status: [:active, :archived]
----
+[#configurable-attributes-railsenumuniqueness]
=== Configurable attributes
|===
@@ -2022,8 +2177,11 @@ enum status: [:active, :archived]
| Array
|===
+[#railsenvlocal]
== Rails/EnvLocal
+NOTE: Required Rails version: 7.1
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -2037,6 +2195,7 @@ enum status: [:active, :archived]
Checks for usage of `Rails.env.development? || Rails.env.test?` which
can be replaced with `Rails.env.local?`, introduced in Rails 7.1.
+[#examples-railsenvlocal]
=== Examples
[source,ruby]
@@ -2048,6 +2207,7 @@ Rails.env.development? || Rails.env.test?
Rails.env.local?
----
+[#railsenvironmentcomparison]
== Rails/EnvironmentComparison
|===
@@ -2063,6 +2223,7 @@ Rails.env.local?
Checks that Rails.env is compared using `.production?`-like
methods instead of equality against a string or symbol.
+[#examples-railsenvironmentcomparison]
=== Examples
[source,ruby]
@@ -2077,6 +2238,7 @@ Rails.env == :test
Rails.env.production?
----
+[#railsenvironmentvariableaccess]
== Rails/EnvironmentVariableAccess
|===
@@ -2096,6 +2258,7 @@ time if the environment variables were loaded as part of initialization
and copied into the application's configuration or secrets. The cop can
be configured to allow either reads or writes if required.
+[#examples-railsenvironmentvariableaccess]
=== Examples
[source,ruby]
@@ -2107,6 +2270,7 @@ Rails.application.secrets.foo
Rails.application.config.foo = "bar"
----
+[#allowreads_-false-_default_-railsenvironmentvariableaccess]
==== AllowReads: false (default)
[source,ruby]
@@ -2116,6 +2280,7 @@ ENV["FOO"]
ENV.fetch("FOO")
----
+[#allowreads_-true-railsenvironmentvariableaccess]
==== AllowReads: true
[source,ruby]
@@ -2125,6 +2290,7 @@ ENV["FOO"]
ENV.fetch("FOO")
----
+[#allowwrites_-false-_default_-railsenvironmentvariableaccess]
==== AllowWrites: false (default)
[source,ruby]
@@ -2133,6 +2299,7 @@ ENV.fetch("FOO")
ENV["FOO"] = "bar"
----
+[#allowwrites_-true-railsenvironmentvariableaccess]
==== AllowWrites: true
[source,ruby]
@@ -2141,6 +2308,7 @@ ENV["FOO"] = "bar"
ENV["FOO"] = "bar"
----
+[#configurable-attributes-railsenvironmentvariableaccess]
=== Configurable attributes
|===
@@ -2163,6 +2331,7 @@ ENV["FOO"] = "bar"
| Boolean
|===
+[#railsexit]
== Rails/Exit
|===
@@ -2189,6 +2358,7 @@ is used.)
the program exiting, which could result in the code failing to run and
do its job.
+[#examples-railsexit]
=== Examples
[source,ruby]
@@ -2200,6 +2370,7 @@ exit(0)
raise 'a bad error has happened'
----
+[#configurable-attributes-railsexit]
=== Configurable attributes
|===
@@ -2214,8 +2385,11 @@ raise 'a bad error has happened'
| Array
|===
+[#railsexpandeddaterange]
== Rails/ExpandedDateRange
+NOTE: Required Rails version: 5.1
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -2229,6 +2403,7 @@ raise 'a bad error has happened'
Checks for expanded date range. It only compatible `..` range is targeted.
Incompatible `...` range is ignored.
+[#examples-railsexpandeddaterange]
=== Examples
[source,ruby]
@@ -2248,10 +2423,12 @@ date.all_quarter
date.all_year
----
+[#references-railsexpandeddaterange]
=== References
* https://rails.rubystyle.guide/#date-time-range
+[#railsfilepath]
== Rails/FilePath
|===
@@ -2267,8 +2444,10 @@ date.all_year
Identifies usages of file path joining process to use `Rails.root.join` clause.
It is used to add uniformity when joining paths.
+[#examples-railsfilepath]
=== Examples
+[#enforcedstyle_-slashes-_default_-railsfilepath]
==== EnforcedStyle: slashes (default)
[source,ruby]
@@ -2287,6 +2466,7 @@ File.join(Rails.root, 'app/models/goober')
Rails.root.join('app/models/goober').to_s
----
+[#enforcedstyle_-arguments-railsfilepath]
==== EnforcedStyle: arguments
[source,ruby]
@@ -2305,6 +2485,7 @@ File.join(Rails.root, 'app/models/goober')
Rails.root.join('app', 'models', 'goober').to_s
----
+[#configurable-attributes-railsfilepath]
=== Configurable attributes
|===
@@ -2315,6 +2496,7 @@ Rails.root.join('app', 'models', 'goober').to_s
| `slashes`, `arguments`
|===
+[#railsfindby]
== Rails/FindBy
|===
@@ -2334,6 +2516,7 @@ And `where(...).first` can return different results from `find_by`.
If you also want to detect `where.first`, you can set `IgnoreWhereFirst` to false.
+[#examples-railsfindby]
=== Examples
[source,ruby]
@@ -2345,6 +2528,7 @@ User.where(name: 'Bruce').take
User.find_by(name: 'Bruce')
----
+[#ignorewherefirst_-true-_default_-railsfindby]
==== IgnoreWhereFirst: true (default)
[source,ruby]
@@ -2353,6 +2537,7 @@ User.find_by(name: 'Bruce')
User.where(name: 'Bruce').first
----
+[#ignorewherefirst_-false-railsfindby]
==== IgnoreWhereFirst: false
[source,ruby]
@@ -2361,6 +2546,7 @@ User.where(name: 'Bruce').first
User.where(name: 'Bruce').first
----
+[#configurable-attributes-railsfindby]
=== Configurable attributes
|===
@@ -2371,10 +2557,12 @@ User.where(name: 'Bruce').first
| Boolean
|===
+[#references-railsfindby]
=== References
* https://rails.rubystyle.guide#find_by
+[#railsfindbyid]
== Rails/FindById
|===
@@ -2391,6 +2579,7 @@ Enforces that `ActiveRecord#find` is used instead of
`where.take!`, `find_by!`, and `find_by_id!` to retrieve a single record
by primary key when you expect it to be found.
+[#examples-railsfindbyid]
=== Examples
[source,ruby]
@@ -2404,10 +2593,12 @@ User.find_by!(id: id)
User.find(id)
----
+[#references-railsfindbyid]
=== References
* https://rails.rubystyle.guide/#find
+[#railsfindeach]
== Rails/FindEach
|===
@@ -2422,12 +2613,14 @@ User.find(id)
Identifies usages of `all.each` and change them to use `all.find_each` instead.
+[#safety-railsfindeach]
=== Safety
This cop is unsafe if the receiver object is not an Active Record object.
Also, `all.each` returns an `Array` instance and `all.find_each` returns nil,
so the return values are different.
+[#examples-railsfindeach]
=== Examples
[source,ruby]
@@ -2439,6 +2632,7 @@ User.all.each
User.all.find_each
----
+[#allowedmethods_-__order__-railsfindeach]
==== AllowedMethods: ['order']
[source,ruby]
@@ -2447,6 +2641,7 @@ User.all.find_each
User.order(:foo).each
----
+[#allowedpattern_-__order__-railsfindeach]
==== AllowedPattern: ['order']
[source,ruby]
@@ -2455,6 +2650,7 @@ User.order(:foo).each
User.order(:foo).each
----
+[#configurable-attributes-railsfindeach]
=== Configurable attributes
|===
@@ -2469,12 +2665,16 @@ User.order(:foo).each
| Array
|===
+[#references-railsfindeach]
=== References
* https://rails.rubystyle.guide#find-each
+[#railsfreezetime]
== Rails/FreezeTime
+NOTE: Required Rails version: 5.2
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -2488,12 +2688,14 @@ User.order(:foo).each
Identifies usages of `travel_to` with an argument of the current time and
change them to use `freeze_time` instead.
+[#safety-railsfreezetime]
=== Safety
This cop’s autocorrection is unsafe because `freeze_time` just delegates to
`travel_to` with a default `Time.now`, it is not strictly equivalent to `Time.now`
if the argument of `travel_to` is the current time considering time zone.
+[#examples-railsfreezetime]
=== Examples
[source,ruby]
@@ -2511,10 +2713,12 @@ travel_to(Time.current.to_time)
freeze_time
----
+[#references-railsfreezetime]
=== References
* https://rails.rubystyle.guide/#freeze-time
+[#railshasandbelongstomany]
== Rails/HasAndBelongsToMany
|===
@@ -2529,6 +2733,7 @@ freeze_time
Checks for the use of the has_and_belongs_to_many macro.
+[#examples-railshasandbelongstomany]
=== Examples
[source,ruby]
@@ -2540,6 +2745,7 @@ Checks for the use of the has_and_belongs_to_many macro.
# has_many :ingredients, through: :recipe_ingredients
----
+[#configurable-attributes-railshasandbelongstomany]
=== Configurable attributes
|===
@@ -2550,10 +2756,12 @@ Checks for the use of the has_and_belongs_to_many macro.
| Array
|===
+[#references-railshasandbelongstomany]
=== References
* https://rails.rubystyle.guide#has-many-through
+[#railshasmanyorhasonedependent]
== Rails/HasManyOrHasOneDependent
|===
@@ -2572,6 +2780,7 @@ specify a `:dependent` option.
It doesn't register an offense if `:through` or `dependent: nil`
is specified, or if the model is read-only.
+[#examples-railshasmanyorhasonedependent]
=== Examples
[source,ruby]
@@ -2600,6 +2809,7 @@ class User < ActiveRecord::Base
end
----
+[#configurable-attributes-railshasmanyorhasonedependent]
=== Configurable attributes
|===
@@ -2610,10 +2820,12 @@ end
| Array
|===
+[#references-railshasmanyorhasonedependent]
=== References
* https://rails.rubystyle.guide#has_many-has_one-dependent-option
+[#railshelperinstancevariable]
== Rails/HelperInstanceVariable
|===
@@ -2639,6 +2851,7 @@ example to a model, decorator or presenter.
Provided that a class inherits `ActionView::Helpers::FormBuilder`,
an offense will not be registered.
+[#examples-railshelperinstancevariable]
=== Examples
[source,ruby]
@@ -2659,6 +2872,7 @@ class MyFormBuilder < ActionView::Helpers::FormBuilder
end
----
+[#configurable-attributes-railshelperinstancevariable]
=== Configurable attributes
|===
@@ -2669,8 +2883,11 @@ end
| Array
|===
+[#railshttppositionalarguments]
== Rails/HttpPositionalArguments
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -2691,6 +2908,7 @@ Rails/HttpPositionalArguments cop or set your TargetRailsVersion in your
NOTE: It does not detect any cases where `include Rack::Test::Methods` is used
which makes the http methods incompatible behavior.
+[#examples-railshttppositionalarguments]
=== Examples
[source,ruby]
@@ -2703,6 +2921,7 @@ get :new, params: { user_id: 1 }
get :new, **options
----
+[#configurable-attributes-railshttppositionalarguments]
=== Configurable attributes
|===
@@ -2713,6 +2932,7 @@ get :new, **options
| Array
|===
+[#railshttpstatus]
== Rails/HttpStatus
|===
@@ -2727,8 +2947,10 @@ get :new, **options
Enforces use of symbolic or numeric value to define HTTP status.
+[#examples-railshttpstatus]
=== Examples
+[#enforcedstyle_-symbolic-_default_-railshttpstatus]
==== EnforcedStyle: symbolic (default)
[source,ruby]
@@ -2753,6 +2975,7 @@ assert_response :ok
assert_redirected_to '/some/path', status: :moved_permanently
----
+[#enforcedstyle_-numeric-railshttpstatus]
==== EnforcedStyle: numeric
[source,ruby]
@@ -2776,6 +2999,7 @@ assert_response 200
assert_redirected_to '/some/path', status: 301
----
+[#configurable-attributes-railshttpstatus]
=== Configurable attributes
|===
@@ -2786,6 +3010,7 @@ assert_redirected_to '/some/path', status: 301
| `numeric`, `symbolic`
|===
+[#railsi18nlazylookup]
== Rails/I18nLazyLookup
|===
@@ -2806,8 +3031,10 @@ is `lazy` (the default), explicit lookups are added as offenses.
When the EnforcedStyle is `explicit` then lazy lookups are added as
offenses.
+[#examples-railsi18nlazylookup]
=== Examples
+[#enforcedstyle_-lazy-_default_-railsi18nlazylookup]
==== EnforcedStyle: lazy (default)
[source,ruby]
@@ -2835,6 +3062,7 @@ class BooksController < ApplicationController
end
----
+[#enforcedstyle_-explicit-railsi18nlazylookup]
==== EnforcedStyle: explicit
[source,ruby]
@@ -2856,6 +3084,7 @@ class BooksController < ApplicationController
end
----
+[#configurable-attributes-railsi18nlazylookup]
=== Configurable attributes
|===
@@ -2870,11 +3099,13 @@ end
| Array
|===
+[#references-railsi18nlazylookup]
=== References
* https://rails.rubystyle.guide/#lazy-lookup
* https://guides.rubyonrails.org/i18n.html#lazy-lookup
+[#railsi18nlocaleassignment]
== Rails/I18nLocaleAssignment
|===
@@ -2894,6 +3125,7 @@ unexpected behavior at a later time.
Using `I18n.with_locale` ensures the code passed in the block is the only place `I18n.locale` is affected.
It eliminates the possibility of a `locale` sticking around longer than intended.
+[#examples-railsi18nlocaleassignment]
=== Examples
[source,ruby]
@@ -2906,6 +3138,7 @@ I18n.with_locale(:fr) do
end
----
+[#configurable-attributes-railsi18nlocaleassignment]
=== Configurable attributes
|===
@@ -2916,6 +3149,7 @@ end
| Array
|===
+[#railsi18nlocaletexts]
== Rails/I18nLocaleTexts
|===
@@ -2930,6 +3164,7 @@ end
Enforces use of I18n and locale files instead of locale specific strings.
+[#examples-railsi18nlocaletexts]
=== Examples
[source,ruby]
@@ -2995,10 +3230,12 @@ class UserMailer < ApplicationMailer
end
----
+[#references-railsi18nlocaletexts]
=== References
* https://rails.rubystyle.guide/#locale-texts
+[#railsignoredcolumnsassignment]
== Rails/IgnoredColumnsAssignment
|===
@@ -3018,6 +3255,7 @@ Overwriting previous assignments is usually a mistake, since it will
un-ignore the first set of columns. Since duplicate column names is not
a problem, it is better to simply append to the list.
+[#examples-railsignoredcolumnsassignment]
=== Examples
[source,ruby]
@@ -3044,10 +3282,12 @@ class User < ActiveRecord::Base
end
----
+[#references-railsignoredcolumnsassignment]
=== References
* https://rails.rubystyle.guide/#append-ignored-columns
+[#railsignoredskipactionfilteroption]
== Rails/IgnoredSkipActionFilterOption
|===
@@ -3067,6 +3307,7 @@ The `if` option will be ignored when `if` and `only` are used together.
Similarly, the `except` option will be ignored when `if` and `except`
are used together.
+[#examples-railsignoredskipactionfilteroption]
=== Examples
[source,ruby]
@@ -3099,6 +3340,7 @@ class MyPageController < ApplicationController
end
----
+[#configurable-attributes-railsignoredskipactionfilteroption]
=== Configurable attributes
|===
@@ -3109,10 +3351,12 @@ end
| Array
|===
+[#references-railsignoredskipactionfilteroption]
=== References
* https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options
+[#railsindexby]
== Rails/IndexBy
|===
@@ -3130,6 +3374,7 @@ Looks for uses of `each_with_object({}) { ... }`,
an enumerable into a hash where the values are the original elements.
Rails provides the `index_by` method for this purpose.
+[#examples-railsindexby]
=== Examples
[source,ruby]
@@ -3144,8 +3389,11 @@ Hash[[1, 2, 3].collect { |el| [foo(el), el] }]
[1, 2, 3].index_by { |el| foo(el) }
----
+[#railsindexwith]
== Rails/IndexWith
+NOTE: Required Rails version: 6.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -3161,6 +3409,7 @@ Looks for uses of `each_with_object({}) { ... }`,
an enumerable into a hash where the keys are the original elements.
Rails provides the `index_with` method for this purpose.
+[#examples-railsindexwith]
=== Examples
[source,ruby]
@@ -3175,6 +3424,7 @@ Hash[[1, 2, 3].collect { |el| [el, foo(el)] }]
[1, 2, 3].index_with { |el| foo(el) }
----
+[#railsinquiry]
== Rails/Inquiry
|===
@@ -3189,6 +3439,7 @@ Hash[[1, 2, 3].collect { |el| [el, foo(el)] }]
Checks that Active Support's `inquiry` method is not used.
+[#examples-railsinquiry]
=== Examples
[source,ruby]
@@ -3210,10 +3461,12 @@ pets = %w(cat dog)
pets.include? 'cat'
----
+[#references-railsinquiry]
=== References
* https://rails.rubystyle.guide/#inquiry
+[#railsinverseof]
== Rails/InverseOf
|===
@@ -3238,6 +3491,7 @@ associated object in memory, or set to `false` to opt-out. Note that
setting `nil` does not stop Active Record from trying to determine the
inverse automatically, and is not considered a valid value for this.
+[#examples-railsinverseof]
=== Examples
[source,ruby]
@@ -3359,6 +3613,7 @@ class Patient < ApplicationRecord
end
----
+[#ignorescopes_-false-_default_-railsinverseof]
==== IgnoreScopes: false (default)
[source,ruby]
@@ -3369,6 +3624,7 @@ class Blog < ApplicationRecord
end
----
+[#ignorescopes_-true-railsinverseof]
==== IgnoreScopes: true
[source,ruby]
@@ -3379,6 +3635,7 @@ class Blog < ApplicationRecord
end
----
+[#configurable-attributes-railsinverseof]
=== Configurable attributes
|===
@@ -3393,11 +3650,13 @@ end
| Array
|===
+[#references-railsinverseof]
=== References
* https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
* https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
+[#railslexicallyscopedactionfilter]
== Rails/LexicallyScopedActionFilter
|===
@@ -3413,6 +3672,7 @@ end
Checks that methods specified in the filter's `only` or
`except` options are defined within the same class or module.
+[#safety-railslexicallyscopedactionfilter]
=== Safety
You can technically specify methods of superclass or methods added by
@@ -3423,6 +3683,7 @@ define the filter in that class or module.
If you rely on behavior defined in the superclass actions, you must
remember to invoke `super` in the subclass actions.
+[#examples-railslexicallyscopedactionfilter]
=== Examples
[source,ruby]
@@ -3500,6 +3761,7 @@ class ArticlesController < ContentController
end
----
+[#configurable-attributes-railslexicallyscopedactionfilter]
=== Configurable attributes
|===
@@ -3510,10 +3772,12 @@ end
| Array
|===
+[#references-railslexicallyscopedactionfilter]
=== References
* https://rails.rubystyle.guide#lexically-scoped-action-filter
+[#railslinktoblank]
== Rails/LinkToBlank
|===
@@ -3534,6 +3798,7 @@ and could change its location for phishing purposes.
The option `rel: 'noreferrer'` also blocks this behavior
and removes the http-referrer header.
+[#examples-railslinktoblank]
=== Examples
[source,ruby]
@@ -3548,12 +3813,14 @@ link_to 'Click here', url, target: '_blank', rel: 'noopener'
link_to 'Click here', url, target: '_blank', rel: 'noreferrer'
----
+[#references-railslinktoblank]
=== References
* https://mathiasbynens.github.io/rel-noopener/
* https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
* https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer
+[#railsmailername]
== Rails/MailerName
|===
@@ -3571,11 +3838,13 @@ Enforces that mailer names end with `Mailer` suffix.
Without the `Mailer` suffix it isn't immediately apparent what's a mailer
and which views are related to the mailer.
+[#safety-railsmailername]
=== Safety
This cop's autocorrection is unsafe because renaming a constant is
always an unsafe operation.
+[#examples-railsmailername]
=== Examples
[source,ruby]
@@ -3595,6 +3864,7 @@ class UserMailer < ApplicationMailer
end
----
+[#configurable-attributes-railsmailername]
=== Configurable attributes
|===
@@ -3605,10 +3875,12 @@ end
| Array
|===
+[#references-railsmailername]
=== References
* https://rails.rubystyle.guide/#mailer-name
+[#railsmatchroute]
== Rails/MatchRoute
|===
@@ -3627,6 +3899,7 @@ can be replaced with a specific HTTP method.
Don't use `match` to define any routes unless there is a need to map multiple request types
among [:get, :post, :patch, :put, :delete] to a single action using the `:via` option.
+[#examples-railsmatchroute]
=== Examples
[source,ruby]
@@ -3642,6 +3915,7 @@ match 'photos/:id', to: 'photos#show', via: [:get, :post]
match 'photos/:id', to: 'photos#show', via: :all
----
+[#configurable-attributes-railsmatchroute]
=== Configurable attributes
|===
@@ -3652,10 +3926,12 @@ match 'photos/:id', to: 'photos#show', via: :all
| Array
|===
+[#references-railsmatchroute]
=== References
* https://rails.rubystyle.guide/#no-match-routes
+[#railsmigrationclassname]
== Rails/MigrationClassName
|===
@@ -3672,6 +3948,7 @@ Makes sure that each migration file defines a migration class
whose name matches the file name.
(e.g. `20220224111111_create_users.rb` should define `CreateUsers` class.)
+[#examples-railsmigrationclassname]
=== Examples
[source,ruby]
@@ -3687,6 +3964,7 @@ class CreateUsers < ActiveRecord::Migration[7.0]
end
----
+[#configurable-attributes-railsmigrationclassname]
=== Configurable attributes
|===
@@ -3697,6 +3975,7 @@ end
| Array
|===
+[#railsnegateinclude]
== Rails/NegateInclude
|===
@@ -3712,11 +3991,13 @@ end
Enforces the use of `collection.exclude?(obj)`
over `!collection.include?(obj)`.
+[#safety-railsnegateinclude]
=== Safety
This cop is unsafe because false positive will occur for
receiver objects that do not have an `exclude?` method. (e.g. `IPAddr`)
+[#examples-railsnegateinclude]
=== Examples
[source,ruby]
@@ -3730,10 +4011,12 @@ array.exclude?(2)
hash.exclude?(:key)
----
+[#references-railsnegateinclude]
=== References
* https://rails.rubystyle.guide#exclude
+[#railsnotnullcolumn]
== Rails/NotNullColumn
|===
@@ -3766,6 +4049,7 @@ environment in `config/database.yml` or the environment variable
`DATABASE_URL` when the `Database` option is not set. If the database
is MySQL, this cop ignores offenses for `TEXT` columns.
+[#examples-railsnotnullcolumn]
=== Examples
[source,ruby]
@@ -3787,6 +4071,7 @@ add_reference :products, :category
change_column_null :products, :category_id, false
----
+[#configurable-attributes-railsnotnullcolumn]
=== Configurable attributes
|===
@@ -3801,6 +4086,7 @@ change_column_null :products, :category_id, false
| Array
|===
+[#railsorderbyid]
== Rails/OrderById
|===
@@ -3822,6 +4108,7 @@ Use a timestamp column to order chronologically. As a bonus the intent is cleare
NOTE: Make sure the changed order column does not introduce performance
bottlenecks and appropriate database indexes are added.
+[#examples-railsorderbyid]
=== Examples
[source,ruby]
@@ -3834,10 +4121,12 @@ scope :chronological, -> { order(primary_key => :asc) }
scope :chronological, -> { order(created_at: :asc) }
----
+[#references-railsorderbyid]
=== References
* https://rails.rubystyle.guide/#order-by-id
+[#railsoutput]
== Rails/Output
|===
@@ -3852,11 +4141,13 @@ scope :chronological, -> { order(created_at: :asc) }
Checks for the use of output calls like puts and print
+[#safety-railsoutput]
=== Safety
This cop's autocorrection is unsafe because depending on the Rails log level configuration,
changing from `puts` to `Rails.logger.debug` could result in no output being shown.
+[#examples-railsoutput]
=== Examples
[source,ruby]
@@ -3870,6 +4161,7 @@ print 'A debug message'
Rails.logger.debug 'A debug message'
----
+[#configurable-attributes-railsoutput]
=== Configurable attributes
|===
@@ -3880,6 +4172,7 @@ Rails.logger.debug 'A debug message'
| Array
|===
+[#railsoutputsafety]
== Rails/OutputSafety
|===
@@ -3898,6 +4191,7 @@ simply return a SafeBuffer containing the content as is. Instead,
use `safe_join` to join content and escape it and concat to
concatenate content and escape it, ensuring its safety.
+[#examples-railsoutputsafety]
=== Examples
[source,ruby]
@@ -3956,8 +4250,11 @@ safe_join([user_content, " ", content_tag(:span, user_content)])
# "<b>hi</b> <b>hi</b>"
----
+[#railspick]
== Rails/Pick
+NOTE: Required Rails version: 6.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -3978,6 +4275,7 @@ Note that when `pick` is added to a relation with an existing limit, it
causes a subquery to be added. In most cases this is undesirable, and
care should be taken while resolving this violation.
+[#safety-railspick]
=== Safety
This cop is unsafe because `pluck` is defined on both `ActiveRecord::Relation` and `Enumerable`,
@@ -3986,6 +4284,7 @@ in Rails 6.1 via rails/rails#38760, at which point the cop is safe.
See: https://github.com/rubocop/rubocop-rails/pull/249
+[#examples-railspick]
=== Examples
[source,ruby]
@@ -3999,12 +4298,16 @@ Model.pick(:a)
[{ a: :b, c: :d }].pick(:a, :b)
----
+[#references-railspick]
=== References
* https://rails.rubystyle.guide#pick
+[#railspluck]
== Rails/Pluck
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -4021,6 +4324,7 @@ Enforces the use of `pluck` over `map`.
element in an enumerable. When called on an Active Record relation, it
results in a more efficient query that only selects the necessary key.
+[#safety-railspluck]
=== Safety
This cop is unsafe because model can use column aliases.
@@ -4034,6 +4338,7 @@ User.select('name AS nickname').map { |user| user[:nickname] } # => array of nic
User.select('name AS nickname').pluck(:nickname) # => raises ActiveRecord::StatementInvalid
----
+[#examples-railspluck]
=== Examples
[source,ruby]
@@ -4047,10 +4352,12 @@ Post.published.pluck(:title)
[{ a: :b, c: :d }].pluck(:a)
----
+[#references-railspluck]
=== References
* https://rails.rubystyle.guide#pluck
+[#railspluckid]
== Rails/PluckId
|===
@@ -4065,10 +4372,12 @@ Post.published.pluck(:title)
Enforces the use of `ids` over `pluck(:id)` and `pluck(primary_key)`.
+[#safety-railspluckid]
=== Safety
This cop is unsafe if the receiver object is not an Active Record object.
+[#examples-railspluckid]
=== Examples
[source,ruby]
@@ -4090,10 +4399,12 @@ def self.user_ids
end
----
+[#references-railspluckid]
=== References
* https://rails.rubystyle.guide/#ids
+[#railspluckinwhere]
== Rails/PluckInWhere
|===
@@ -4117,6 +4428,7 @@ This cop has two modes of enforcement. When the `EnforcedStyle` is set
to `conservative` (the default), only calls to `pluck` on a constant
(e.g. a model class) within `where` are considered offenses.
+[#safety-railspluckinwhere]
=== Safety
When `EnforcedStyle` is set to `aggressive`, all calls to `pluck`
@@ -4132,6 +4444,7 @@ subquery result sequentially, rather than using an index. This can
cause significant performance issues compared to writing the query
differently or using `pluck`.
+[#examples-railspluckinwhere]
=== Examples
[source,ruby]
@@ -4147,6 +4460,7 @@ Post.where(user_id: active_users.select(:id))
Post.where.not(user_id: active_users.select(:id))
----
+[#enforcedstyle_-conservative-_default_-railspluckinwhere]
==== EnforcedStyle: conservative (default)
[source,ruby]
@@ -4155,6 +4469,7 @@ Post.where.not(user_id: active_users.select(:id))
Post.where(user_id: active_users.pluck(:id))
----
+[#enforcedstyle_-aggressive-railspluckinwhere]
==== EnforcedStyle: aggressive
[source,ruby]
@@ -4163,6 +4478,7 @@ Post.where(user_id: active_users.pluck(:id))
Post.where(user_id: active_users.pluck(:id))
----
+[#configurable-attributes-railspluckinwhere]
=== Configurable attributes
|===
@@ -4173,6 +4489,7 @@ Post.where(user_id: active_users.pluck(:id))
| `conservative`, `aggressive`
|===
+[#railspluralizationgrammar]
== Rails/PluralizationGrammar
|===
@@ -4188,6 +4505,7 @@ Post.where(user_id: active_users.pluck(:id))
Checks for correct grammar when using ActiveSupport's
core extensions to the numeric classes.
+[#examples-railspluralizationgrammar]
=== Examples
[source,ruby]
@@ -4205,6 +4523,7 @@ core extensions to the numeric classes.
1.gigabyte
----
+[#railspresence]
== Rails/Presence
|===
@@ -4220,6 +4539,7 @@ core extensions to the numeric classes.
Checks code that can be written more easily using
`Object#presence` defined by Active Support.
+[#examples-railspresence]
=== Examples
[source,ruby]
@@ -4258,6 +4578,7 @@ a.blank? ? b : a
a.presence || b
----
+[#railspresent]
== Rails/Present
|===
@@ -4278,8 +4599,10 @@ The configuration of `NotBlank` will not produce an offense in the
context of `unless else` if `Style/UnlessElse` is enabled. This is
to prevent interference between the autocorrection of the two cops.
+[#examples-railspresent]
=== Examples
+[#notnilandnotempty_-true-_default_-railspresent]
==== NotNilAndNotEmpty: true (default)
[source,ruby]
@@ -4296,6 +4619,7 @@ foo != nil && !foo.empty?
foo.present?
----
+[#notblank_-true-_default_-railspresent]
==== NotBlank: true (default)
[source,ruby]
@@ -4312,6 +4636,7 @@ not foo.blank?
foo.present?
----
+[#unlessblank_-true-_default_-railspresent]
==== UnlessBlank: true (default)
[source,ruby]
@@ -4325,6 +4650,7 @@ something unless foo.blank?
something if foo.present?
----
+[#configurable-attributes-railspresent]
=== Configurable attributes
|===
@@ -4343,6 +4669,7 @@ something if foo.present?
| Boolean
|===
+[#railsrakeenvironment]
== Rails/RakeEnvironment
|===
@@ -4366,12 +4693,14 @@ following conditions:
* The task does not need application code.
* The task invokes the `:environment` task.
+[#safety-railsrakeenvironment]
=== Safety
Probably not a problem in most cases, but it is possible that calling `:environment` task
will break a behavior. It's also slower. E.g. some task that only needs one gem to be
loaded to run will run significantly faster without loading the whole application.
+[#examples-railsrakeenvironment]
=== Examples
[source,ruby]
@@ -4387,6 +4716,7 @@ task foo: :environment do
end
----
+[#configurable-attributes-railsrakeenvironment]
=== Configurable attributes
|===
@@ -4401,6 +4731,7 @@ end
| Array
|===
+[#railsreadwriteattribute]
== Rails/ReadWriteAttribute
|===
@@ -4428,6 +4759,7 @@ When called from within a method with the same name as the attribute,
`read_attribute` and `write_attribute` must be used to prevent an
infinite loop:
+[#examples-railsreadwriteattribute]
=== Examples
[source,ruby]
@@ -4449,6 +4781,7 @@ def foo
end
----
+[#configurable-attributes-railsreadwriteattribute]
=== Configurable attributes
|===
@@ -4459,10 +4792,12 @@ end
| Array
|===
+[#references-railsreadwriteattribute]
=== References
* https://rails.rubystyle.guide#read-attribute
+[#railsredundantactiverecordallmethod]
== Rails/RedundantActiveRecordAllMethod
|===
@@ -4483,10 +4818,12 @@ This is because omitting `all` from an association changes the methods
from `ActiveRecord::Relation` to `ActiveRecord::Associations::CollectionProxy`,
which can affect their behavior.
+[#safety-railsredundantactiverecordallmethod]
=== Safety
This cop is unsafe for autocorrection if the receiver for `all` is not an Active Record object.
+[#examples-railsredundantactiverecordallmethod]
=== Examples
[source,ruby]
@@ -4504,6 +4841,7 @@ users.where(id: ids)
user.articles.order(:created_at)
----
+[#allowedreceivers_-__actionmailer__preview__-_activesupport__timezone__-_default_-railsredundantactiverecordallmethod]
==== AllowedReceivers: ['ActionMailer::Preview', 'ActiveSupport::TimeZone'] (default)
[source,ruby]
@@ -4513,6 +4851,7 @@ ActionMailer::Preview.all.first
ActiveSupport::TimeZone.all.first
----
+[#configurable-attributes-railsredundantactiverecordallmethod]
=== Configurable attributes
|===
@@ -4523,10 +4862,12 @@ ActiveSupport::TimeZone.all.first
| Array
|===
+[#references-railsredundantactiverecordallmethod]
=== References
* https://rails.rubystyle.guide/#redundant-all
+[#railsredundantallownil]
== Rails/RedundantAllowNil
|===
@@ -4542,6 +4883,7 @@ ActiveSupport::TimeZone.all.first
Checks Rails model validations for a redundant `allow_nil` when
`allow_blank` is present.
+[#examples-railsredundantallownil]
=== Examples
[source,ruby]
@@ -4566,6 +4908,7 @@ validates :x, length: { is: 5 }, allow_blank: false
validates :x, length: { is: 5 }, allow_nil: true, allow_blank: false
----
+[#configurable-attributes-railsredundantallownil]
=== Configurable attributes
|===
@@ -4576,6 +4919,7 @@ validates :x, length: { is: 5 }, allow_nil: true, allow_blank: false
| Array
|===
+[#railsredundantforeignkey]
== Rails/RedundantForeignKey
|===
@@ -4591,6 +4935,7 @@ validates :x, length: { is: 5 }, allow_nil: true, allow_blank: false
Detects cases where the `:foreign_key` option on associations
is redundant.
+[#examples-railsredundantforeignkey]
=== Examples
[source,ruby]
@@ -4614,8 +4959,11 @@ class Comment
end
----
+[#railsredundantpresencevalidationonbelongsto]
== Rails/RedundantPresenceValidationOnBelongsTo
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -4631,11 +4979,13 @@ unless `config.active_record.belongs_to_required_by_default` is
explicitly set to `false`. The presence validator is added
automatically, and explicit presence validation is redundant.
+[#safety-railsredundantpresencevalidationonbelongsto]
=== Safety
This cop's autocorrection is unsafe because it changes the default error message
from "can't be blank" to "must exist".
+[#examples-railsredundantpresencevalidationonbelongsto]
=== Examples
[source,ruby]
@@ -4659,6 +5009,7 @@ belongs_to :user
belongs_to :author, foreign_key: :user_id
----
+[#railsredundantreceiverinwithoptions]
== Rails/RedundantReceiverInWithOptions
|===
@@ -4674,6 +5025,7 @@ belongs_to :author, foreign_key: :user_id
Checks for redundant receiver in `with_options`.
Receiver is implicit from Rails 4.2 or higher.
+[#examples-railsredundantreceiverinwithoptions]
=== Examples
[source,ruby]
@@ -4729,8 +5081,11 @@ with_options options: false do |merger|
end
----
+[#railsredundanttravelback]
== Rails/RedundantTravelBack
+NOTE: Required Rails version: 5.2
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -4744,6 +5099,7 @@ end
Checks for redundant `travel_back` calls.
Since Rails 5.2, `travel_back` is automatically called at the end of the test.
+[#examples-railsredundanttravelback]
=== Examples
[source,ruby]
@@ -4771,6 +5127,7 @@ after do
end
----
+[#configurable-attributes-railsredundanttravelback]
=== Configurable attributes
|===
@@ -4781,6 +5138,7 @@ end
| Array
|===
+[#railsreflectionclassname]
== Rails/ReflectionClassName
|===
@@ -4796,11 +5154,13 @@ end
Checks if the value of the option `class_name`, in
the definition of a reflection is a string.
+[#safety-railsreflectionclassname]
=== Safety
This cop is unsafe because it cannot be determined whether
constant or method return value specified to `class_name` is a string.
+[#examples-railsreflectionclassname]
=== Examples
[source,ruby]
@@ -4813,6 +5173,7 @@ has_many :accounts, class_name: Account.name
has_many :accounts, class_name: 'Account'
----
+[#railsrefutemethods]
== Rails/RefuteMethods
|===
@@ -4827,8 +5188,10 @@ has_many :accounts, class_name: 'Account'
Use `assert_not` methods instead of `refute` methods.
+[#examples-railsrefutemethods]
=== Examples
+[#enforcedstyle_-assert_not-_default_-railsrefutemethods]
==== EnforcedStyle: assert_not (default)
[source,ruby]
@@ -4844,6 +5207,7 @@ assert_not_empty [1, 2, 3]
assert_not_equal true, false
----
+[#enforcedstyle_-refute-railsrefutemethods]
==== EnforcedStyle: refute
[source,ruby]
@@ -4859,6 +5223,7 @@ refute_empty [1, 2, 3]
refute_equal true, false
----
+[#configurable-attributes-railsrefutemethods]
=== Configurable attributes
|===
@@ -4873,6 +5238,7 @@ refute_equal true, false
| Array
|===
+[#railsrelativedateconstant]
== Rails/RelativeDateConstant
|===
@@ -4888,10 +5254,12 @@ refute_equal true, false
Checks whether constant value isn't relative date.
Because the relative date will be evaluated only once.
+[#safety-railsrelativedateconstant]
=== Safety
This cop's autocorrection is unsafe because its dependence on the constant is not corrected.
+[#examples-railsrelativedateconstant]
=== Examples
[source,ruby]
@@ -4918,6 +5286,7 @@ class SomeClass
end
----
+[#railsrenderinline]
== Rails/RenderInline
|===
@@ -4932,6 +5301,7 @@ end
Looks for inline rendering within controller actions.
+[#examples-railsrenderinline]
=== Examples
[source,ruby]
@@ -4955,10 +5325,12 @@ class ProductsController < ApplicationController
end
----
+[#references-railsrenderinline]
=== References
* https://rails.rubystyle.guide/#inline-rendering
+[#railsrenderplaintext]
== Rails/RenderPlainText
|===
@@ -4974,6 +5346,7 @@ end
Identifies places where `render text:` can be
replaced with `render plain:`.
+[#examples-railsrenderplaintext]
=== Examples
[source,ruby]
@@ -4988,6 +5361,7 @@ render plain: 'Ruby!'
render text: 'Ruby!', content_type: 'text/html'
----
+[#contenttypecompatibility_-true-_default_-railsrenderplaintext]
==== ContentTypeCompatibility: true (default)
[source,ruby]
@@ -4996,6 +5370,7 @@ render text: 'Ruby!', content_type: 'text/html'
render text: 'Ruby!'
----
+[#contenttypecompatibility_-false-railsrenderplaintext]
==== ContentTypeCompatibility: false
[source,ruby]
@@ -5004,6 +5379,7 @@ render text: 'Ruby!'
render text: 'Ruby!'
----
+[#configurable-attributes-railsrenderplaintext]
=== Configurable attributes
|===
@@ -5014,10 +5390,12 @@ render text: 'Ruby!'
| Boolean
|===
+[#references-railsrenderplaintext]
=== References
* https://rails.rubystyle.guide/#plain-text-rendering
+[#railsrequestreferer]
== Rails/RequestReferer
|===
@@ -5033,8 +5411,10 @@ render text: 'Ruby!'
Checks for consistent uses of `request.referer` or
`request.referrer`, depending on the cop's configuration.
+[#examples-railsrequestreferer]
=== Examples
+[#enforcedstyle_-referer-_default_-railsrequestreferer]
==== EnforcedStyle: referer (default)
[source,ruby]
@@ -5046,6 +5426,7 @@ request.referrer
request.referer
----
+[#enforcedstyle_-referrer-railsrequestreferer]
==== EnforcedStyle: referrer
[source,ruby]
@@ -5057,6 +5438,7 @@ request.referer
request.referrer
----
+[#configurable-attributes-railsrequestreferer]
=== Configurable attributes
|===
@@ -5067,8 +5449,11 @@ request.referrer
| `referer`, `referrer`
|===
+[#railsrequiredependency]
== Rails/RequireDependency
+NOTE: Required Rails version: 6.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -5090,6 +5475,7 @@ Applications running in Zeitwerk mode should not use `require_dependency`.
NOTE: This cop is disabled by default. Please enable it if you are using Zeitwerk mode.
+[#examples-railsrequiredependency]
=== Examples
[source,ruby]
@@ -5098,12 +5484,16 @@ NOTE: This cop is disabled by default. Please enable it if you are using Zeitwer
require_dependency 'some_lib'
----
+[#references-railsrequiredependency]
=== References
* https://guides.rubyonrails.org/autoloading_and_reloading_constants.html
+[#railsresponseparsedbody]
== Rails/ResponseParsedBody
+NOTE: Required Rails version: 5.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -5116,6 +5506,7 @@ require_dependency 'some_lib'
Prefer `response.parsed_body` to custom parsing logic for `response.body`.
+[#safety-railsresponseparsedbody]
=== Safety
This cop is unsafe because Content-Type may not be `application/json` or `text/html`.
@@ -5123,6 +5514,7 @@ For example, the proprietary Content-Type provided by corporate entities such as
`application/vnd.github+json` is not supported at `response.parsed_body` by default,
so you still have to use `JSON.parse(response.body)` there.
+[#examples-railsresponseparsedbody]
=== Examples
[source,ruby]
@@ -5140,6 +5532,7 @@ Nokogiri::HTML5.parse(response.body)
response.parsed_body
----
+[#configurable-attributes-railsresponseparsedbody]
=== Configurable attributes
|===
@@ -5150,6 +5543,7 @@ response.parsed_body
| Array
|===
+[#railsreversiblemigration]
== Rails/ReversibleMigration
|===
@@ -5165,6 +5559,7 @@ response.parsed_body
Checks whether the change method of the migration file is
reversible.
+[#examples-railsreversiblemigration]
=== Examples
[source,ruby]
@@ -5328,6 +5723,7 @@ def change
end
----
+[#configurable-attributes-railsreversiblemigration]
=== Configurable attributes
|===
@@ -5338,11 +5734,13 @@ end
| Array
|===
+[#references-railsreversiblemigration]
=== References
* https://rails.rubystyle.guide#reversible-migration
* https://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html
+[#railsreversiblemigrationmethoddefinition]
== Rails/ReversibleMigrationMethodDefinition
|===
@@ -5359,6 +5757,7 @@ Checks whether the migration implements
either a `change` method or both an `up` and a `down`
method.
+[#examples-railsreversiblemigrationmethoddefinition]
=== Examples
[source,ruby]
@@ -5399,6 +5798,7 @@ class SomeMigration < ActiveRecord::Migration[6.0]
end
----
+[#configurable-attributes-railsreversiblemigrationmethoddefinition]
=== Configurable attributes
|===
@@ -5409,6 +5809,7 @@ end
| Array
|===
+[#railsrootjoinchain]
== Rails/RootJoinChain
|===
@@ -5423,6 +5824,7 @@ end
Use a single `#join` instead of chaining on `Rails.root` or `Rails.public_path`.
+[#examples-railsrootjoinchain]
=== Examples
[source,ruby]
@@ -5440,6 +5842,7 @@ Rails.public_path.join('path', 'file.pdf')
Rails.public_path.join('path', to, 'file.pdf')
----
+[#railsrootpathnamemethods]
== Rails/RootPathnameMethods
|===
@@ -5460,11 +5863,13 @@ so we can apply many IO methods directly.
This cop works best when used together with
`Style/FileRead`, `Style/FileWrite` and `Rails/RootJoinChain`.
+[#safety-railsrootpathnamemethods]
=== Safety
This cop is unsafe for autocorrection because ``Dir``'s `children`, `each_child`, `entries`, and `glob`
methods return string element, but these methods of `Pathname` return `Pathname` element.
+[#examples-railsrootpathnamemethods]
=== Examples
[source,ruby]
@@ -5489,6 +5894,7 @@ Rails.root.join('db', 'schema.rb').binwrite(content)
Rails.root.glob("db/schema.rb")
----
+[#railsrootpublicpath]
== Rails/RootPublicPath
|===
@@ -5503,6 +5909,7 @@ Rails.root.glob("db/schema.rb")
Favor `Rails.public_path` over `Rails.root` with `'public'`
+[#examples-railsrootpublicpath]
=== Examples
[source,ruby]
@@ -5518,6 +5925,7 @@ Rails.public_path.join('file.pdf')
Rails.public_path.join('file.pdf')
----
+[#railssafenavigation]
== Rails/SafeNavigation
NOTE: Required Ruby version: 2.3
@@ -5536,8 +5944,10 @@ Converts usages of `try!` to `&.`. It can also be configured
to convert `try`. It will convert code to use safe navigation
if the target Ruby version is set to 2.3+
+[#examples-railssafenavigation]
=== Examples
+[#converttry_-false-_default_-railssafenavigation]
==== ConvertTry: false (default)
[source,ruby]
@@ -5559,6 +5969,7 @@ foo&.bar(baz)
foo&.bar { |e| e.baz }
----
+[#converttry_-true-railssafenavigation]
==== ConvertTry: true
[source,ruby]
@@ -5577,6 +5988,7 @@ foo&.bar(baz)
foo&.bar { |e| e.baz }
----
+[#configurable-attributes-railssafenavigation]
=== Configurable attributes
|===
@@ -5587,6 +5999,7 @@ foo&.bar { |e| e.baz }
| Boolean
|===
+[#railssafenavigationwithblank]
== Rails/SafeNavigationWithBlank
|===
@@ -5602,6 +6015,7 @@ foo&.bar { |e| e.baz }
Checks to make sure safe navigation isn't used with `blank?` in
a conditional.
+[#safety-railssafenavigationwithblank]
=== Safety
While the safe navigation operator is generally a good idea, when
@@ -5616,6 +6030,7 @@ foo&.blank? #=> nil
foo.blank? #=> true
----
+[#examples-railssafenavigationwithblank]
=== Examples
[source,ruby]
@@ -5629,6 +6044,7 @@ do_something if foo.blank?
do_something unless foo.blank?
----
+[#railssavebang]
== Rails/SaveBang
|===
@@ -5663,6 +6079,7 @@ that behavior can be turned off with `AllowImplicitReturn: false`.
You can permit receivers that are giving false positives with
`AllowedReceivers: []`
+[#safety-railssavebang]
=== Safety
This cop's autocorrection is unsafe because a custom `update` method call would be changed to `update!`,
@@ -5683,6 +6100,7 @@ end
update
----
+[#examples-railssavebang]
=== Examples
[source,ruby]
@@ -5712,6 +6130,7 @@ def save_user
end
----
+[#allowimplicitreturn_-true-_default_-railssavebang]
==== AllowImplicitReturn: true (default)
[source,ruby]
@@ -5724,6 +6143,7 @@ def save_user
end
----
+[#allowimplicitreturn_-false-railssavebang]
==== AllowImplicitReturn: false
[source,ruby]
@@ -5746,6 +6166,7 @@ def save_user
end
----
+[#allowedreceivers_-__merchant_customers__-_service__mailer__-railssavebang]
==== AllowedReceivers: ['merchant.customers', 'Service::Mailer']
[source,ruby]
@@ -5768,6 +6189,7 @@ Services::Service::Mailer.update(message: 'Message')
Service::Mailer::update
----
+[#configurable-attributes-railssavebang]
=== Configurable attributes
|===
@@ -5782,10 +6204,12 @@ Service::Mailer::update
| Array
|===
+[#references-railssavebang]
=== References
* https://rails.rubystyle.guide#save-bang
+[#railsschemacomment]
== Rails/SchemaComment
|===
@@ -5801,6 +6225,7 @@ Service::Mailer::update
Enforces the use of the `comment` option when adding a new table or column
to the database during a migration.
+[#examples-railsschemacomment]
=== Examples
[source,ruby]
@@ -5820,6 +6245,7 @@ create_table :table, comment: 'Table of offenses data' do |t|
end
----
+[#railsscopeargs]
== Rails/ScopeArgs
|===
@@ -5835,6 +6261,7 @@ end
Checks for scope calls where it was passed
a method (usually a scope) instead of a lambda/proc.
+[#examples-railsscopeargs]
=== Examples
[source,ruby]
@@ -5846,6 +6273,7 @@ scope :something, where(something: true)
scope :something, -> { where(something: true) }
----
+[#configurable-attributes-railsscopeargs]
=== Configurable attributes
|===
@@ -5856,6 +6284,7 @@ scope :something, -> { where(something: true) }
| Array
|===
+[#railsselectmap]
== Rails/SelectMap
|===
@@ -5873,11 +6302,13 @@ These can be replaced with `pluck(:column_name)`.
There also should be some performance improvement since it skips instantiating the model class for matches.
+[#safety-railsselectmap]
=== Safety
This cop is unsafe because the model might override the attribute getter.
Additionally, the model's `after_initialize` hooks are skipped when using `pluck`.
+[#examples-railsselectmap]
=== Examples
[source,ruby]
@@ -5889,6 +6320,7 @@ Model.select(:column_name).map(&:column_name)
Model.pluck(:column_name)
----
+[#railsshorti18n]
== Rails/ShortI18n
|===
@@ -5911,6 +6343,7 @@ calls are added as offenses.
When the EnforcedStyle is aggressive then all `translate` and `localize` calls
without a receiver are added as offenses.
+[#examples-railsshorti18n]
=== Examples
[source,ruby]
@@ -5924,6 +6357,7 @@ I18n.t :key
I18n.l Time.now
----
+[#enforcedstyle_-conservative-_default_-railsshorti18n]
==== EnforcedStyle: conservative (default)
[source,ruby]
@@ -5935,6 +6369,7 @@ t :key
l Time.now
----
+[#enforcedstyle_-aggressive-railsshorti18n]
==== EnforcedStyle: aggressive
[source,ruby]
@@ -5948,6 +6383,7 @@ t :key
l Time.now
----
+[#configurable-attributes-railsshorti18n]
=== Configurable attributes
|===
@@ -5958,10 +6394,12 @@ l Time.now
| `conservative`, `aggressive`
|===
+[#references-railsshorti18n]
=== References
* https://rails.rubystyle.guide/#short-i18n
+[#railsskipsmodelvalidations]
== Rails/SkipsModelValidations
|===
@@ -5980,10 +6418,12 @@ https://guides.rubyonrails.org/active_record_validations.html#skipping-validatio
Methods may be ignored from this rule by configuring a `AllowedMethods`.
+[#safety-railsskipsmodelvalidations]
=== Safety
This cop is unsafe if the receiver object is not an Active Record object.
+[#examples-railsskipsmodelvalidations]
=== Examples
[source,ruby]
@@ -6005,6 +6445,7 @@ user.update(website: 'example.com')
FileUtils.touch('file')
----
+[#allowedmethods_-__touch__-railsskipsmodelvalidations]
==== AllowedMethods: ["touch"]
[source,ruby]
@@ -6018,6 +6459,7 @@ person.toggle :active
user.touch
----
+[#configurable-attributes-railsskipsmodelvalidations]
=== Configurable attributes
|===
@@ -6032,10 +6474,12 @@ user.touch
| Array
|===
+[#references-railsskipsmodelvalidations]
=== References
* https://guides.rubyonrails.org/active_record_validations.html#skipping-validations
+[#railssquishedsqlheredocs]
== Rails/SquishedSQLHeredocs
|===
@@ -6050,11 +6494,13 @@ user.touch
Checks SQL heredocs to use `.squish`.
+[#safety-railssquishedsqlheredocs]
=== Safety
Some SQL syntax (e.g. PostgreSQL comments and functions) requires newlines
to be preserved in order to work, thus autocorrection for this cop is not safe.
+[#examples-railssquishedsqlheredocs]
=== Examples
[source,ruby]
@@ -6090,10 +6536,12 @@ execute(<<~SQL.squish, "Post Load")
SQL
----
+[#references-railssquishedsqlheredocs]
=== References
* https://rails.rubystyle.guide/#squished-heredocs
+[#railsstripheredoc]
== Rails/StripHeredoc
NOTE: Required Ruby version: 2.3
@@ -6110,6 +6558,7 @@ NOTE: Required Ruby version: 2.3
Enforces the use of squiggly heredoc over `strip_heredoc`.
+[#examples-railsstripheredoc]
=== Examples
[source,ruby]
@@ -6130,10 +6579,12 @@ EOS
EOS
----
+[#references-railsstripheredoc]
=== References
* https://rails.rubystyle.guide/#prefer-squiggly-heredoc
+[#railstablenameassignment]
== Rails/TableNameAssignment
|===
@@ -6163,6 +6614,7 @@ https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema.html#method-c-table
STI base classes named `Base` are ignored by this cop.
For more information: https://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html
+[#examples-railstablenameassignment]
=== Examples
[source,ruby]
@@ -6172,6 +6624,7 @@ self.table_name = 'some_table_name'
self.table_name = :some_other_name
----
+[#configurable-attributes-railstablenameassignment]
=== Configurable attributes
|===
@@ -6182,10 +6635,12 @@ self.table_name = :some_other_name
| Array
|===
+[#references-railstablenameassignment]
=== References
* https://rails.rubystyle.guide/#keep-ar-defaults
+[#railsthreestatebooleancolumn]
== Rails/ThreeStateBooleanColumn
|===
@@ -6201,6 +6656,7 @@ self.table_name = :some_other_name
Enforces that boolean columns are created with default values (`false` or `true`) and
`NOT NULL` constraint.
+[#examples-railsthreestatebooleancolumn]
=== Examples
[source,ruby]
@@ -6216,6 +6672,7 @@ t.column :active, :boolean, default: true, null: false
t.boolean :active, default: true, null: false
----
+[#configurable-attributes-railsthreestatebooleancolumn]
=== Configurable attributes
|===
@@ -6226,10 +6683,12 @@ t.boolean :active, default: true, null: false
| Array
|===
+[#references-railsthreestatebooleancolumn]
=== References
* https://rails.rubystyle.guide/#three-state-boolean
+[#railstimezone]
== Rails/TimeZone
|===
@@ -6253,10 +6712,12 @@ then only use of `Time.zone` is allowed.
When EnforcedStyle is 'flexible' then it's also allowed
to use `Time#in_time_zone`.
+[#safety-railstimezone]
=== Safety
This cop's autocorrection is unsafe because it may change handling time.
+[#examples-railstimezone]
=== Examples
[source,ruby]
@@ -6271,8 +6732,11 @@ Time.current
Time.zone.now
Time.zone.parse('2015-03-02T19:05:37')
Time.zone.parse('2015-03-02T19:05:37Z') # Respect ISO 8601 format with timezone specifier.
+Time.parse('2015-03-02T19:05:37Z') # Also respects ISO 8601
+'2015-03-02T19:05:37Z'.to_time # Also respects ISO 8601
----
+[#enforcedstyle_-flexible-_default_-railstimezone]
==== EnforcedStyle: flexible (default)
[source,ruby]
@@ -6283,6 +6747,7 @@ Time.zone.parse('2015-03-02T19:05:37Z') # Respect ISO 8601 format with timezone
Time.at(timestamp).in_time_zone
----
+[#enforcedstyle_-strict-railstimezone]
==== EnforcedStyle: strict
[source,ruby]
@@ -6293,6 +6758,7 @@ Time.at(timestamp).in_time_zone
Time.at(timestamp).in_time_zone
----
+[#configurable-attributes-railstimezone]
=== Configurable attributes
|===
@@ -6307,11 +6773,13 @@ Time.at(timestamp).in_time_zone
| Array
|===
+[#references-railstimezone]
=== References
* https://rails.rubystyle.guide#time
* http://danilenko.org/2012/7/6/rails_timezones
+[#railstimezoneassignment]
== Rails/TimeZoneAssignment
|===
@@ -6331,6 +6799,7 @@ unexpected behavior at a later time.
Using `Time.use_zone` ensures the code passed in the block is the only place Time.zone is affected.
It eliminates the possibility of a `zone` sticking around longer than intended.
+[#examples-railstimezoneassignment]
=== Examples
[source,ruby]
@@ -6343,6 +6812,7 @@ Time.use_zone('EST') do
end
----
+[#configurable-attributes-railstimezoneassignment]
=== Configurable attributes
|===
@@ -6353,12 +6823,16 @@ end
| Array
|===
+[#references-railstimezoneassignment]
=== References
* https://thoughtbot.com/blog/its-about-time-zones
+[#railstoformatteds]
== Rails/ToFormattedS
+NOTE: Required Rails version: 7.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -6372,8 +6846,10 @@ end
Checks for consistent uses of `to_fs` or `to_formatted_s`,
depending on the cop's configuration.
+[#examples-railstoformatteds]
=== Examples
+[#enforcedstyle_-to_fs-_default_-railstoformatteds]
==== EnforcedStyle: to_fs (default)
[source,ruby]
@@ -6385,6 +6861,7 @@ time.to_formatted_s(:db)
time.to_fs(:db)
----
+[#enforcedstyle_-to_formatted_s-railstoformatteds]
==== EnforcedStyle: to_formatted_s
[source,ruby]
@@ -6396,6 +6873,7 @@ time.to_fs(:db)
time.to_formatted_s(:db)
----
+[#configurable-attributes-railstoformatteds]
=== Configurable attributes
|===
@@ -6406,12 +6884,16 @@ time.to_formatted_s(:db)
| `to_fs`, `to_formatted_s`
|===
+[#references-railstoformatteds]
=== References
* https://rails.rubystyle.guide/#prefer-to-fs
+[#railstoswithargument]
== Rails/ToSWithArgument
+NOTE: Required Rails version: 7.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -6424,11 +6906,13 @@ time.to_formatted_s(:db)
Identifies passing any argument to `#to_s`.
+[#safety-railstoswithargument]
=== Safety
This cop is marked as unsafe because it may detect `#to_s` calls
that are not related to Active Support implementation.
+[#examples-railstoswithargument]
=== Examples
[source,ruby]
@@ -6440,8 +6924,11 @@ obj.to_s(:delimited)
obj.to_formatted_s(:delimited)
----
+[#railstoplevelhashwithindifferentaccess]
== Rails/TopLevelHashWithIndifferentAccess
+NOTE: Required Rails version: 5.1
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -6455,6 +6942,7 @@ obj.to_formatted_s(:delimited)
Identifies top-level `HashWithIndifferentAccess`.
This has been soft-deprecated since Rails 5.1.
+[#examples-railstoplevelhashwithindifferentaccess]
=== Examples
[source,ruby]
@@ -6466,6 +6954,7 @@ HashWithIndifferentAccess.new(foo: 'bar')
ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
----
+[#configurable-attributes-railstoplevelhashwithindifferentaccess]
=== Configurable attributes
|===
@@ -6476,10 +6965,12 @@ ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
| String
|===
+[#references-railstoplevelhashwithindifferentaccess]
=== References
* https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#top-level-hashwithindifferentaccess-is-soft-deprecated
+[#railstransactionexitstatement]
== Rails/TransactionExitStatement
|===
@@ -6504,6 +6995,11 @@ desired.
If you are defining custom transaction methods, you can configure it with `TransactionMethods`.
+NOTE: This cop is disabled on Rails >= 7.2 because transactions were restored
+to their historical behavior. In Rails 7.1, the behavior is controlled with
+the config `active_record.commit_transaction_on_non_local_return`.
+
+[#examples-railstransactionexitstatement]
=== Examples
[source,ruby]
@@ -6546,6 +7042,7 @@ ApplicationRecord.transaction do
end
----
+[#transactionmethods_-__custom_transaction__-railstransactionexitstatement]
==== TransactionMethods: ["custom_transaction"]
[source,ruby]
@@ -6556,6 +7053,7 @@ CustomModel.custom_transaction do
end
----
+[#configurable-attributes-railstransactionexitstatement]
=== Configurable attributes
|===
@@ -6566,10 +7064,12 @@ end
| Array
|===
+[#references-railstransactionexitstatement]
=== References
* https://github.com/rails/rails/commit/15aa4200e083
+[#railsuniqbeforepluck]
== Rails/UniqBeforePluck
|===
@@ -6597,13 +7097,16 @@ as the cop cannot distinguish between calls to `pluck` on an
ActiveRecord::Relation vs a call to pluck on an
ActiveRecord::Associations::CollectionProxy.
+[#safety-railsuniqbeforepluck]
=== Safety
This cop is unsafe for autocorrection because the behavior may change
depending on the database collation.
+[#examples-railsuniqbeforepluck]
=== Examples
+[#enforcedstyle_-conservative-_default_-railsuniqbeforepluck]
==== EnforcedStyle: conservative (default)
[source,ruby]
@@ -6615,6 +7118,7 @@ Album.pluck(:band_name).uniq
Album.distinct.pluck(:band_name)
----
+[#enforcedstyle_-aggressive-railsuniqbeforepluck]
==== EnforcedStyle: aggressive
[source,ruby]
@@ -6634,6 +7138,7 @@ Album.distinct.where(year: 1985).pluck(:band_name)
customer.favourites.distinct.pluck(:color)
----
+[#configurable-attributes-railsuniqbeforepluck]
=== Configurable attributes
|===
@@ -6644,6 +7149,7 @@ customer.favourites.distinct.pluck(:color)
| `conservative`, `aggressive`
|===
+[#railsuniquevalidationwithoutindex]
== Rails/UniqueValidationWithoutIndex
|===
@@ -6667,6 +7173,7 @@ the query will be heavy.
Note that the cop does nothing if db/schema.rb does not exist.
+[#examples-railsuniquevalidationwithoutindex]
=== Examples
[source,ruby]
@@ -6681,6 +7188,7 @@ validates :account, uniqueness: true
validates :account, length: { minimum: MIN_LENGTH }
----
+[#configurable-attributes-railsuniquevalidationwithoutindex]
=== Configurable attributes
|===
@@ -6691,6 +7199,7 @@ validates :account, length: { minimum: MIN_LENGTH }
| Array
|===
+[#railsunknownenv]
== Rails/UnknownEnv
|===
@@ -6709,6 +7218,7 @@ By default the cop allows three environments which Rails ships with:
`development`, `test`, and `production`.
More can be added to the `Environments` config parameter.
+[#examples-railsunknownenv]
=== Examples
[source,ruby]
@@ -6722,6 +7232,7 @@ Rails.env.production?
Rails.env == 'production'
----
+[#configurable-attributes-railsunknownenv]
=== Configurable attributes
|===
@@ -6736,6 +7247,7 @@ Rails.env == 'production'
| Array
|===
+[#railsunusedignoredcolumns]
== Rails/UnusedIgnoredColumns
|===
@@ -6758,6 +7270,7 @@ this cop can cause `ignored_columns` to be removed even though the production sc
the column, which can lead to downtime when the migration is actually executed. Only enable this cop
if you know your migrations will be run before any of your Rails applications boot with the modified code.
+[#examples-railsunusedignoredcolumns]
=== Examples
[source,ruby]
@@ -6773,6 +7286,7 @@ class User < ApplicationRecord
end
----
+[#configurable-attributes-railsunusedignoredcolumns]
=== Configurable attributes
|===
@@ -6783,6 +7297,7 @@ end
| Array
|===
+[#railsunusedrendercontent]
== Rails/UnusedRenderContent
|===
@@ -6800,6 +7315,7 @@ it will be dropped from the response.
This cop checks for uses of `render` which specify both body content and a non-content status.
+[#examples-railsunusedrendercontent]
=== Examples
[source,ruby]
@@ -6813,6 +7329,7 @@ head :continue
head 100
----
+[#configurable-attributes-railsunusedrendercontent]
=== Configurable attributes
|===
@@ -6823,6 +7340,7 @@ head 100
| String
|===
+[#railsvalidation]
== Rails/Validation
|===
@@ -6837,6 +7355,7 @@ head 100
Checks for the use of old-style attribute validation macros.
+[#examples-railsvalidation]
=== Examples
[source,ruby]
@@ -6870,6 +7389,7 @@ validates :foo, length: true
validates :foo, uniqueness: true
----
+[#configurable-attributes-railsvalidation]
=== Configurable attributes
|===
@@ -6880,6 +7400,7 @@ validates :foo, uniqueness: true
| Array
|===
+[#railswhereequals]
== Rails/WhereEquals
|===
@@ -6896,11 +7417,13 @@ Identifies places where manually constructed SQL
in `where` and `where.not` can be replaced with
`where(attribute: value)` and `where.not(attribute: value)`.
+[#safety-railswhereequals]
=== Safety
This cop's autocorrection is unsafe because is may change SQL.
See: https://github.com/rubocop/rubocop-rails/issues/403
+[#examples-railswhereequals]
=== Examples
[source,ruby]
@@ -6922,10 +7445,12 @@ User.where(name: ['john', 'jane'])
User.where(users: { name: 'Gabe' })
----
+[#references-railswhereequals]
=== References
* https://rails.rubystyle.guide/#hash-conditions
+[#railswhereexists]
== Rails/WhereExists
|===
@@ -6946,6 +7471,7 @@ then the cop enforces `exists?(...)` over `where(...).exists?`.
When EnforcedStyle is 'where' then the cop enforces
`where(...).exists?` over `exists?(...)`.
+[#safety-railswhereexists]
=== Safety
This cop is unsafe for autocorrection because the behavior may change on the following case:
@@ -6959,8 +7485,10 @@ Author.includes(:articles).exists?(articles: {id: id})
#=> Perform `preload` behavior and `ActiveRecord::StatementInvalid` error occurs.
----
+[#examples-railswhereexists]
=== Examples
+[#enforcedstyle_-exists-_default_-railswhereexists]
==== EnforcedStyle: exists (default)
[source,ruby]
@@ -6977,6 +7505,7 @@ User.where('length(name) > 10').exists?
user.posts.exists?(published: true)
----
+[#enforcedstyle_-where-railswhereexists]
==== EnforcedStyle: where
[source,ruby]
@@ -6994,6 +7523,7 @@ user.posts.where(published: true).exists?
User.where('length(name) > 10').exists?
----
+[#configurable-attributes-railswhereexists]
=== Configurable attributes
|===
@@ -7004,8 +7534,11 @@ User.where('length(name) > 10').exists?
| `exists`, `where`
|===
+[#railswheremissing]
== Rails/WhereMissing
+NOTE: Required Rails version: 6.1
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -7020,6 +7553,7 @@ Use `where.missing(...)` to find missing relationship records.
This cop is enabled in Rails 6.1 or higher.
+[#examples-railswheremissing]
=== Examples
[source,ruby]
@@ -7031,10 +7565,12 @@ Post.left_joins(:author).where(authors: { id: nil })
Post.where.missing(:author)
----
+[#references-railswheremissing]
=== References
* https://rails.rubystyle.guide/#finding-missing-relationship-records
+[#railswherenot]
== Rails/WhereNot
|===
@@ -7050,6 +7586,7 @@ Post.where.missing(:author)
Identifies places where manually constructed SQL
in `where` can be replaced with `where.not(...)`.
+[#examples-railswherenot]
=== Examples
[source,ruby]
@@ -7071,10 +7608,12 @@ User.where.not(name: ['john', 'jane'])
User.where.not(users: { name: 'Gabe' })
----
+[#references-railswherenot]
=== References
* https://rails.rubystyle.guide/#hash-conditions
+[#railswherenotwithmultipleconditions]
== Rails/WhereNotWithMultipleConditions
|===
@@ -7095,6 +7634,7 @@ The behavior of `where.not` changed in Rails 6.1. Prior to the change,
From Rails 6.1 onwards, this executes the query
`WHERE NOT (trashed == TRUE AND roles == 'admin')`.
+[#examples-railswherenotwithmultipleconditions]
=== Examples
[source,ruby]
@@ -7111,6 +7651,7 @@ User.where.not(trashed: true).where.not(role: ['moderator', 'admin'])
User.where.not('trashed = ? OR role = ?', true, 'admin')
----
+[#configurable-attributes-railswherenotwithmultipleconditions]
=== Configurable attributes
|===
@@ -7121,14 +7662,18 @@ User.where.not('trashed = ? OR role = ?', true, 'admin')
| String
|===
+[#references-railswherenotwithmultipleconditions]
=== References
* https://rails.rubystyle.guide/#where-not-with-multiple-attributes
+[#railswhererange]
== Rails/WhereRange
NOTE: Required Ruby version: 2.6
+NOTE: Required Rails version: 6.0
+
|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed
@@ -7142,6 +7687,7 @@ NOTE: Required Ruby version: 2.6
Identifies places where manually constructed SQL
in `where` can be replaced with ranges.
+[#safety-railswhererange]
=== Safety
This cop's autocorrection is unsafe because it can change the query
@@ -7151,6 +7697,7 @@ implicitly attach the `end_at` column to the `events` table. But when autocorrec
`Booking.joins(:events).where(end_at: ...Time.current)`, it will now be incorrectly
explicitly attached to the `bookings` table.
+[#examples-railswhererange]
=== Examples
[source,ruby]
@@ -7175,6 +7722,7 @@ User.where(users: { age: 18.. })
User.where('age > ?', 18)
----
+[#references-railswhererange]
=== References
* https://rails.rubystyle.guide/#where-ranges
diff --git a/lib/rubocop/rails/version.rb b/lib/rubocop/rails/version.rb
index 15095dece0..090716add8 100644
--- a/lib/rubocop/rails/version.rb
+++ b/lib/rubocop/rails/version.rb
@@ -4,7 +4,7 @@ module RuboCop
module Rails
# This module holds the RuboCop Rails version information.
module Version
- STRING = '2.26.2'
+ STRING = '2.27.0'
def self.document_version
STRING.match('\d+\.\d+').to_s
diff --git a/relnotes/v2.27.0.md b/relnotes/v2.27.0.md
new file mode 100644
index 0000000000..6abf1141b1
--- /dev/null
+++ b/relnotes/v2.27.0.md
@@ -0,0 +1,15 @@
+### Bug fixes
+
+* [#1377](https://github.com/rubocop/rubocop-rails/issues/1377): Fix an error for `Rails/EnumSyntax` when positional arguments are used and options are not passed as keyword arguments. ([@koic][])
+* [#1367](https://github.com/rubocop/rubocop-rails/pull/1367): Fix `Rails/TimeZone` should not report offense on `String#to_time` with timezone specifier. ([@armandmgt][])
+
+### Changes
+
+* [#727](https://github.com/rubocop/rubocop-rails/issues/727): Disable `Rails/TransactionExitStatement` on Rails >= 7.2. ([@earlopain][])
+* [#1374](https://github.com/rubocop/rubocop-rails/pull/1374): Change `Rails/EnvLocal` to handle negated conditions. ([@fatkodima][])
+* [#1195](https://github.com/rubocop/rubocop-rails/issues/1195): Change `Rails/SelectMap` to handle safe navigation operators. ([@fatkodima][])
+
+[@koic]: https://github.com/koic
+[@armandmgt]: https://github.com/armandmgt
+[@earlopain]: https://github.com/earlopain
+[@fatkodima]: https://github.com/fatkodima