Ruby on rails 如何扩展核心Rails FormBuilder字段

Ruby on rails 如何扩展核心Rails FormBuilder字段,ruby-on-rails,ruby,forms,ruby-on-rails-4,twitter-bootstrap-3,Ruby On Rails,Ruby,Forms,Ruby On Rails 4,Twitter Bootstrap 3,我正在使用Bootstrap3和Rails4,我想创建一个自定义FormBuilder来处理Bootstrap的一些独特HTML语法。具体地说,我需要一个自定义帮助程序,它可以在表单字段周围创建表单组div包装器,因为 现在我想利用引导来显示错误消息。这需要我扩展Rails本机帮助程序(例如上面示例中的text\u字段),然后在f.form\u组的块中调用它们 解决方案似乎非常简单:调用父对象,并将我的span块附加到末尾 def text_field(method, options={})

我正在使用Bootstrap3和Rails4,我想创建一个自定义FormBuilder来处理Bootstrap的一些独特HTML语法。具体地说,我需要一个自定义帮助程序,它可以在表单字段周围创建
表单组
div包装器,因为

现在我想利用引导来显示错误消息。这需要我扩展Rails本机帮助程序(例如上面示例中的
text\u字段
),然后在
f.form\u组的块中调用它们

解决方案似乎非常简单:调用父对象,并将我的span块附加到末尾

def text_field(method, options={})
  @template.text_field(method, options)
  if !@object.errors[method].blank?
    @template.content_tag(:span, @object.errors.full_messages_for(method), class: 'help-block')
  end
end
只有它不会输出任何HTML,div才会显示为空。我尝试了一系列不同的语法方法:

  • super
    vs
    text\u-field
    vs
    text\u-field\u-tag
  • concat
    -ing结果--
    @template.concat(@template.content_tag([…])
  • 动态变量,例如
    def text\u字段(方法,*args)
    然后
    options=args.extract\u options!。象征你的钥匙
我只会遇到奇怪的语法错误,或者一个空的
div
。在某些情况下,
input
字段会出现,但帮助文本
span
不会出现,反之亦然


我肯定我把一些简单的东西搞糟了,我就是看不出来。

花了几天时间,但我最终还是找到了正确的语法。希望它能拯救其他人的理智

Ruby的
return
automagic,加上Rails有时复杂的作用域,让我很不舒服。具体地说,
@template.text\u字段
绘制内容,但它必须由helper方法返回才能出现在调用块中。但是,我们必须返回两次调用的结果

def text_field(method, options={})
  field_errors = object.errors[method].join(', ') if !@object.errors[method].blank?
  content = super
  content << (@template.content_tag(:span, @object.errors.full_messages_for(method), class: 'help-block') if field_errors)
  return content
end
注意:表单是使用ActiveModel对象启动的,这就是为什么我们可以访问
@object
。为
实现
form\u而不将其与模型关联需要您扩展
text\u field\u标记

这是我完成的自定义FormBuilder

class BootstrapFormBuilder < ActionView::Helpers::FormBuilder

  def form_group(method, options={})
    class_def = 'form-group'
    class_def << ' has-error' unless @object.errors[method].blank?
    class_def << " #{options[:class]}" if options[:class].present?
    options[:class] = class_def
    @template.content_tag(:div, options) { yield }
  end

  def text_field(method, options={})
    field_errors = object.errors[method].join(', ') if !@object.errors[method].blank?
    super + (@template.content_tag(:span, @object.errors.full_messages_for(method), class: 'help-block') if field_errors)
  end

end
编辑:这里有一些有用的链接,帮助我走上启蒙之路。链接果汁荣誉的作者

def text_field(method, options={})
  field_errors = object.errors[method].join(', ') if !@object.errors[method].blank?
  content = super
  content << (@template.content_tag(:span, @object.errors.full_messages_for(method), class: 'help-block') if field_errors)
  return content
end
def text_field(method, options={})
  field_errors = object.errors[method].join(', ') if !@object.errors[method].blank?
  super + (@template.content_tag(:span, @object.errors.full_messages_for(method), class: 'help-block') if field_errors)
end
class BootstrapFormBuilder < ActionView::Helpers::FormBuilder

  def form_group(method, options={})
    class_def = 'form-group'
    class_def << ' has-error' unless @object.errors[method].blank?
    class_def << " #{options[:class]}" if options[:class].present?
    options[:class] = class_def
    @template.content_tag(:div, options) { yield }
  end

  def text_field(method, options={})
    field_errors = object.errors[method].join(', ') if !@object.errors[method].blank?
    super + (@template.content_tag(:span, @object.errors.full_messages_for(method), class: 'help-block') if field_errors)
  end

end
form_for(:user, :builder => BootstrapFormBuilder [, ...])