ruby on rails f.select options with custom attributes

后端 未结 5 1618
一个人的身影
一个人的身影 2020-11-28 01:34

I have a form select statement, like this:

= f.select :country_id, @countries.map{ |c| [c.name, c.id] }

Which results in this code:

5条回答
  •  庸人自扰
    2020-11-28 01:59

    The extra attributes hash is only supported in Rails 3.

    If you're on Rails 2.x, and want to override options_for_select

    I basically just copied the Rails 3 code. You need to override these 3 methods:

    def options_for_select(container, selected = nil)
        return container if String === container
        container = container.to_a if Hash === container
        selected, disabled = extract_selected_and_disabled(selected)
    
        options_for_select = container.inject([]) do |options, element|
          html_attributes = option_html_attributes(element)
          text, value = option_text_and_value(element)
          selected_attribute = ' selected="selected"' if option_value_selected?(value, selected)
          disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled)
          options << %()
        end
    
        options_for_select.join("\n").html_safe
    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
    
    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
    

    Kinda messy but it's an option. I place this code in a helper module called RailsOverrides which I then include in ApplicationHelper. You can also do a plugin/gem if you prefer.

    One gotcha is that to take advantage of these methods you must always invoke options_for_select directly. Shortcuts like

    select("post", "person_id", Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] })
    

    will yield the old results. Instead it should be:

    select("post", "person_id", options_for_select(Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] }))
    

    Again not a great solution, but it might be worth it to get to the ever so useful data-attribute.

提交回复
热议问题