参照のあるモデルをviewから作る
ParentとChildの関係にあるモデルの作り方と簡単な使いかたを前回書いたが、では画面からそれらを登録していくにはどうすればいいか。
考えられる方法はとりあえず二つ
- 作成済みのParentのページにChildを作るリンクを作成する
- Childを新規作成するページで既存のParentを指定できるようにする
モデルは仮に以下のようにしておく
class Parent include Mongoid::Document field :name, :type => String field :age, :type => Integer references_many :child end class Child include Mongoid::Document field :name, :type => String field :age, :type => Integer referenced_in :parent end
1.についてはParentのObjectIDを引き渡せば良いと思われる。後は2.の途中からと同じ手順になるはず。
2.について、まずは(scaffoldで作った場合の)newをいじる。
Parentをプルダウンで選択するようにするには、selectを用いる。viewを全部書くと非常に面倒なので部分的に書くと、以下のような感じ。
form_for :child do |f| f.label :parent f.select :parent, Parent.all.map { |parent| [parent.name, parent.id] } end
意味は params[:child][:parent]に関するセレクタを[name, id]の組み合わせの配列で作成する、ということになる。
ここで、配列 [ [n1,m1], [n2,m2] ] が渡されたときのselectは「表示"n1"に対してvalue="m1", 表示"n2"に対してvalue="m2"」となり、上記の例で実際にparams[:child][:parent]に渡される値はparent.id(つまり選んだParentのBSON::Objectid)となる。
このままだと、controller側のChild.newで:parentが余計に含まれてしまい失敗してしまうので、:parentを消しつつ、対応するParentを呼び出して参照関係を作る。
@parent = Parent.criteria.id(params[:child][:parent]).first params[:child].delete(:parent) @child = Child.new(params[:child]) @parent.child << @child @child.save
諸々省略したが、これで参照を作る事ができる。