Rails における Enum の挙動について調査した内容を備忘録として残しておく

環境

  • ruby: 2.7.6
  • rails: 5.2.8.1

実際のコード

DB のカラムに対応する enum を定義した場合、自動的に scope が定義される
※Rails 6 では not_* の scope も自動的に定義される 参考
※Rails 7 では新しい構文が追加されたため、今後オプションの指定が従来のやり方だと非推奨になる可能性がある 参考

[モデル定義]

class Article < ApplicationRecord
  enum status: {
    draft: 0,      # 下書き
    published: 1,  # 公開中
    closed: 2,     # 掲載終了
  }, _prefix: true
end

[Rails Console]

# enum 確認
Article.statuses
#=> {"draft"=>0, "published"=>1, "closed"=>2}

# scope
Article.status_published
#=> Article Load (7.8ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`status` = 1

# 以下と同義
Article.where(status: :published).to_sql
#=> "SELECT `articles`.* FROM `articles` WHERE `articles`.`status` = 1"

他にも以下のヘルパーが使用できる

article = Article.status_published.first

# status が published かどうか
article.status_published?
#=> true

# status を closed に更新
article.status_closed!
#=> TRANSACTION (0.5ms)  BEGIN
#=> Article Update (0.9ms)  UPDATE "articles" SET "status" = $1, "updated_at" = $2
#=> WHERE "articles"."id" #=>= $3  [["status", 2], ["updated_at", "2022-12-04 10:17:57.666814"], ["id", 1]]
#=> TRANSACTION (8.0ms)  COMMIT
#=> true

article
#=> <Article:0x000055a42ece8f38
#=> id: 1,
#=> name: "サンプル記事",
#=> status: "closed",
#=> created_at: Sun, 04 Dec 2022 10:10:22.903934000 UTC +00:00,
#=> updated_at: Sun, 04 Dec 2022 10:17:57.666814000 UTC +00:00>