Skip to content

Instantly share code, notes, and snippets.

@zoras
Created September 28, 2023 05:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zoras/1eabfb092c54bf1a30ad4c587d5a29b6 to your computer and use it in GitHub Desktop.
Save zoras/1eabfb092c54bf1a30ad4c587d5a29b6 to your computer and use it in GitHub Desktop.
Custom HTML attributes in options_for_select

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}] })

Source: https://web.archive.org/web/20130128223827/http://www.pogodan.com/blog/2011/02/24/custom-html-attributes-in-options-for-select

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment