rubocop / rubocop-rails

A RuboCop extension focused on enforcing Rails best practices and coding conventions.
https://docs.rubocop.org/rubocop-rails
MIT License
801 stars 257 forks source link

Cop to detect deprecated enums with keyword arguments #1238

Closed yahonda closed 3 days ago

yahonda commented 6 months ago

Is your feature request related to a problem? Please describe.

Rails main branch raises DEPRECATION WARNING: Defining enums with keyword arguments is deprecated and will be removed in Rails 7.3 since https://github.com/rails/rails/pull/50987 I'd like have some cops to detect and address these warnings.

Describe the solution you'd like

I'd like have some cops to detect and auto-correct these warnings.

Describe alternatives you've considered

Follow the warning and fix each enum definition manually.

DEPRECATION WARNING: Defining enums with keyword arguments is deprecated and will be removed
in Rails 7.3. Positional arguments should be used instead:

enum :status, [:active, :archived]
 (called from <class:Conversation> at foo.rb:34)

Additional context

Here is a sample ruby script to reproduce this warning.

gemfile(true) do source "https://rubygems.org"

git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem "rails", github: "rails/rails", branch: "main" gem "sqlite3" end

require "active_record" require "minitest/autorun" require "logger"

This connection will do for database-independent bug reports.

ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do create_table :conversations, force: true do |t| t.column :status, :integer, default: 0 end end

good

enum :status, [ :active, :archived ]

bad

enum status: [ :active, :archived ]

class Conversation < ActiveRecord::Base enum status: [ :active, :archived ] end

class BugTest < Minitest::Test def test_association_stuff conversation = Conversation.create! assert conversation.active? refute conversation.archived? end end


- Run the foo.rb
```ruby
$ ruby foo.rb
Fetching https://github.com/rails/rails.git
Fetching gem metadata from https://rubygems.org/..........
Resolving dependencies...
-- create_table(:conversations, {:force=>true})
D, [2024-02-14T13:48:22.489739 #201147] DEBUG -- :    (2.0ms)  DROP TABLE IF EXISTS "conversations"
D, [2024-02-14T13:48:22.490110 #201147] DEBUG -- :    (0.1ms)  CREATE TABLE "conversations" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "status" integer DEFAULT 0)
   -> 0.0089s
D, [2024-02-14T13:48:22.491160 #201147] DEBUG -- :    (0.1ms)  CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY)
D, [2024-02-14T13:48:22.492450 #201147] DEBUG -- :    (0.1ms)  CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL)
D, [2024-02-14T13:48:22.508765 #201147] DEBUG -- :   ActiveRecord::InternalMetadata Load (1.0ms)  SELECT * FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? ORDER BY "ar_internal_metadata"."key" ASC LIMIT 1  [[nil, "environment"]]
D, [2024-02-14T13:48:22.509110 #201147] DEBUG -- :   ActiveRecord::InternalMetadata Create (0.1ms)  INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ('environment', 'development', '2024-02-14 04:48:22.508832', '2024-02-14 04:48:22.508838') RETURNING "key"
DEPRECATION WARNING: Defining enums with keyword arguments is deprecated and will be removed
in Rails 7.3. Positional arguments should be used instead:

enum :status, [:active, :archived]
 (called from <class:Conversation> at foo.rb:32)
Run options: --seed 37140

# Running:

D, [2024-02-14T13:48:22.615934 #201147] DEBUG -- :   TRANSACTION (0.0ms)  begin transaction
D, [2024-02-14T13:48:22.616119 #201147] DEBUG -- :   Conversation Create (0.3ms)  INSERT INTO "conversations" DEFAULT VALUES RETURNING "id"
D, [2024-02-14T13:48:22.617499 #201147] DEBUG -- :   TRANSACTION (0.0ms)  commit transaction
.

Finished in 0.009117s, 109.6865 runs/s, 219.3730 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips
$
yahonda commented 6 months ago

Here are the example of good and bad ones.

class Conversation < ActiveRecord::Base
  enum :status, [ :active, :archived ]
end
yahonda commented 5 months ago

This good syntax like enum :status, [ :active, :archived ] has been introduced since Rails 7.0 via https://github.com/rails/rails/pull/41328 . Using this syntax for Rails 6.1 raises `enum': wrong number of arguments (given 2, expected 1) (ArgumentError)

gemfile(true) do source "https://rubygems.org"

git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem "rails", "~> 6.1.0" gem "sqlite3" end

require "active_record" require "minitest/autorun" require "logger"

This connection will do for database-independent bug reports.

ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do create_table :conversations, force: true do |t| t.column :status, :integer, default: 0 end end

good

enum :status, [ :active, :archived ]

bad

enum status: [ :active, :archived ]

class Conversation < ActiveRecord::Base enum :status, [ :active, :archived ] end

class BugTest < Minitest::Test def test_association_stuff conversation = Conversation.create! assert conversation.active? refute conversation.archived? end end $


