箱のプログラミング日記。

渋谷の自社開発企業でRails書いてます。

enumの使い方【Rails】

f:id:y_hakoiri:20191102121618j:plain

enumとは

railsの場合は標準機能としてモデルに記述することで使うことができる。

セレクトボックスから選ばせた値をDBに保存する時などに便利

 

わざわざDBにテーブルを作って保存しておくほどではない静的なデータも

ユーザーに任意の値を入力させたり、いくつもセレクトのオプションを作ったりするよりも

enumで数値に変換させてDBに保存させることで、保存される値を限定的に保つことができる。

 

モデルに記述

class Item < ApplicationRecord
 enum size:{ small: , middle: , large: }
end
 
基本的な構文は以下
enum カラム:{ 値1, 値2, 値3 }
何も指定しなくてもこのように前から順番に0,1,2...と番号が振られていくので
わざわざ明記する必要がないように思うが、明示しておいた方が良い
(後々値が追加された場合などにDBとの生合成を保てるように)
 
実際DBに保存されるのは数値
ビューで呼び出す時に文字列として表現することができる
 
 
ただデフォルトでは英語表記になっているので(モデルに直接日本語で書くことはできない)
日本語表記をしたい場合はja.ymlに記述して変換させる必要がある。
 

gemをインストール

gem 'enum_help'
 
日本語表記に使用するgemをインストール
bundle install後、サーバーを再起動
 

 ymlを作成

app/config/locals/にja.ymlを作成

ja:
 enums:
  item:
   size:
    small: Sサイズ
    middle: Mサイズ
    large: Lサイズ
 
 

ja.ymlを読み込み

app/config/apprcation.rb

class Application < Rails::Application
 config.i18n.default_locale = :ja
end
 
 

ビューで呼び出す

今回はセレクトボックスを使いました(form_for内、hamlで使用)

enumとセレクトボックスは併用することが多くなると思います

 

= f.select :size, Item.sizes_i18n.invert, {prompt: "---"}, {class: "select__box__format"}

分かりやすく分解すると以下

= f.select :カラム, Item.sizes_i18n.invert, {selectオプション}, {htmlオプション}

 

 

セレクトボックスの詳しい解説は以下が分りやすかったです

freesworder.net

  

 

ビューで呼び出す

今回はセレクトボックスを使いました(form_for内、hamlで使用)

enumとセレクトボックスは併用することが多くなると思います

 

= f.select :size, Item.sizes_i18n.invert, {prompt: "---"}, {class: "select__box__format"}

分かりやすく分解すると以下

= f.select :カラム, Item.sizes_i18n.invert, {selectオプション}, {htmlオプション}

 

 

Item.sizes_i18n.invertをもう少し分解

Item.sizes

enumを使用するとRailsのItem.newのようにインスタンスとして扱うことができるので
Item.sizesとするとItemモデルで定義したsizeのenum全部を呼び出すことができる 


コンソール

[1] pry(main)> Item.sizes

Creating scope :included. Overwriting existing method Post.included.

=> {"small"=>0, "middle"=>1, "large"=>2} 

 
_i18n

これは簡単。日本語化してるだけ

 

コンソール

[2] pry(main)> Item.sizes_i18n

=> {"small"=>"Sサイズ", "middle"=>"Mサイズ", "large"=>"Lサイズ"}

 
.invert
Railsのinvertメソッド
配列のキーとバリューを逆にしてくれる
 
コンソール

[3] pry(main)> Item.sizes_i18n.invert

=> {"Sサイズ"=>"small", "Mサイズ"=>"middle", "Lサイズ"=>"large"}

 
ここでf.selectに戻る

なんでinvertでキーとバリューを逆にする必要があるのかという話は

f.selectの引数に起因する。

 

f.selectの引数は以下

= f.select :カラム,  ["表示名","DBに保存する値"], {selectオプション}, {htmlオプション}

第一引数に保存先のカラム、第二引数にセレクトボックスで表示させる値たち

を指定する。 

 

[3] pry(main)> Item.sizes_i18n.invert

=> {"Sサイズ"=>"small", "Mサイズ"=>"middle", "Lサイズ"=>"large"}

こうすることで、セレクトボックスへの表示は日本語で表現し
DBにはsmallを保存しようとしてくれる
(実際にはenumを参照し、数値が保存される)
 
 
以下参照
 

_before_type_castが便利(2019/11/29追記)

enumで保存した値を後から取り出す時、数字のまま取り出したい場合は_before_type_cast が便利なのでメモ。
 
カラム名に繋げて_before_type_caseとすると、enumの数値のまま取り出すことができる。