はじめに
Rails 6 に追加されそうな新機能を試す第44段。 今回は、 enum
編です。
Rails 6 では、 enum
で指定する値が、Hash, シンボルの配列、文字列の配列以外の場合は、 ArgumentError が発生するようになりました。
わかりにくいバグを防ぐのが目的です。
Ruby 2.6.3, Rails 6.0.0.rc1, Rails 5.2.3 で確認しました。Rails 6.0.0.rc1 は gem install rails --prerelease
でインストールできます。
$ rails --version
Rails 6.0.0.rc1
プロジェクトを作る
bin/rails new rails6_0_0rc1
モデルを作る
bin/rails g model Child name generation:integer
Child モデルに enum を追加する
ここで、わざとバグになる紛らわしい enum を設定します。
class Child < ApplicationRecord
enum generation: [baby: 0, toddler: 1, preschool: 2, gradeschool: 3, teen: 4, young_adult: 5]
end
rake db:migrate を実行する
$ bin/rake db:create db:migrate
Rails 6 では
rails console
で Child
のインスタンスを作ろうとすると ArgumentError
が発生します。
$ bin/rails c
...
irb(main):001:0> c = Child.new
Traceback (most recent call last):
3: from (irb):1
2: from app/models/child.rb:1:in `<main>'
1: from app/models/child.rb:2:in `<class:Child>'
ArgumentError (Enum values [{:baby=>0, :toddler=>1, :preschool=>2, :gradeschool=>3, :teen=>4, :young_adult=>5}] must be either a hash, an array of symbols, or an array of strings.)
Rails 5 では
ArgumentError が発生しませんが、 generation に :baby を設定しようとするとエラーになります。
$ bin/rails c
irb(main):001:0> child = Child.new
=> #<Child id: nil, name: nil, generation: nil, created_at: nil, updated_at: nil>
irb(main):002:0> child.generation = :baby
Traceback (most recent call last):
1: from (irb):2
ArgumentError ('baby' is not a valid generation)
Child.generations で調べてみると設定できるのは、{ baby: 0, toddler: 1, preschool: 2, gradeschool: 3, teen: 4, young_adult: 5 }
だけとわかります。
enum で指定したのは、1つの Hash オブジェクトを要素とする配列になってしまっているためです。
irb(main):003:0> Child.generations
=> {{:baby=>0, :toddler=>1, :preschool=>2, :gradeschool=>3, :teen=>4, :young_adult=>5}=>0}
意図した動作にするには
以下のように []
で囲まないで、 {}
で囲めば、意図した通りの動作になります。
class Child < ApplicationRecord
enum generation: { baby: 0, toddler: 1, preschool: 2, gradeschool: 3, teen: 4, young_adult: 5 }
end
試したソース
試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try044_enum_validation