はじめに
初めまして、Railsを勉強中のものです。
現在SNSアプリを開発中です。
よくある投稿機能や出品機能などに持たせるカラムとして、あらかじめ用意した値の中から選択させる属性を扱う場合enum
が便利だと色んな記事で見てたのですが、
思っていたよりすんなり実装できなかったので初めてenum
を使う方の参考になればと思い記録しておきます。
あくまで私が実装した内容を載せるだけなので、細かい説明は参考にしたリンクを貼っておきますのでそちらをご参照ください。
実装する内容
ユーザー情報に持たせるカラムとして、性別と年齢をenum
を使って実装していきます。
Railsのバージョンは5.2.4
です。今回はhaml
で書いてます。
それではやってみましょう。
enumで値を定義する
まずはマイグレーションファイルから。
enum
を使うカラムはinteger
型で用意します。
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :nickname, null: false
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
t.string :profile, null: false
# 型はintegerにする
t.integer :gender, default: 0
t.integer :age, default: 0
# .省略
end
end
初めオプションはnull :false
にしてました。今回はそれでも問題はなかったのですが、他の記事を見るとどれもdefault: 0
で設定してたのと、公式ではこちらが推奨されてるみたいなので直しました。
次にモデルで実際にデータを用意します。
class User < ApplicationRecord
enum gender: { gender_private: 0, male: 1, female: 2, others: 3 }
enum age: { age_private: 0, teens: 1, twenties: 2, thirties: 3, forties: 4, fifties: 5, over_sixties: 6 }
end
配列で定義してる方もいました。
class User < ApplicationRecord
enum gender: [ :gender_private, :male, :female, :others ]
enum age: [ :age_private, :teens, :twenties, :thirties, :forties, :fifties, :over_sixties ]
end
どちらでも大丈夫ですが、配列の場合対応する数字が自動で0から順になるということだけ注意が必要です。
他のカラムと区別したり、わかりやすくするために1、10、20などの数字にする方もいるみたいです。その場合はハッシュで書くしかないですね。
viewでフォームを実装する
次にフォームの実装です。
私はセレクトボックス で用意しました。
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
.field
= f.label :gender
%br/
= f.select :gender, options_for_select_from_enum(User, :gender)
.field
= f.label :age
%br/
= f.select :age, options_for_select_from_enum(User, :age)
フォームの実装はいろいろな書き方があると思いますが、私の場合
ArgumentError ('2' is not a valid gender):
というエラーが出てしまい、色々試した結果最終的に上の書き方になりました。
同じエラーに当たった方は、こちらの記事が詳しく書いてありました。
enumを使うとArgumentError in TasksController#create => '2' is not a valid status_id
これでenum
を使って性別と年齢を登録できるようになりましたが、現状セレクトボックスに表示されるのは英語のままになっています(age_private、teens、twenties ...)
プルダウンの表示を日本語化する
こちらもいくつかやり方があるみたいです。
gemを使う方法もあるみたいですが今回は別の方法で実装します。
こちらの記事を参考にさせてもらいました。
というかまんまこの通りやりました。
ちなみにgemを使う方法はこちらに書いてあります。
【初心者向け】i18nを利用して、enumのf.selectオプションを日本語化する[Rails]
ja.ymlファイルの作成
まず、i18機能で日本語設定をしていない場合はファイルを用意する必要があります。
#rails5系
gem 'rails-i18n', '~> 5.1'
#rails4系
gem 'rails-i18n', '~> 4.0'
こちらのgemを導入、もしくは
svenfuchs/rails-i18n
こちらのファイルをコピーして、config/locales/ja.yml
ファイルを作ります。
そのファイルにenum
で定義した値を日本語に変換させるのための記述をします。
:ja
#省略
enums:
user:
gender:
gender_private: "非公開"
male: "男性"
female: "女性"
others: "他"
#省略
デフォルトの言語を日本語化
次にapplication.rb
でデフォルトの言語を日本語化するための設定です。
module SnsApp
class Application < Rails::Application
#省略
#追記
config.i18n.default_locale = :ja
config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
#省略
end
end
これで先程のja.yml
ファイルが読み込まれます。
そしてもう一つファイルを作ります。
##Helperメソッドを用意する
app/helpers
の下にファイルを作ります。
module EnumHelper
# クラスオブジェクトとカラム名を引数として呼ばれるコールバック関数です
def options_for_select_from_enum(klass,column)
#該当クラスのEnum型リストをハッシュで取得
enum_list = klass.send(column.to_s.pluralize)
#Enum型のハッシュリストに対して、nameと日本語化文字列の配列を取得(valueは使わないため_)
enum_list.map do | name , _value |
# selectで使うための組み合わせ順は[ 表示値, value値 ]のため以下の通り設定
[ t("enums.#{klass.to_s.downcase}.#{column}.#{name}") , name ]
end
end
end
上の記事から丸ごと頂きました。
これでプルダウンの日本語も完了です!
#最後に
今回はenumを使った実装方法を書きましたが、他に都道府県のカラムも欲しかったのでそちらはactive_hash
で実装しました。
使い勝手も実装のしやすさもactive_hash
の方が楽なのですが、性別など2個か3個しかない値のためにモデルをいっぱい作るのも無駄なような感じがしたのと、
大体皆さん性別はenum
で実装してる方が多いみたいなので今回使ってみました。
実際覚えてしまえば使う場面はいっぱいあると思うので、必要に応じて積極的に使っていこうと思います。
私が書いたやり方でうまくいかなかった方は、今回参考にした記事をまとめておきますので色々見て見てください!
また、無駄な記述や間違った認識などがありましたらご指摘いただけるとありがたいです!
#参考にした記事
Ruby on Rails:ModelのプロパティにEnumを使う※おまけ:ラジオボタンでEnumを扱う
enumを使うとArgumentError in TasksController#create => '2' is not a valid status_id
【初心者向け】i18nを利用して、enumのf.selectオプションを日本語化する[Rails]
[[初学者]Railsのi18nによる日本語化対応]
(https://qiita.com/shimadama/items/7e5c3d75c9a9f51abdd5)