The Rails documentation doesn't seem to mention this, but it's possible to add your own custom HTML attributes to the option tags generated using options_for_select
In our case, we wanted to add custom HTML5 data attributes to our options tags we could use unobtrusive javascript to notice when the the user made a new selection and update another part of the page with the contents of the selected option tag's data attribute
I found someone else actually recommend doing a copy/paste/rewrite of options_for_select
, but if you dig into the Rails code a bit you'll find this is totally unnecessary. This is from form_options_helper.rb
- the two methods that get called on each element of the array you pass to
options_for_select
:
def option_html_attributes(element)
return "" unless Array === element
html_attributes = []
element.select { |e| Hash === e }.reduce({}, :merge).each do |k, v|
html_attributes << " #{k}=\"#{ERB::Util.html_escape(v.to_s)}\""
end
html_attributes.join
end
def option_text_and_value(option)
# Options are [text, value] pairs or strings used for both.
case
when Array === option
option = option.reject { |e| Hash === e }
[option.first, option.last]
when !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last)
[option.first, option.last]
else
[option, option]
end
end
So, this code is frankly a bit ugly, but basically what it does is if you put one or more hashes inside your option array, it merges them together and converts them into HTML attributes (and also prevents them from winding up in your option tag's text/value)
So in our case, our select tag is as simple as this:
select_tag :product_id, options_for_select(products.map{ |p| [p.name, p.id, {'data-sku' => p.sku}] })