ポリモーフィックなカラムのセレクトボックスを作る

rails4

ポリモーフィック(polymorphic)関連とは

UserモデルとPostモデルの両方にPhotoモデルを関連つけたい。
ユーザと記事は画像を持てる。みたいな時に
このポリモーフィック関連を使うといい感じに実装できる。(~ableにするのが慣習っぽい。)

使うには、Photoモデルに

photoable_type: string
photoable_id: integer

みたいなカラムが必要で、Photoモデルには『 photoable 』という名前でポリモーフィックするよという宣言が必要になる。

ポリモーフィックなカラムのセレクトボックスを作る

本題。
Photo編集画面から、UserモデルとPostモデルのレコードをどちらに属するかを選べる画面にしてみる。
通常の1対1の関連なら、idだけわかればいいので

f.select_collection :hoge_id

と書けるけど、ポリモーフィックだと○×_typeに入れるモデル名が必要になるので、そのままのselect_collectionではできない。
どうするかというと、セレクトボックスを変更した時に、hiddenなfiledにしている×○able_typeをセットする。

# _form.html.erb
      @photoables = Hoge.all + Foo.all
  @photo = Photo.find(1)
     ------------

      <%= f.select :photoable_id,
        options_for_select(@photoables.map{ |s| [s.name, s.id, {
          'data-resource_model' => s.class,
          'data-text' => s.name }]},
        {},
        { onchange: "setPhotoableType(this)" }
      %>
      <%= f.hidden_field :photoable_type, value: @photo.photoable_type %>

    <script>
      (function() {
        // セレクトボックスを選択中のもににフォーカスする
        var name = "<%= @photo.photoable.try(:name)  %>";
        $("#photo_ptohoable_id option[data-text=" + name + "]").attr('selected','selected');
      })();

      function setPhotoableType(select_input){
        $("#photo_photoable_type").val($(select_input.options[select_input.selectedIndex]).data('resource_model'));
      }
    </script>

newアクションの時だと、これで問題ないんだけどeditアクションだとセレクトボックスが初期値になる。
たぶんf.selectって第一引数のカラムとoptionのvalueに一致するものにフォーカスを変えるんだけど、
valueに重複があるから初期値のままになってるっぽい。
ここは強引だけどonloadでセレクトボックスのフォーカスをかえている。