メソッドを使用する (小さな) 欠点は、単にブロックをtldr: に渡すだけf.input do end
で、デフォルトの入力 html オプション (単純なフォームrequired
やoptional
クラス、required
属性など) とデフォルト オプション ( などb.use :input, class: 'input-element'
) が欠落していることです: 入力は装飾されません。f.input
これらの追加のクラスと属性に依存する場合は、それらを手動で渡す必要があります (ドライではありません)。
これを克服するために、特別な選択用のカスタム入力を作成したので、必要に応じて選択の本体 (<option>
タグ) を定義できますが、選択は通常どおり装飾されます。
# app/inputs/select_container_input.rb
class SelectContainerInput < SimpleForm::Inputs::Base
def input(wrapper_options)
options_html = input_options.delete(:options_html)
# since we pass our options by our self (and have to select the correct
# option), set `selected` to `''` to prevent rails calling
# `object.send(attribute_name)` only to set `selected` which is not used.
input_options[:selected] = ''
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.select attribute_name, nil, input_options, merged_input_options do
options_html
end
end
end
次のように呼び出すだけです。
<% options_html = capture do %>
<option>bla</option>
<% end %>
<%= f.input :attribute, as: :select_container, options_html: options_html %>
これoptions_html
は回避策です。実際には、ブロックをカスタム入力に渡す方が簡単だからです。
<%= f.input :attribute, as: :select_container do %>
<option>bla</option>
<% end %>
しかし、SimpleForm::FormBuilder#def_inputの動作方法により、コードが入力に触れる前にブロックが取り除かれます。そのため、simple_form をリファクタリングせずにはいられません。
全体として、これにより、特別な選択のためにビューに少し余分なノイズの多いコードが含まれる問題が解決されます。