読者です 読者をやめる 読者になる 読者になる

Single Table Inheritance を利用し、かつ、form_for では親クラスのコントローラーを使いたいとき

RoR

こんな人私の他にいるのかわからないけど、ハマったのでメモ。

前提

Fruit モデルを継承した Apple と Orange を Single Table Inheritance で実現する。

# app/models/fruit.rb
class Fruit < ActiveRecord::Base
   self.inheritance_column = :type
   〜省略〜

end

class Apple < Fruit 
   〜省略〜
end

class Orange < Fruit 
   〜省略〜
end

コントローラーは Fruitのものを共有する。

# config/routes.rb
resources :fruits
# app/controllers/fruits_controller.rb
class FruitsController < ApplicationController
  〜省略〜
 def edit  
 end

 def update
 end 
 〜省略〜
end

** Fruits#edit で form_forを使うと各モデルの専用コントローラーに飛ばされる

Bootstrap 3とRailsのフォームヘルパーを組み合わせるのが面倒なので[https://github.com/bootstrap-ruby/rails-bootstrap-forms:title=bootstrap-ruby/rails-bootstrap-forms]を使いたいのだけど、BootstrapFormは [http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for:title=form_for]の拡張。よって、app/views/fruits/edit.html.erb に以下のように書く。
>||
<%= bootstrap_form_for(@fruit) do | f |%>

<% end -%>

すると、@fruit が Fruitクラスのオブジェクトならば、データの送り先が fruit_path(@fruit) :method => "PATCH"(すなわちFruites#update) で、かつ、input タグのtypeもすべて fruit となってくれるのだけど、@fruit が Appleクラスのオブジェクトだと、apple_path(@fruit) :method => "PATCH"(すなわちApples#update) で、かつ、input タグのtypeもすべて apple になる。

## 解決法

url オプションと
as オプションで明示的に指定する。
<%= bootstrap_form_for(@fruit, :as => 'fruit', :url => {:controller => :fruits, :action => :update, :id => @fruit.id }) do | f |%>

<% end -%>

## 関連