すんごい基礎的な内容なのですが、2通りのやり方に出会ったので整理したかったのと、地味なとこでハマったので備忘録。
やりたいこと
Postモデルにstatusというenumがあるとする。
class Post < ApplicationRecord
enum status: { active: 10, inactive: 20 }, _prefix: true
end
htmlはこう。ブラウザで見える文字列とvalue属性を渡してあげたい。
<select class="form-control" name="post[status]" id="post_status">
<option selected="selected" value="active">有効</option>
<option value="inactive">非有効</option>
</select>
selectの出力にはRailsのselectメソッドを使う。
https://railsdoc.com/page/select
# f.object
f.select(メソッド名, 要素(配列 or ハッシュ)=nil, オプション={}, HTML属性={} or イベント属性={}, ブロック引数)
第二引数には以下のようなハッシュ、もしくは配列を渡してあげれば良い。
# { "ブラウザで見える文字列"=>"value属性" }
=> {"有効"=>"active", "非有効"=>"inactive"}
1. gemを使わず自分でメソッドを作るやり方
こちらを参照しました。gemを無闇に使いたくないならこれ。
config/locales
ja:
activerecord:
attributes:
post/status:
active: 有効
inactive: 無効
view
<%= f.select(:status, Post.status_options, {}, class: 'form-control') %>
app/models/post.rb
def self.status_options
statuses.map { |k, _| [human_attribute_enum_value(:status, k), k] }.to_h
end
def self.human_attribute_enum_value(attr_name, value)
human_attribute_name("#{attr_name}.#{value}")
end
def human_attribute_enum(attr_name)
self.class.human_attribute_enum_value(attr_name, self[attr_name])
end
2. gem使う。 "exnum"でやる。
exnumはこちら。
https://github.com/Kta-M/exnum#array-for-select-box-extention
Gemfile
gem 'exnum'
↓ここが地味にハマった。enum
をexnum
にしないといけない。
app.models/post.rb
exnum status: { active: 10, inactive: 20 }, _prefix: true
config/locales/
ja:
activerecord:
enum:
post:
status:
active: 有効
inactive: 非有効
ここまですると以下のようなメソッドが使える。
[1] pry(main)> Post.statuses_i18n
=> {"active"=>"有効", "inactive"=>"非有効"}
[2] pry(main)> Post.statuses_i18n.invert
=> {"有効"=>"active", "非有効"=>"inactive"}
[3] pry(main)> Post.statuses_for_select
=> [["有効", "active"], ["非有効", "inactive"]]
これ↑の1だとブラウザで見える文字列とvalue属性が逆になっちゃうので、2か3をselectの引数に渡してあげればOK。
view
<%= f.select(:status, Post.statuses_i18n.invert, {}, class: 'form-control') %>
どっちにするんだい!?
modelに色々メソッドとか書きたくないので、gem使う方に一票。