【问题标题】:Rails, collection_select and ProcRails、collection_select 和 Proc
【发布时间】:2013-01-06 04:49:40
【问题描述】:

我有一个国家/地区的州列表,我想在<select> 上显示它们。由于我试图显示一个代表每个州标志的图标,因此我使用了this JQuery 插件。无论如何,目前这是一个纯粹的 Rails 问题。

要使用该插件,我需要在此select 中包含的每个option 标记上设置一个“数据图像”属性。

到目前为止我所拥有的是:

<%= collection_select(:state, :code, @states, :code, 
:name, {"data-image" => lambda {|state| image_path("/flags/#{state.code}.png") }}) %>

我尝试了很多方法来为每个option 设置“data-image”属性,但目前的结果是:

<select id="state_code" name="state[code]">
  <option value="foo">State Foo</option>
  <option value="bar" selected="selected">State Bar</option>
</select>

因此,我没有成功注入我的“数据图像”属性。我一直在寻找一些光,我看到了this [api.rubyonrails] 和下面的例子,

collection_select(:post, :category_id, Category.all, :id, :name, {:disabled => lambda{|category| category.archived? }})

这基本上就是我要找的东西,我的东西几乎是一样的,但它不起作用。我正在使用 Rails 2.3.11。如有建议,我将不胜感激。

【问题讨论】:

    标签: jquery ruby-on-rails collections ruby-on-rails-2 view-helpers


    【解决方案1】:

    查看this Stackoverflow question 的第二个答案。

    基本上,它涉及使用options_for_select 帮助程序来创建自定义data 前缀属性。

    【讨论】:

    • 谢谢,我赞成您的回答并发布了完整的答案。在我看到你的回答时,我已经理解了 Rails 2 上的 options_for_select 和数据属性问题。
    • 我完全错过了您使用 Rails 2 的事实,我的错!我得开始更仔细地阅读。很高兴你把事情弄清楚了!
    • 没问题,如果我以前没有看到这个问题,你的链接将是解决方案的北方。万分感谢!干杯!
    【解决方案2】:

    所以,我最终解决了这个问题,以下是完整的解决方案。据我了解,由于我使用的是 Rails 2.3,因此没有帮助程序支持 data 前缀属性。事实证明,正如this 回答所指出的那样,我需要使用 Rails 3 options_for_select 助手。作为旁注,我没有使用 msDropDown 插件,而是使用了ddSlick。另外,我没有使用collection_select,而是使用了select_tag。那么基本上你必须拥有的是:

    rails_overrides.rb

    # https://stackoverflow.com/a/13962481/914874
    module RailsOverrides
      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 << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{html_escape(text.to_s)}</option>)
          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
    end
    

    application_helper.rb

    module ApplicationHelper
      include RailsOverrides
    end
    

    index.html.erb

    <%= select_tag(:state, options_for_select (states.map { |state| [state.name, state.code, {"data-imagesrc" => image_path("flags/#{state.code}.png"), "data-description" => "Data from #{state.name}"}]}, current_state.code)) %>
    

    这里,current_state 是要选择为默认选项的状态。例如,我将它存储在 session 变量中,但为了简单起见,它可能是 @current_state。

    解决此问题的另一种方法是使用 options_from_collection_for_select_with_data 的修改版本,因此无需公开 map。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 2014-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-01
      • 1970-01-01
      相关资源
      最近更新 更多