独自FormBuilderを使うメモ

今更だけど、

```rhtml
<%= form_for @article do |f| %>
  <%= f.text_field :title %>
  <%= f.submit %>
<% end %>
```

こんな感じのフォームビルダーの挙動を換えたい、とか

```rhtml
<%= form_for @article do |f| %>
  <%= f.my_field :title %>
  <%= f.submit %>
<% end %>
```

独自のメソッド（この例ではmy_field）を使いたい、とか、そんなときには、 ActionView::Helpers::FormBuilder のサブクラスを作ればよい。

参考
http://guides.rubyonrails.org/form_helpers.html#customizing-form-builders:title=Customizing Form Builders - Ruby on Rails Guides
http://d.hatena.ne.jp/zariganitosh/20080117/1200554948:title=ラベル付きエラー表示付きフォームの雛形が欲しい！ - ザリガニが見ていた...。


##基本

```ruby:app/helpers/application_form_builder.rb
class ApplicationFormBuilder < ActionView::Helpers::FormBuilder
  def my_field(method, options={})
    # 任意の処理
    # ここではあらかじめ作成していた同名のヘルパーを使う例
    @template.my_field(@object_name, method, objectify_options(options))
  end
end
```

:builderオプションで指定

```rhtml
<%= form_for @article, builder: ApplicationFormBuilder do |f| %>
  <%= f.my_field :title %>
  <%= f.submit %>
<% end %>
```


##テスト
よくわかんないけど、僕はこんな感じ。

```ruby:spec/bulders/application_form_builder_spec.rb
require 'spec_helper'

describe ApplicationFormBuilder do
  let(:object){ mock_model(Article) }
  let(:helper){ double(ActionView::Helpers::FormHelper).as_null_object }
  let(:builder){ ApplicationFormBuilder.new(:article, object, helper, {}, nil) }
  describe '#my_field' do
    it 'my_fieldヘルパーを呼び出すこと' do
      helper.should_receive(:my_field).with(:article, :name, object: object)
      helper.my_field :name
    end

    # その他オプションを渡したときの挙動とかイロイロ
  end
end
```


##独自FormBuilderを頻繁に使うとき

###独自のビューヘルパ application_form_for を定義する

:builderオプションを省略してコーディング効率と見通しをよくする

```ruby
def application_form_for(*args, &proc)
  args << {} unless args.last.is_a?(Hash)
  options = args.last
  if args.first.is_a?(Symbol)
    options.merge!(as: args.shift)
  end
  options.merge!({builder: ApplicationFormBuilder})
  form_for(*args, &proc)
end
```

と適当なところで定義しておき

```rhtml
<%= application_form_for @article do |f| %>
  <%= f.my_field :title %>
  <%= f.submit %>
<% end %>
```

###いっそデフォルトにしてしまうとか

form_for で独自FormBuilderを使ってしまえばよくね？

```ruby
config.action_view.default_form_builder = ApplicationFormBuilder 
```

らしいんだけど、initializers内ではうまくいかなかったのでググったらこんなかんじでやってる人がいた。

```ruby:config/initializers/default_form_builder.rb
# http://calvinconaway.com/2011/11/08/how-to-set-a-default-form-builder-in-rails-3-1-while-letting-it-be-autoloaded/
module ActionView
  module Helpers
    module FormHelper
      def form_for_with_application(record, options = {}, &proc)
        options[:builder] ||= ApplicationFormBuilder
        form_for_without_application(record, options, &proc)
      end

      def fields_for_with_application(record_name, record_object = nil, options = {}, &block)
        options[:builder] ||= ApplicationFormBuilder
        fields_for_without_application(record_name, record_object, options, &block)
      end

      alias_method_chain :form_for, :application
      alias_method_chain :fields_for, :application
    end
  end
end
```

でもまぁ、ちょっときもいかなぁ。


##独自FormBuilderで render f したときに _form.html.erb が使われるようにしたい

```rhtml
<%= form_for @article, builder: ApplicationFormBuilder do |f| %>
  <%= render f %>
  <%= f.submit %>
<% end %>
```

としたときには、「_application_form.html.erb」が選択される。

多分、FormBuilder ごとに部分テンプレートを切り替えられるようにするためだと思うんだけど、 ApplicationFormBuilder をデフォルトとして使うようにした場合には、元々のデフォルトと同じ「_form.html.erb」が選択された方が都合が良い。

ソースを読んでみると、._to_partial_path というメソッドが使われているようなので、これをオーバーライドしてやることにした。

```ruby
class ApplicationFormBuilder < ActionView::Helpers::FormBuilder

  def self._to_partial_path
    return @_to_partial_path if defined?(@_to_partial_path)
    @_to_partial_path = self == ApplicationFormBuilder ? 'form' : super
  end

  # 省略
end
```

でもやっぱりきもいなぁ、あんまりこういうのはしない方が良いと思うけど、どうしてもやるなら。