2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】Rails 8.0 における enum の基本的な使い方

Posted at

はじめに

学習内容のアウトプットのため、Rails 8.0 で簡単なプロジェクト管理アプリを作成していたところ、enum定義の仕方が変更されていたことに気づかず、エラー解決まで時間を要してしまいました。そこで、今回学んだ事を踏まえ、改めてenumの使い方をおさらいし、備忘録として残しておきたいと思います。

この記事でわかること

  • Rails 8.0 以降のenumの基本的な使い方

この記事の対象者

  • enumって何?と思った初学者の方
  • 今まで通りenumを使っていたはずなのにエラーが出てしまった方

列挙型(enum)とは?

列挙型(enum)は、あらかじめ定義された一連の定数値を名前付きで管理するデータ型です。
Railsでは、モデルにenumを定義することで、ステータスや種類などの限られた選択肢しか取らない値に意味のある名前を付けて管理することができます。

動作概要

前提

Taskモデルを例に説明していきます。tasksテーブルは、タスクの名前である title カラムと、タスクの状態を表す status カラムを持っています。

マイグレーションファイルは以下のようになっていて、enumで管理する status カラムは integer型 を指定します。

class CreateTasks < ActiveRecord::Migration[8.0]
  def change
    create_table :tasks do |t|
      t.string :title, null: false
      t.integer :status, default: 0, null: false

      t.timestamps
    end
  end
end

定義

modelファイルで定義します。

  • Rails 8.0

Rails 8.0 では、第一引数対象とする属性名を指定します。

task.rb
class Task < ApplicationRecord
  enum :status, { incomplete: 0, in_progress: 1, complete: 2 }
end
  • Rails 7.2 以前

task.rb
class Task < ApplicationRecord
  enum status: { incomplete: 0, in_progress: 1, complete: 2 }
end

私は最初こちらの記述で書いていたために下記のようなエラーが発生していました。

irb(main):001:0> Task.create!(title: "Sample Task", status: :incomplete)
app/models/task.rb:2:in `<class:Task>': wrong number of arguments (given 0, expected 1..2) 

Rails 7.2 では、キーワード引数の使用による列挙型の定義は非推奨との事で警告メッセージが表示されるようです。

使い方

  • 状態に応じたデータを取得する場合

enum を利用すると、指定した値に対応するデータを取得するスコープが自動生成されます。

# モデル名.キー名
Task.incomplete     # => status が "incomplete" のレコードを取得
Task.in_progress    # => status が "in_progress" のレコードを取得
Task.complete       # => status が "complete" のレコードを取得
  • enum の定義を参照する場合

statuses のように属性名を複数形にして使用すると enum の定義を確認でき、キー(シンボルまたは文字列)と対応する値(整数)を使った処理や一覧の取得も簡単に行えます。

Task.statuses
=> {"incomplete"=>0, "in_progress"=>1, "complete"=>2}
Task.statuses.keys
=> ["incomplete", "in_progress", "complete"]
Task.statuses.values
=> [0, 1, 2]
Task.statuses[:incomplete]
=> 0
  • オブジェクトの状態を判定する場合

「キー名 + ?」 で生成されるメソッドを使用することで、特定のレコードの状態を判定できます。

task = Task.create!(title: "first task", status: "in_progress")

task.incomplete?
=> false
task.in_progress?
=> true
  • 現在の状態を取得する場合

enum の値は、整数、文字列、またはシンボルとして設定可能で、モデル内ではキー名が文字列として保持されます。

task1 = Task.create!(title: "task1", status: 0)
task1.status
=> "incomplete"

task2 = Task.create!(title: "task2", status: "incomplete") 
task2.status
=> "incomplete"

task3 = Task.create!(title: "task3", status: :incomplete)
task3.status
=> "incomplete"

値を文字列ではなく数値で取得したい場合は以下を使用します。

  • [属性名]_before_type_cast
  • [属性名]_for_database
  • read_attribute_before_type_cast()
  • read_attribute_before_type_cast()

[属性名]_before_type_cast は型変換前の値を取得し、[属性名]_for_database はデータベースに保存される値を取得するものです。

task1.status_before_type_cast
=> 0
task1.status_for_database
=> 0

# 引数には文字列かシンボルを渡す
task1.read_attribute_before_type_cast(:status)
=> 0
task1.read_attribute_for_database("status")
=> 0

# 前者と後者の違いは、存在しない属性を指定したときに"nil"になるか"例外"が発生するかどうか
task1.read_attribute_before_type_cast(:other_status)
=> nil
task1.other_status_before_type_cast
=> "NoMethodError"
  • オプションの使用

prefixsuffix オプションを使うと、メソッド名の衝突を避けることができ、名前の可読性を向上させることができます。これは特に同じモデル内で似たような名前のメソッドが多い場合に有効です。

task.rb
class Task < ApplicationRecord
  enum :status, { incomplete: 0, in_progress: 1, complete: 2 }, prefix: :status
  # 下記も同様
  enum :status, { incomplete: 0, in_progress: 1, complete: 2 }, prefix: :true
end

これにより、status_complete? のようなメソッドが生成されます。

task = Task.create!(title: "task", status: "complete") 
task.status_complete?
=> true
task.status_incomplete?
=> false

Task.status_complete     # => status が "complete" のレコードを取得

suffix の場合も同様に、complete_status? といった具合で使用できます。
この prefixsuffix は同時に使うことも可能です。

なお、Rails 7.2 以前は、_prefix や _suffix のように _ を付けていましたが、Rails 8.0 ではエラーになるので注意しましょう。

おわりに

今回は Rails 8.0 における enum の基本的な使い方を振り返り、備忘録として記事をまとめました。初めての記事ということもあり、読みにくい箇所があったかもしれませんが、温かく見守っていただけると幸いです。また、内容に誤りがあったり、enum の発展的な活用方法をご存じの方がいれば、ぜひご意見をいただきたいです。

この記事が、新しく Rails を学び始めた方や、新しいバージョンで enum 周りの実装に悩んでいる方の助けになれば嬉しく思います!

参考URL

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?