collection_selectでの初期値設定

がっつりはまってしまった。

Railsにはcollection_selectという便利なメソッドが存在する。
こいつは、form_forメソッド内にドロップダウンリストを作成する際に利用すると、オブジェクトからドロップダウンへの表示項目とform_forへと送る値とを任意に指定できる優れもの。
実際の利用はこんな感じ。


<% form_for(@book) do |f| %>
<%= f.collection_select 'publisher_id', Publisher.find(:all), :id, :name %><% end %>

上記の例では、たとえばPublisher内に、nameが「小学館」「集英社」「講談社」、idは左から1,2,3というデータがあったとしたら、画面上には下のように表示される。
ここで「集英社」を選択すると、@bookのpublisher_idには 2 がセットされるといった処理になる。 このため、コードマスタ等に設定していたモデルから値を紐付けて取得することが非常に容易で、便利になる。 さて、ここからが今回の本題。 以下のようにすると、修正画面での初期表示がおかしくなる。

<% form_for(@book) do |f| %>
  <%= f.collection_select 'genre_id', Genre.find(:all), :id, :name %>
  <%= f.collection_select 'publisher_id', Publisher.find(:all), :id, :name %>
<% end %>
一つのform_forメソッド内に複数のcollection_selectメソッドを記述すると(たぶん)edit画面等の既に入力されている情報を取得する際に初期値が異なって指定される。 具体的に書くと以下のようなケースになる まず、genreにミステリー(idが2とする)publisherに講談社を指定して登録する。 DBにはgenre_idが2, publisher_idが2で登録される。 次にこのデータを変更しようと修正画面を開くと、genreにミステリー、publisherに小学館と表示される。 collection_selectの謎。 - railsでhogehogeを作ってみる。 このサイトの人なんかも、同様の事象に陥ったみたい。 初期値を任意に指定できないかを探したが、さっぱりだったのでselectメソッドを利用した。
<% form_for(@book) do |f| %>
  <%= f.select 'genre_id', @genre %>
<% end %>
コントローラでの記載は以下の通り。
genre = Genre.find(:all)
i = 0
while genre[i] != nil
  @genre << [genre[i].name, genre[i].id.to_i]
end
配列の入れ子を追加しているが、入れ子の2つ目の要素がStringの場合、どうも上手くいかなかった。 試しにto_iメソッドを利用すると上手く表示されるようになった。 無駄なコードが増えるが、仕方がないからこれでよいことにする。 後、コントローラでのコーディングがイケてない気がするけど、力尽きたので今日は以上。