enumっぽいこと
ActiveRecordでenum型ってサポートされてないのかなーと色々調べたけど、どうやら未実装みたい。validates_inclusion_ofによるチェックは可能だけど、そこでの定義とform_tagでのselectタグとをどうやって同期取るんだ、みたいなことになってしまう。
で、enumerations_mixinというプラグインを発見。これを使って、大体目的は達成できた。
テーブル定義
自分はGenericEnumというモデルをmigrateで定義した。
create_table :generic_enums, :force => true do |t| t.column :name, :string t.column :category, :string t.column :position, :integer, :default => 1 end
クラス定義
Enumごとにクラスを増やしてしまうと部屋が散らかるので、virtual_enumerationsってのを使う。config/virtual_enumerations.rbを編集すればよい。こんな感じ。
ActiveRecord::VirtualEnumerations.define do |config| config.define 'OccupationCategory', :table_name => 'generic_enums', :conditions => ['category = ?', "occupation_category"], :order => 'position ASC' end
データを作るにはMySQLを直接操作しても良いけど、やっぱりmigrateを使うのが便利。ただし、enumeration_model_updates_permittedをtrueにしてやらないと値の挿入や変更はできない(みたい)。そうしないと処理中にenumの値が変わるというヘンテコな状態になるからでしょ。
GenericEnum.enumeration_model_updates_permitted = true GenericEnum.create( :name => 'CEO/CIO', :category => 'occupation_category', :position => 1 ) GenericEnum.create( :name => 'VP', :category => 'occupation_category', :position => 2 )
enumを使う
あとは他のモデルからこのenumを自由に使える。
class Customer < ActiveRecord::Base has_enumerated :occupation, :class_name => 'OccupationCategory', :foreign_key => 'occupation_id' end
もちろん、この場合のcusomersテーブルにはoccupation_idを用意しておく必要がある。そして
customer.occupation = Occupation['CEO/CIO']
みたいに使える。
formから使う
コントローラで
@occupations = Occupation.all.collect {|p| [p.name, "#{p.id}"]}
と用意しておいて、フォームで
<%= select('customer', 'occupation_id', @occupations) %>
みたいにすれば、select要素を簡単に作れる。
明日はset型の報告。