From 809fd5480c8289215943548bb59394862914a990 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Fri, 17 May 2024 11:58:59 +0900 Subject: [PATCH] Cut 2.25.0 --- CHANGELOG.md | 2 + config/default.yml | 4 +- docs/antora.yml | 2 +- docs/modules/ROOT/pages/cops.adoc | 1 + docs/modules/ROOT/pages/cops_rails.adoc | 101 +++++++++++++++++++++--- lib/rubocop/rails/version.rb | 2 +- relnotes/v2.25.0.md | 24 ++++++ 7 files changed, 122 insertions(+), 14 deletions(-) create mode 100644 relnotes/v2.25.0.md diff --git a/CHANGELOG.md b/CHANGELOG.md index aadc4c9276..651e0b7c13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ## master (unreleased) +## 2.25.0 (2024-05-17) + ### New features * [#1272](https://github.com/rubocop/rubocop-rails/pull/1272): Add new `Rails/WhereRange` cop. ([@fatkodima][]) diff --git a/config/default.yml b/config/default.yml index 52604c1acd..da35758392 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1165,7 +1165,7 @@ Rails/UnusedIgnoredColumns: Description: 'Remove a column that does not exist from `ignored_columns`.' Enabled: false VersionAdded: '2.11' - VersionChanged: <> + VersionChanged: '2.25' Include: - app/models/**/*.rb @@ -1226,7 +1226,7 @@ Rails/WhereRange: Description: 'Use ranges in `where` instead of manually constructing SQL.' StyleGuide: 'https://rails.rubystyle.guide/#where-ranges' Enabled: pending - VersionAdded: '<>' + VersionAdded: '2.25' # Accept `redirect_to(...) and return` and similar cases. Style/AndOr: diff --git a/docs/antora.yml b/docs/antora.yml index 9e0ff48acb..2af9fa857f 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.25' nav: - modules/ROOT/nav.adoc diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index 56dfc04e5b..5e87149ded 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -145,5 +145,6 @@ based on the https://rails.rubystyle.guide/[Rails Style Guide]. * xref:cops_rails.adoc#railswheremissing[Rails/WhereMissing] * xref:cops_rails.adoc#railswherenot[Rails/WhereNot] * xref:cops_rails.adoc#railswherenotwithmultipleconditions[Rails/WhereNotWithMultipleConditions] +* xref:cops_rails.adoc#railswhererange[Rails/WhereRange] // END_COP_LIST diff --git a/docs/modules/ROOT/pages/cops_rails.adoc b/docs/modules/ROOT/pages/cops_rails.adoc index 3308d9fc08..45748ae1d2 100644 --- a/docs/modules/ROOT/pages/cops_rails.adoc +++ b/docs/modules/ROOT/pages/cops_rails.adoc @@ -2661,6 +2661,8 @@ render json: { foo: 'bar' }, status: 200 render plain: 'foo/bar', status: 304 redirect_to root_url, status: 301 head 200 +assert_response 200 +assert_redirected_to '/some/path', status: 301 # good render :foo, status: :ok @@ -2668,6 +2670,8 @@ render json: { foo: 'bar' }, status: :ok render plain: 'foo/bar', status: :not_modified redirect_to root_url, status: :moved_permanently head :ok +assert_response :ok +assert_redirected_to '/some/path', status: :moved_permanently ---- ==== EnforcedStyle: numeric @@ -2680,6 +2684,8 @@ render json: { foo: 'bar' }, status: :not_found render plain: 'foo/bar', status: :not_modified redirect_to root_url, status: :moved_permanently head :ok +assert_response :ok +assert_redirected_to '/some/path', status: :moved_permanently # good render :foo, status: 200 @@ -2687,6 +2693,8 @@ render json: { foo: 'bar' }, status: 404 render plain: 'foo/bar', status: 304 redirect_to root_url, status: 301 head 200 +assert_response 200 +assert_redirected_to '/some/path', status: 301 ---- === Configurable attributes @@ -3659,13 +3667,25 @@ hash.exclude?(:key) | 2.20 |=== -Checks for add_column call with NOT NULL constraint in migration file. +Checks for add_column calls with a NOT NULL constraint without a default +value. -`TEXT` can have default values in PostgreSQL, but not in MySQL. -It will automatically detect an adapter from `development` 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 the `TEXT`. +This cop only applies when adding a column to an existing table, since +existing records will not have a value for the new column. New tables +can freely use NOT NULL columns without defaults, since there are no +records that could violate the constraint. + +If you need to add a NOT NULL column to an existing table, you must add +it as nullable first, back-fill the data, and then use +`change_column_null`. Alternatively, you could add the column with a +default first to have the database automatically backfill existing rows, +and then use `change_column_default` to remove the default. + +`TEXT` cannot have a default value in MySQL. +The cop will automatically detect an adapter from `development` +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 @@ -3674,12 +3694,18 @@ this cop ignores offenses for the `TEXT`. # bad add_column :users, :name, :string, null: false add_reference :products, :category, null: false +change_table :users do |t| + t.string :name, null: false +end # good add_column :users, :name, :string, null: true add_column :users, :name, :string, null: false, default: '' +change_table :users do |t| + t.string :name, null: false, default: '' +end add_reference :products, :category -add_reference :products, :category, null: false, default: 1 +change_column_null :products, :category_id, false ---- === Configurable attributes @@ -3869,6 +3895,10 @@ Using `pluck` followed by `first` creates an intermediate array, which `pick` avoids. When called on an Active Record relation, `pick` adds a limit to the query so that only one value is fetched from the database. +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 This cop is unsafe because `pluck` is defined on both `ActiveRecord::Relation` and `Enumerable`, @@ -6612,17 +6642,23 @@ Rails.env == 'production' |=== | Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed -| Pending +| Disabled | Yes | No | 2.11 -| - +| 2.25 |=== Suggests you remove a column that does not exist in the schema from `ignored_columns`. `ignored_columns` is necessary to drop a column from RDBMS, but you don't need it after the migration to drop the column. You avoid forgetting to remove `ignored_columns` by this cop. +IMPORTANT: This cop can't be used to effectively check for unused columns because the development +and production schema can be out of sync until the migration has been run on production. As such, +this cop can cause `ignored_columns` to be removed even though the production schema still contains +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 [source,ruby] @@ -6729,7 +6765,7 @@ validates :foo, length: true validates :foo, numericality: true validates :foo, presence: true validates :foo, absence: true -validates :foo, size: true +validates :foo, length: true validates :foo, uniqueness: true ---- @@ -6984,3 +7020,48 @@ User.where.not('trashed = ? OR role = ?', true, 'admin') === References * https://rails.rubystyle.guide/#where-not-with-multiple-attributes + +== Rails/WhereRange + +NOTE: Required Ruby version: 2.6 + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| Always +| 2.25 +| - +|=== + +Identifies places where manually constructed SQL +in `where` can be replaced with ranges. + +=== Examples + +[source,ruby] +---- +# bad +User.where('age >= ?', 18) +User.where.not('age >= ?', 18) +User.where('age < ?', 18) +User.where('age >= ? AND age < ?', 18, 21) +User.where('age >= :start', start: 18) +User.where('users.age >= ?', 18) + +# good +User.where(age: 18..) +User.where.not(age: 18..) +User.where(age: ...18) +User.where(age: 18...21) +User.where(users: { age: 18.. }) + +# good +# There are no beginless ranges in ruby. +User.where('age > ?', 18) +---- + +=== References + +* https://rails.rubystyle.guide/#where-ranges diff --git a/lib/rubocop/rails/version.rb b/lib/rubocop/rails/version.rb index f5c6881e78..77d9a63a6b 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.24.1' + STRING = '2.25.0' def self.document_version STRING.match('\d+\.\d+').to_s diff --git a/relnotes/v2.25.0.md b/relnotes/v2.25.0.md new file mode 100644 index 0000000000..03239f1989 --- /dev/null +++ b/relnotes/v2.25.0.md @@ -0,0 +1,24 @@ +### New features + +* [#1272](https://github.com/rubocop/rubocop-rails/pull/1272): Add new `Rails/WhereRange` cop. ([@fatkodima][]) + +### Bug fixes + +* [#1270](https://github.com/rubocop/rubocop-rails/issues/1270): Fix an incorrect autocorrect for `Rails/Validation` when using `validates_size_of`. ([@koic][]) +* [#1278](https://github.com/rubocop/rubocop-rails/issues/1278): Fix a false positive for `Rails/SkipsModelValidations` when using `insert` or `insert!` with a safe navigator. ([@tldn0718][]) +* [#1260](https://github.com/rubocop/rubocop-rails/issues/1260): Fix a performance regression caused by `Rails/UnknownEnv` when using Rails 7.1. ([@lukasfroehlich1][]) + +### Changes + +* [#1249](https://github.com/rubocop/rubocop-rails/issues/1249): Disable `Rails/UnusedIgnoredColumns` by default. ([@earlopain][]) +* [#1266](https://github.com/rubocop/rubocop-rails/pull/1266): Check `change_table` calls for offenses. ([@ccutrer][]) +* [#1267](https://github.com/rubocop/rubocop-rails/pull/1267): Make `Rails/HttpStatus` aware of Rails-specific response assertions. ([@tldn0718][]) +* [#1137](https://github.com/rubocop/rubocop-rails/pull/1137): Migrate to `TargetRailsVersion` the new [`requires_gem` API](https://github.com/rubocop/rubocop/pull/12186). ([@amomchilov][]) + +[@fatkodima]: https://github.com/fatkodima +[@koic]: https://github.com/koic +[@tldn0718]: https://github.com/tldn0718 +[@lukasfroehlich1]: https://github.com/lukasfroehlich1 +[@earlopain]: https://github.com/earlopain +[@ccutrer]: https://github.com/ccutrer +[@amomchilov]: https://github.com/amomchilov