diff --git a/CHANGELOG.md b/CHANGELOG.md index b960820286..8671e1bf72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ## master (unreleased) +## 2.26.0 (2024-08-24) + ### New features * [#1238](https://github.com/rubocop/rubocop-rails/issues/1238): Add new `Rails/EnumSyntax` cop. ([@maxprokopiev][], [@koic][]) diff --git a/config/default.yml b/config/default.yml index f2b87a6367..97b01498b0 100644 --- a/config/default.yml +++ b/config/default.yml @@ -428,7 +428,7 @@ Rails/EnumSyntax: Description: 'Use positional arguments over keyword arguments when defining enums.' Enabled: pending Severity: warning - VersionAdded: '<>' + VersionAdded: '2.26' Include: - app/models/**/*.rb @@ -1198,7 +1198,7 @@ Rails/WhereEquals: Enabled: 'pending' SafeAutoCorrect: false VersionAdded: '2.9' - VersionChanged: <> + VersionChanged: '2.26' Rails/WhereExists: Description: 'Prefer `exists?(...)` over `where(...).exists?`.' diff --git a/docs/antora.yml b/docs/antora.yml index 9e0ff48acb..0e3477f379 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.26' nav: - modules/ROOT/nav.adoc diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index 5e87149ded..10c6b8a388 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -53,6 +53,7 @@ based on the https://rails.rubystyle.guide/[Rails Style Guide]. * xref:cops_rails.adoc#railsdynamicfindby[Rails/DynamicFindBy] * xref:cops_rails.adoc#railseagerevaluationlogmessage[Rails/EagerEvaluationLogMessage] * xref:cops_rails.adoc#railsenumhash[Rails/EnumHash] +* xref:cops_rails.adoc#railsenumsyntax[Rails/EnumSyntax] * xref:cops_rails.adoc#railsenumuniqueness[Rails/EnumUniqueness] * xref:cops_rails.adoc#railsenvlocal[Rails/EnvLocal] * xref:cops_rails.adoc#railsenvironmentcomparison[Rails/EnvironmentComparison] diff --git a/docs/modules/ROOT/pages/cops_rails.adoc b/docs/modules/ROOT/pages/cops_rails.adoc index 65cf9a1287..b946879608 100644 --- a/docs/modules/ROOT/pages/cops_rails.adoc +++ b/docs/modules/ROOT/pages/cops_rails.adoc @@ -1084,7 +1084,6 @@ This will work fine when the receiver is a hash object. And `compact_blank!` has different implementations for `Array`, `Hash`, and `ActionController::Parameters`. `Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`. -`ActionController::Parameters#compact_blank!` is equivalent to `reject!(&:blank?)`. If the cop makes a mistake, autocorrected code may get unexpected behavior. === Examples @@ -1094,6 +1093,8 @@ If the cop makes a mistake, autocorrected code may get unexpected behavior. # bad collection.reject(&:blank?) collection.reject { |_k, v| v.blank? } +collection.select(&:present?) +collection.select { |_k, v| v.present? } # good collection.compact_blank @@ -1101,8 +1102,8 @@ collection.compact_blank # bad collection.delete_if(&:blank?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` collection.delete_if { |_k, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` -collection.reject!(&:blank?) # Same behavior as `ActionController::Parameters#compact_blank!` -collection.reject! { |_k, v| v.blank? } # Same behavior as `ActionController::Parameters#compact_blank!` +collection.keep_if(&:present?) # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` +collection.keep_if { |_k, v| v.present? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!` # good collection.compact_blank! @@ -1294,10 +1295,10 @@ Rails time zone. You must use `Time.zone.today` instead. The cop also reports warnings when you are using `to_time` method, because it doesn't know about Rails time zone either. -Two styles are supported for this cop. When `EnforcedStyle` is 'strict' +Two styles are supported for this cop. When `EnforcedStyle` is `strict` then the Date methods `today`, `current`, `yesterday`, and `tomorrow` are prohibited and the usage of both `to_time` -and 'to_time_in_current_zone' are reported as warning. +and `to_time_in_current_zone` are reported as warning. When `EnforcedStyle` is `flexible` then only `Date.today` is prohibited. @@ -1881,6 +1882,12 @@ value for each key prevents this from happening. [source,ruby] ---- +# bad +enum :status, [:active, :archived] + +# good +enum :status, { active: 0, archived: 1 } + # bad enum status: [:active, :archived] @@ -1902,6 +1909,48 @@ enum status: { active: 0, archived: 1 } * https://rails.rubystyle.guide#enums +== Rails/EnumSyntax + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Always +| 2.26 +| - +|=== + +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 + +[source,ruby] +---- +# bad +enum status: { active: 0, archived: 1 }, _prefix: true + +# good +enum :status, { active: 0, archived: 1 }, prefix: true +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| Severity +| `warning` +| String + +| Include +| `+app/models/**/*.rb+` +| Array +|=== + == Rails/EnumUniqueness |=== @@ -1920,6 +1969,18 @@ Looks for duplicate values in enum declarations. [source,ruby] ---- +# bad +enum :status, { active: 0, archived: 0 } + +# good +enum :status, { active: 0, archived: 1 } + +# bad +enum :status, [:active, :archived, :active] + +# good +enum :status, [:active, :archived] + # bad enum status: { active: 0, archived: 0 } @@ -4031,18 +4092,27 @@ Identifies places where `pluck` is used in `where` query methods and can be replaced with `select`. Since `pluck` is an eager method and hits the database immediately, -using `select` helps to avoid additional database queries. +using `select` helps to avoid additional database queries by running as +a subquery. -This cop has two different enforcement modes. When the `EnforcedStyle` -is `conservative` (the default) then only calls to `pluck` on a constant -(i.e. a model class) in the `where` is used as offenses. +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 -When the `EnforcedStyle` is `aggressive` then all calls to `pluck` in the -`where` is used as offenses. This may lead to false positives -as the cop cannot replace to `select` between calls to `pluck` on an -`ActiveRecord::Relation` instance vs a call to `pluck` on an `Array` instance. +When `EnforcedStyle` is set to `aggressive`, all calls to `pluck` +within `where` are considered offenses. This might lead to false +positives because the check cannot distinguish between calls to +`pluck` on an `ActiveRecord::Relation` instance and calls to `pluck` +on an `Array` instance. + +Additionally, when using a subquery with the SQL `IN` operator, +databases like PostgreSQL and MySQL can't optimize complex queries as +well. They need to scan all records of the outer table against the +subquery result sequentially, rather than using an index. This can +cause significant performance issues compared to writing the query +differently or using `pluck`. === Examples @@ -4107,10 +4177,14 @@ core extensions to the numeric classes. # bad 3.day.ago 1.months.ago +5.megabyte +1.gigabyte # good 3.days.ago 1.month.ago +5.megabytes +1.gigabyte ---- == Rails/Presence @@ -6794,15 +6868,16 @@ validates :foo, uniqueness: true | Yes | Always (Unsafe) | 2.9 -| 2.10 +| 2.26 |=== Identifies places where manually constructed SQL -in `where` can be replaced with `where(attribute: value)`. +in `where` and `where.not` can be replaced with +`where(attribute: value)` and `where.not(attribute: value)`. === Safety -This cop's autocorrection is unsafe because it may change SQL. +This cop's autocorrection is unsafe because is may change SQL. See: https://github.com/rubocop/rubocop-rails/issues/403 === Examples @@ -6811,6 +6886,7 @@ See: https://github.com/rubocop/rubocop-rails/issues/403 ---- # bad User.where('name = ?', 'Gabe') +User.where.not('name = ?', 'Gabe') User.where('name = :name', name: 'Gabe') User.where('name IS NULL') User.where('name IN (?)', ['john', 'jane']) @@ -6819,6 +6895,7 @@ User.where('users.name = :name', name: 'Gabe') # good User.where(name: 'Gabe') +User.where.not(name: 'Gabe') User.where(name: nil) User.where(name: ['john', 'jane']) User.where(users: { name: 'Gabe' }) diff --git a/lib/rubocop/rails/version.rb b/lib/rubocop/rails/version.rb index 29db46e6d2..438e0a2245 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.25.1' + STRING = '2.26.0' def self.document_version STRING.match('\d+\.\d+').to_s diff --git a/relnotes/v2.26.0.md b/relnotes/v2.26.0.md new file mode 100644 index 0000000000..312b84f82a --- /dev/null +++ b/relnotes/v2.26.0.md @@ -0,0 +1,33 @@ +### New features + +* [#1238](https://github.com/rubocop/rubocop-rails/issues/1238): Add new `Rails/EnumSyntax` cop. ([@maxprokopiev][], [@koic][]) +* [#1309](https://github.com/rubocop/rubocop-rails/pull/1309): Support Rails 7 syntax for `Rails/EnumHash` cop. ([@ytjmt][]) +* [#1298](https://github.com/rubocop/rubocop-rails/pull/1298): Support Rails 7 syntax for `Rails/EnumUniqueness` cop. ([@ytjmt][]) + +### Bug fixes + +* [#1335](https://github.com/rubocop/rubocop-rails/pull/1335): Fix an error for `Rails/BulkChangeTable` when the block for `change_table` is empty. ([@earlopain][]) +* [#1325](https://github.com/rubocop/rubocop-rails/pull/1325): Fix an error for `Rails/RenderPlainText` when the content type is passed as a constant. ([@earlopain][]) +* [#1337](https://github.com/rubocop/rubocop-rails/pull/1337): Fix an error for `Rails/Validation` when passing no arguments. ([@earlopain][]) +* [#1330](https://github.com/rubocop/rubocop-rails/pull/1330): Fix an error for `Rails/WhereNot` when using placeholder without second argument. ([@earlopain][]) +* [#1311](https://github.com/rubocop/rubocop-rails/pull/1311): Fix false negatives for `Rails/ActionControllerFlashBeforeRender` when using implicit render or rescue blocks. ([@tldn0718][]) +* [#1313](https://github.com/rubocop/rubocop-rails/pull/1313): Fix false positives for `Rails/CompactBlank` when using `collection.reject!`. ([@koic][]) +* [#1319](https://github.com/rubocop/rubocop-rails/issues/1319): Fix a false positive for `Rails/RedundantPresenceValidationOnBelongsTo` when removing `presence` would leave other non-validation options like `allow_blank` without validations. ([@earlopain][]) +* [#1306](https://github.com/rubocop/rubocop-rails/pull/1306): Make `Rails/PluralizationGrammar` aware of byte methods. ([@earlopain][]) +* [#1302](https://github.com/rubocop/rubocop-rails/pull/1302): Allow `params` receiver by default for `Style/CollectionMethods`. ([@koic][]) +* [#1321](https://github.com/rubocop/rubocop-rails/pull/1321): Fix an error for `Rails/WhereEquals` when the second argument is not yet typed (`where("foo = ?", )`). ([@earlopain][]) + +### Changes + +* [#1308](https://github.com/rubocop/rubocop-rails/issues/1308): Change `Rails/CompactBlank` to handle `select(&:present?)`. ([@fatkodima][]) +* [#1303](https://github.com/rubocop/rubocop-rails/pull/1303): Change `Rails/IgnoredSkipActionFilterOption` to handle multiple callbacks. ([@fatkodima][]) +* [#1199](https://github.com/rubocop/rubocop-rails/issues/1199): Make `Rails/WhereEquals` aware of `where.not(...)`. ([@earlopain][]) +* [#1003](https://github.com/rubocop/rubocop-rails/pull/1003): Change `Rails/RootPathnameMethods` to detect offenses on `Dir.[]`. ([@r7kamura][]) + +[@maxprokopiev]: https://github.com/maxprokopiev +[@koic]: https://github.com/koic +[@ytjmt]: https://github.com/ytjmt +[@earlopain]: https://github.com/earlopain +[@tldn0718]: https://github.com/tldn0718 +[@fatkodima]: https://github.com/fatkodima +[@r7kamura]: https://github.com/r7kamura