25

有没有一种方法可以创建自定义表单助手,而不是:

special_field_tag :object, :method

我可以实现以下目标:

form.special_field :method
4

3 回答 3

48

是的,您可以添加到 FormBuilder 类并访问传递给 form_for 的对象。我做了很多事情:日期、时间、测量等。下面是一个例子:

class ActionView::Helpers::FormBuilder
  include ActionView::Helpers::TagHelper
  include ActionView::Helpers::FormTagHelper
  include ActionView::Helpers::FormOptionsHelper
  include ActionView::Helpers::CaptureHelper
  include ActionView::Helpers::AssetTagHelper

  # Accepts an int and displays a smiley based on >, <, or = 0
  def smile_tag(method, options = {})
    value = @object.nil? ? 0 : @object.send(method).to_i
    options[:id] = field_id(method,options[:index])
    smiley = ":-|"
    if value > 0
      smiley = ":-)"
    elsif smiley < 0
       smiley = ":-("
    end
    return text_field_tag(field_name(method,options[:index]),options) + smiley
  end

  def field_name(label,index=nil)
    output = index ? "[#{index}]" : ''
    return @object_name + output + "[#{label}]"
  end

  def field_id(label,index=nil)
    output = index ? "_#{index}" : ''
    return @object_name + output + "_#{label}"
  end

end

您可以像这样使用它:

<% form_for @quiz do |f| %>
  <%= f.smile_tag(:score) %>
<% end %>

Rails 创建了一些实例变量,您可以在这些辅助方法中访问它们:

  • @object - 表单指定的模型对象
  • @object_name - 对象的类名
  • @template - 我认为它是 ActionView 的一个实例,您可以通过调用模板上的方法绕过我添加的所有包含。还没试过。
  • @options - 由 form_for 调用创建时传递给 FormBuilder 的选项

我编写了 field_id 和 field_name 方法来在 HTML 输入元素上创建这些属性,就像常规助手一样,我确信有一种方法可以绑定到 Rails 使用的相同方法,但我还没有找到它.

使用这些辅助方法可以做的事情没有限制,它们只是返回字符串。您可以在一个页面中创建整个 HTML 表格或页面,但您最好有充分的理由这样做。

此文件应添加到 app/helpers 文件夹中

于 2010-04-12T21:54:35.447 回答
7

@Tilendor,非常感谢您的指点。下面是一个enum_select表单标签助手的例子,它使用 Rails 4.1 枚举自动填充选择标签的选项:

# helpers/application_helper.rb
module ApplicationHelper
  class ActionView::Helpers::FormBuilder
    # http://stackoverflow.com/a/2625727/1935918
    include ActionView::Helpers::FormTagHelper
    include ActionView::Helpers::FormOptionsHelper
    def enum_select(name, options = {})
      # select_tag "company[time_zone]", options_for_select(Company.time_zones
      #   .map { |value| [value[0].titleize, value[0]] }, selected: company.time_zone)
      select_tag @object_name + "[#{name}]", options_for_select(@object.class.send(name.to_s.pluralize)
        .map { |value| [value[0].titleize, value[0]] }, selected: @object.send(name))
    end
  end
end

最棘手的构造是@object.class.send(name.to_s.pluralize)产生可用值的散列(例如,Company.time_zones)。将其放入helpers/application_helper.rb会使其自动可用。它的用法如下:

<%= f.label :billing_status %>:
<%= f.enum_select :billing_status %><br />
于 2014-07-25T04:25:30.997 回答
3

我们的应用在文本字段中显示电话号码,我们想省略国内号码的国家代码。我正在使用表单助手。在阅读了this和rails source之后,我来到了这个解决方案:

class ActionView::Helpers::FormBuilder
  def phone_text_field name, options = {}
    value = object.public_send(name).to_s
    if value.start_with? "9" # national number
      value = value[1..-1]
      options["value"] = value
    end
    text_field name, options
  end
end

我把它放在 app/helpers/application_helper.rb 上并像使用text_field()helper 一样使用它。希望这可以帮助某人。

于 2015-08-21T07:34:12.673 回答