您应该创建一个自定义构建器并使用 :builder 参数将其传递给表单,而不是更改默认构建器。
class HintFormBuilder < ActionView::Helpers::FormBuilder
end
form_for @resource, :builder => HintFormBuilder do |f|
# ...
end
Hint 构建器继承了所有 FormBuilder 功能,包括验证、错误消息等。现在,您应该更改需要更改的内容以自定义行为。
这是一个非常原始的草稿。
class HintFormBuilder < ActionView::Helpers::FormBuilder
(%w(label)).each do |selector|
src = <<-end_src
def #{selector}(method, options = {})
hint = options.delete(:hint)
returning(super) do |element|
# replace here the value of element with hint
# if hint != nil
# remember to use gsub! and not gsub
end
end
end_src
class_eval src, __FILE__, __LINE__
end
end
根据第一条评论编辑:
最好不要破解 Rails 内部结构,因为您现在或将来可能需要使用依赖于原始行为的插件或功能。如果您不想在表单中手动附加构建器,您可以创建一个帮助器。
def search_form_for(record_or_name_or_array, *args, &proc)
options = { :builder => HintFormBuilder }
form_for(record_or_name_or_array,
*(args << options),
&proc)
结束
如果您想重新打开原始类,我建议创建一个新方法。此解决方案也适用于自定义助手,并且您可以自定义它而无需 gsub!响应。是的,gsub!是这样做的常用方法,因为在扩展原始方法时,您只能访问方法/选项和结果,没有值(由 @object 变量注入)。
class ActionView::Helpers::FormBuilder
def label_with_hint(method, text = nil, options = {})
hint = options.delete(:hint)
# do your own customizations...
@template.label(@object_name, method, text, objectify_options(options))
end
end
编辑:我弄错了,您可以将自定义文本作为参数传递,这样您就不需要 gsub!返回的字符串。我对 text_field 标签感到困惑。
此时,您可以使用第一个(使用/不使用自定义方法的子类化)、第二个(hacking internals)或第三个选项(使用 custom method hacking internals)并在将文本值发送到@template.label 之前拦截它。
还要注意 text 可以为 nil。如果为 nil,则从方法中自动生成该值。你应该意识到这一点。