これに対するややエレガントな解決策を見つけたと思います。次のモジュールを作成し、デコレーターに混ぜました。
module FormDecoration
def form options={}, &blk
h.simple_form_for model, options do |builder|
@form_builder = builder
blk[builder]
end
ensure
@form_builder = nil
end
def method_missing meth, *args, &blk
if @form_builder && @form_builder.respond_to?(meth)
@form_builder.public_send meth, *args, &blk
else
super
end
end
def respond_to? meth
(@form_builder && @form_builder.respond_to?(meth)) || super
end
end
今、私の見解は次のようになります。
= user.form do
= user.input :name
= user.input :email
= user.role_or_select
input
メソッドはフォーム ビルダーにプロキシされます。role_or_select はヘルパーで次のように定義されています。
def role_or_select
available_roles = h.policy_scope User::ROLES
if available_roles.include? object.role
input :role, collection: available_roles, include_blank: false
else
object.role
end
end
これにより、デコレータにフォーム オプションを追加することもできます。たとえば、次を UserDecorator に追加すると、オートコンプリートがオフになります。
def form options={}
options[:html] ||= {}
options[:html][:autocomplete] = 'off'
super options
end