```ruby
$ ruby foo1238_61.rb 
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
/home/yahonda/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/activesupport-6.1.7.7/lib/active_support/message_verifier.rb:3: warning: base64 was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add base64 to your Gemfile or gemspec. Also contact author of activesupport-6.1.7.7 to add base64 into its gemspec.
/home/yahonda/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/activesupport-6.1.7.7/lib/active_support/dependencies.rb:332: warning: bigdecimal was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add bigdecimal to your Gemfile or gemspec. Also contact author of activesupport-6.1.7.7 to add bigdecimal into its gemspec.
/home/yahonda/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/activesupport-6.1.7.7/lib/active_support/dependencies.rb:332: warning: mutex_m was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec. Also contact author of activesupport-6.1.7.7 to add mutex_m into its gemspec.
-- create_table(:conversations, {:force=>true})
D, [2024-03-01T08:10:27.313045 #31274] DEBUG -- :    (0.7ms)  SELECT sqlite_version(*)
D, [2024-03-01T08:10:27.313384 #31274] DEBUG -- :    (0.0ms)  DROP TABLE IF EXISTS "conversations"
D, [2024-03-01T08:10:27.313743 #31274] DEBUG -- :    (0.1ms)  CREATE TABLE "conversations" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "status" integer DEFAULT 0)
   -> 0.0053s
D, [2024-03-01T08:10:27.332203 #31274] DEBUG -- :    (0.1ms)  CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL)
D, [2024-03-01T08:10:27.340223 #31274] DEBUG -- :   ActiveRecord::InternalMetadata Load (1.2ms)  SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ?  [["key", "environment"], ["LIMIT", 1]]
D, [2024-03-01T08:10:27.343119 #31274] DEBUG -- :   TRANSACTION (0.0ms)  begin transaction
D, [2024-03-01T08:10:27.343314 #31274] DEBUG -- :   ActiveRecord::InternalMetadata Create (0.1ms)  INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["key", "environment"], ["value", "development"], ["created_at", "2024-02-29 23:10:27.342793"], ["updated_at", "2024-02-29 23:10:27.342793"]]
D, [2024-03-01T08:10:27.343453 #31274] DEBUG -- :   TRANSACTION (0.0ms)  commit transaction
/home/yahonda/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/activerecord-6.1.7.7/lib/active_record/enum.rb:158:in `enum': wrong number of arguments (given 2, expected 1) (ArgumentError)
        from foo1238_61.rb:32:in `<class:Conversation>'
        from foo1238_61.rb:31:in `<main>'
$
yahonda commented 5 months ago

This good syntax like enum :status, [ :active, :archived ] works as expected for Rails 7.0.z

$ more foo1238_70.rb 
require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "rails", "~> 7.0.0"
  gem "sqlite3"
end

require "active_record"
require "minitest/autorun"
require "logger"

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :conversations, force: true do |t|
    t.column :status, :integer, default: 0
  end
end

# good
# enum :status, [ :active, :archived ]
# bad
# enum status: [ :active, :archived ]

class Conversation < ActiveRecord::Base
  enum :status, [ :active, :archived ]
end

class BugTest < Minitest::Test
  def test_association_stuff
    conversation = Conversation.create!
    assert conversation.active?
    refute conversation.archived?
  end
end
$ ruby foo1238_70.rb
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
/home/yahonda/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/activesupport-7.0.8.1/lib/active_support/message_verifier.rb:4: warning: base64 was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add base64 to your Gemfile or gemspec. Also contact author of activesupport-7.0.8.1 to add base64 into its gemspec.
/home/yahonda/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/activesupport-7.0.8.1/lib/active_support/core_ext/object/json.rb:5: warning: bigdecimal was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add bigdecimal to your Gemfile or gemspec. Also contact author of activesupport-7.0.8.1 to add bigdecimal into its gemspec.
/home/yahonda/.rbenv/versions/3.3.0/lib/ruby/gems/3.3.0/gems/activesupport-7.0.8.1/lib/active_support/notifications/fanout.rb:3: warning: mutex_m was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec. Also contact author of activesupport-7.0.8.1 to add mutex_m into its gemspec.
-- create_table(:conversations, {:force=>true})
D, [2024-03-01T08:14:12.901063 #32048] DEBUG -- :    (0.0ms)  DROP TABLE IF EXISTS "conversations"
D, [2024-03-01T08:14:12.901388 #32048] DEBUG -- :    (0.1ms)  CREATE TABLE "conversations" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "status" integer DEFAULT 0)
   -> 0.0048s
D, [2024-03-01T08:14:12.920747 #32048] DEBUG -- :    (0.1ms)  CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL)
D, [2024-03-01T08:14:12.928217 #32048] DEBUG -- :   ActiveRecord::InternalMetadata Load (0.9ms)  SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ?  [["key", "environment"], ["LIMIT", 1]]
D, [2024-03-01T08:14:12.931977 #32048] DEBUG -- :   TRANSACTION (0.0ms)  begin transaction
D, [2024-03-01T08:14:12.932172 #32048] DEBUG -- :   ActiveRecord::InternalMetadata Create (0.1ms)  INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["key", "environment"], ["value", "development"], ["created_at", "2024-02-29 23:14:12.931327"], ["updated_at", "2024-02-29 23:14:12.931327"]]
D, [2024-03-01T08:14:12.932288 #32048] DEBUG -- :   TRANSACTION (0.0ms)  commit transaction
Run options: --seed 13734

# Running:

D, [2024-03-01T08:14:12.959906 #32048] DEBUG -- :   TRANSACTION (0.0ms)  begin transaction
D, [2024-03-01T08:14:12.960012 #32048] DEBUG -- :   Conversation Create (0.0ms)  INSERT INTO "conversations" DEFAULT VALUES
D, [2024-03-01T08:14:12.960120 #32048] DEBUG -- :   TRANSACTION (0.0ms)  commit transaction
.

Finished in 0.003686s, 271.2821 runs/s, 542.5642 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips
$