このブログをご覧のみなさん、こんにちは。
掲題の通り、ActiveRecord::Enum
の使い方と重複エラーの避け方をご紹介します。
Environment
- OS: macOS Sierra
- Ruby: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]
- Gems
- rails (5.1.2)
- enum_help (0.0.17)
ActiveRecord::Enum の使い方
ActiveRecord::Enum を使うと、プログラムからは名前でアクセスでき、DB には整数値で保存できます。
class Student < ActiveRecord::Base
enum favorite_school_subject: { math: 1, science: 2 }
end
$ rails console
> student = Student.create(favorite_school_subject: 1)
=> #<Student …, favorite_school_subject: "math", …>
> student.favorite_school_subject
=> "math"
> student.favorite_school_subject_before_type_cast
=> 1 # レコードに設定されている値
> student.favorite_school_subject = 2
> student.favorite_school_subject
=> "science"
ActiveRecord::Enum の重複エラー
好きな教科があるので、嫌いな教科を追加しましょう。
class Student < ActiveRecord::Base
enum favorite_school_subject: { math: 1, science: 2 }
enum disliked_school_subject: { math: 1, science: 2 }
end
しかし、このコードは、同じ名前(math, science)を二回使っているため、以下のエラーが発生します。
ArgumentError:
You tried to define an enum named "disliked_school_subject" on the model "Student", but this will generate a instance method "math?", which is already defined by another enum.
従って、以下のように名前が被らないようにしなければなりません。
class Student < ActiveRecord::Base
enum favorite_school_subject: { favorite_math: 1, favorite_science: 2 }
enum disliked_school_subject: { disliked_math: 1, disliked_science: 2 }
end
しかし、この方法では、以下のように理解し易いコードではなくなってしまいます。
$ rails console
> student = Student.create(favorite_school_subject: 1)
=> #<Student …, favorite_school_subject: "favorite_math", …>
> student.favorite_school_subject
=> "favorite_math"
> student.favorite_school_subject_before_type_cast
=> 1 # レコードに設定されている値
> student.favorite_school_subject = 2
> student.favorite_school_subject
=> "favorite_science"
ActiveRecord::Enum の重複エラーの避け方
enum
には _prefix
, _suffix
というオプションがあり、接頭辞、接尾辞の指定が可能です。
このオプションを使うと、以下のように理解し易く、スッキリしたコードが書けます。
class Student < ActiveRecord::Base
enum favorite_school_subject: { math: 1, science: 2 }, _prefix: true
enum disliked_school_subject: { math: 1, science: 2 }, _prefix: true
end
$ rails console
> student = Student.create(favorite_school_subject: 1)
=> #<Student …, favorite_school_subject: "math", …>
> student.favorite_school_subject
=> "math"
> student.favorite_school_subject_before_type_cast
=> 1 # レコードに設定されている値
> student.favorite_school_subject = 2
> student.favorite_school_subject
=> "science"