1

我正在尝试在 Rails 中构建一个表单构建器,为它添加一个disabled属性text_fieldselect助手。这是我的代码的简化版本:

class LabelFormBuilder < ActionView::Helpers::FormBuilder  
  %w[text_field select].each do |method_name|
    define_method(method_name) do |name, *args|
      super(name, :disabled => true, *args)
    end  
  end
end

随着text_fields属性被正确添加,但selects事情变得有点棘手,我不断收到undefined method merge for #<Array:0x10b5229a0>错误。

这是我的视图代码(再次简化):

<%= f.label :name %>
<%= f.text_field :name %>      # works!

<%= f.label :person %>
<%= f.select(:person_id, current_user.person_names, :prompt => 'Please select...') %>  # does not work!

我怎样才能让我上面班级的第 4 行也能在select帮手上工作?

谢谢你的帮助!

4

1 回答 1

2

selectfor在此处使用以下方法签名ActionView::Helpers::FormBuilder定义

def select(method, choices, options = {}, html_options = {})

text_fieldfor在此处(动态)ActionView::Helpers::FormBuilder定义,具有以下方法签名

def text_field(method, options = {})

这是一个问题;您的代码{ disabled: true }作为choices参数传递,这不是 Rails 所期望的。

我看到的另一个问题与我对您的意图的混淆有关

super(name, :disabled => true, *args)

因为您options在重载方法中显式地进行{ disabled: true },忽略从您的视图传入的任何选项。

我认为独立重载每个方法是最简单的。

class LabelFormBuilder < ActionView::Helpers::FormBuilder  
  def text_field(method, options={})
    options.reverse_merge! disabled: true
    super(method, options)
  end

  def select(method, choices, options = {}, html_options = {})
    html_options.reverse_merge! disabled: true
    super(method, choices, options = {}, html_options = {})
  end
end

注意使用reverse_merge!. 这是一个 Rails 方法Hash,允许您为散列项提供默认值(例如上面所做的默认选项)。这允许将其他选项传递给您正在重载的方法,同时提供合理的默认值,:disabled但仍允许根据具体情况对其进行覆盖(您将直接传递disabled: falseselectortext_field调用)

这是未经测试的,但应该让你接近你所追求的。

于 2012-11-05T01:40:02.453 回答