Rails 4.1からActiveRecordでenumが扱えるようになったので、Gemを追加することなく、enum
が使えるようになっています。enum型あるいは列挙型は、カラムの値が固定値の場合に、値を文字列として扱うことができるので、効率よくデータを格納したり検索できるようになります。今回はinteger型と、boolean型を列挙型にして、enum_helpというGemを利用して多言語対応していきます。さらにsimple_formと合わせることで、viewsを簡素化することができます。
EnumHelp
https://github.com/zmbacker/enum_help
SimpleForm
https://github.com/plataformatec/simple_form
環境はこちらです
1 2 3 4 |
ruby 2.5.1 rails 5.1.6 enum_help 0.0.17 simple_form 4.0.1 |
準備
必要なgemはこちらです。
1 2 |
gem 'enum_help' gem 'simple_form' |
$ bundle します。
simple_form を使う場合は次のコマンドでインストールします。
1 |
$ rails g simple_form:install |
列挙型にする対象のカラムを生成します。
1 |
$ rails g migration add_age_to_users age:integer |
カラムにデフォルト値を入れておきます。
db/migrate/20xxxxxxxxx_add_age_to_users.rb
1 2 3 4 5 6 |
class AddAgeToUsers < ActiveRecord::Migration[5.1] def change add_column :users, :age, :integer, default: 0 add_column :users, :message, :boolean, default: true, null: false end end |
$ rails db:migrate します。
モデル
integer値とboolean値にそれぞれ、文字列を指定します。age_privateとしているのは、privateのみだと、他のメソッドでも使う可能性があるので、多重定義でエラーにならないためにユニークなメソッド名にしています。名前は重複しないように注意が必要です。
app/models/user.rb
1 2 3 4 5 6 |
class User < ApplicationRecord enum age: { age_private: 0, under19: 1, twenty: 2, thirty: 3, forty: 4, fifty: 5, sixty: 6, up70: 7 } enum message: { receive: true , not_receive: false } end |
ロケール
localファイルにenums以下を記述します。
config/locales/ja.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
ja: enums: user: age: age_private: 非公開 under19: 19歳以下 twenty: 20~29歳 thirty: 30~39歳 forty: 40~49歳 fifty: 50~59歳 sixty: 60~69歳 up70: 70歳以上 message: receive: 受け取る not_receive: 受け取らない |
ビュー
simple_formを使っている場合のviewsはこのようになります。ちなみにinclude_blankはセレクトメニューの先頭に文字を入れることができます。
_form.html.erb
1 2 3 4 5 6 7 8 9 |
<%= simple_form_for @user do |f| %> <%= f.input :age, include_blank: false %> <%= f.input :message, as: :radio_buttons %> <%= f.button :submit %> <% end %> |
viewsで値を受け取る時は_i18nを付与します。
show.html.erb
1 2 |
<%= @user.age_i18n %> <%= @user.message_i18n %> |
コンソールで確認
コンソールで見ると文字列として格納されているのが確認できます。
1 2 3 4 5 6 |
irb(main):002:0> User.find(2).age User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]] => "up70" irb(main):003:0> User.find(2).message User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]] => "not_receive" |
これで可読性も向上しますし、文字列なので検索しやすくなります。
今回は以上です!ご覧いただき、ありがとうございました!!☺️