【Rails】enumで特定の値を選択肢から省きたい
きむらです。またもやenum関連ですがちょっとなるほどと思ったことがあったので備忘録。
enumに設定している値を全て取り出す
例えばセレクトボックスに選択肢としてenumに設定している値を出す場合などによく使うとおもいます。
# blogというモデルに公開範囲(非公開、公開、一部に公開)のようなステータスがある想定 class Blog < ActiveRecord::Base enum status: { unpublish: 0, publish: 1, part_publish: 2 } end # enumに設定したstatusの状態をすべて取得する Blog.statuses => {"unpublish"=>0, "publish"=>1, "part_publish"=>2}
てな感じでモデル.enumを設定した属性の複数系
と書くことでenumに設定した値を取得することができます!
これを使えばブログの公開範囲選択セレクトボックスを作成するのが簡単になったりします!
enumに設定している特定の値だけを取得したい
便利とはいえ特定の状態だけを選択させたくなるときもあります。
例えば一部に公開(part_publish)を特定の箇所では選択肢に入らないようにしたいとか
そんなときはslice
やexcept
を使うと幸せになれます!
sliceを使ってpart_publishを省く
Blog.statuses.slice(:unpublish, :publish) => {"unpublish"=>0, "publish"=>1}
slice
を用いると引数に指定した値だけを取り出すことができます。
特定の値を省くというより、特定の値だけを取り出すという感じですね!
exceptを使ってpart_publishを省く
Blog.statuses.except(:part_publish) => {"unpublish"=>0, "publish"=>1}
except
を用いると引数に指定した値は取得しないようになります!
省くという意味合いではexcept
の方が正しそうですね。
といった感じで簡単にenumに設定した特定の値だけを取得できるようになります!
これらを使ってクラスメソッドなんか作ってあげるとスマートっぽい気がしますね!
class Blog < ActiveRecord::Base enum status: { unpublish: 0, publish: 1, part_publish: 2 } def self.restrict_statuses statuses.except(:part_publish) end end Blog.restrict_statuses => {"unpublish"=>0, "publish"=>1}
slice、exceptは何者か
この二つはActiveSupport
のメソッドのようです!
enumを設定して設定内容を取得したもののクラスが以下にになります!
Blog.statuses.class => ActiveSupport::HashWithIndifferentAccess
つまりBlog.statuses
で取得できるものはハッシュってことになります。
RailsだとハッシュはActiveSupport
パイセンの力でちょいちょい強化されていて、その強化された力を用いることで割と簡単にハッシュ操作ができたりします…。slice
、except
はその力の一部であるということです…。
ほんとActiveSupport、ActiveRecordあたりはよしなにいろんなことをやってくれるので便利すぎるなあという気持ちになります。
最近RailsのよしなにしてくれるところにあぐらかいてRuby力がなくなってきている(そもそもそんなにない)ので、その辺鍛え直さないとなあ…。