Ruby on Rails自定义FormBuilder覆盖text_field

时间:2013-04-22 14:52:51

标签: ruby-on-rails ruby-on-rails-3.2 formbuilder

我的项目中有一个自定义表单构建器,在初始化程序中使用以下代码:

class CustomFormBuilder < ActionView::Helpers::FormBuilder

  def submit(label, *args)
    options = args.extract_options!
    new_class = options[:class] || "btn"
    super(label, *(args << options.merge(:class => new_class)))
  end

  def text_field(label, *args)
    options = args.extract_options!
    new_class = options[:class] || "textbox"
    super(label, *(args << options.merge(:class => new_class)))
  end

end

# Set CustomBuilder as default FormBuilder
ActionView::Base.default_form_builder = CustomFormBuilder

提交定义可以运行并附加类 btn 来提交输入,但是 text_field 定义似乎不适合作为类文本框不会附加到文本输入中。

在查看FormBuilder的documentation后,我注意到 submit 被列为方法,而 text_field 则没有。我需要弄清楚的是如何正确地覆盖使用 form_for 生成表单时使用的 text_field 方法。如果它有助于我使用Ruby 2.0.0和Rails 3.2.13。另外我查看了一个示例here,其中显示了自定义FormBuilder类中的 text_field 方法,因此我想知道在Rails 3中是否已从 FormBuilder 中删除此方法并放入别的地方。任何有关如何实现这一目标的见解将不胜感激。

以下是我的解决方案 (根据PinnyM提供的信息)

class CustomFormBuilder < ActionView::Helpers::FormBuilder

  def submit(label, *args)
    options = args.extract_options!
    options[:class] = "btn" if !options[:class].present?
    super(label, *(args << options))
  end

  def self.create_tagged_field(method_name)
    case method_name
    when 'text_field'
      define_method(method_name) do |name, *args|
        options = args.extract_options!
        options[:class] = "textbox" if !options[:class].present?
        super(name, *(args << options))
      end
    end
  end

  field_helpers.each do |name|
    create_tagged_field(name)
  end

end

1 个答案:

答案 0 :(得分:0)

FormBuilder使用元代码为大多数表单标记生成方法(包括text_field)。它为此目的借用了FormHelper实例方法,排除了需要不同实现的特定标记,并遍历其余标记以自动生成它们的方法。生成代的相关代码如下所示:

(field_helpers - %w(label check_box radio_button fields_for hidden_field file_field)).each do |selector|
  class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
    def #{selector}(method, options = {}) # def text_field(method, options = {})
      @template.send( # @template.send(   
        #{selector.inspect}, # "text_field",
        @object_name, # @object_name,
        method, # method,
        objectify_options(options)) # objectify_options(options))
    end # end
    RUBY_EVAL
end