跳到内容 跳到搜索

Action View 表单构建器

一个 FormBuilder 对象与特定的模型对象相关联,允许你生成与模型对象关联的字段。FormBuilder 对象在使用 form_withfields_for 时被 yield。例如

<%= form_with model: @person do |person_form| %>
  Name: <%= person_form.text_field :name %>
  Admin: <%= person_form.checkbox :admin %>
<% end %>

在上面的代码块中,一个 FormBuilder 对象作为 person_form 变量被 yield。这允许你通过指定它们的同名方法来生成 text_fieldcheckbox 字段,这些方法修改底层模板并将 @person 模型对象与表单相关联。

FormBuilder 对象可以被认为是 FormHelper 模块中方法的代理。但是,此类允许你使用正在构建表单的模型对象调用方法。

你可以通过子类化此类来创建自己的自定义 FormBuilder 模板。例如

class MyFormBuilder < ActionView::Helpers::FormBuilder
  def div_radio_button(method, tag_value, options = {})
    @template.content_tag(:div,
      @template.radio_button(
        @object_name, method, tag_value, objectify_options(options)
      )
    )
  end
end

上面的代码创建了一个新的方法 div_radio_button,它将一个 div 围绕新的单选按钮。注意,当传递选项时,你必须调用 objectify_options 以便模型对象被正确传递给方法。如果没有调用 objectify_options,那么新创建的助手将不会链接回模型。

上面的 div_radio_button 代码现在可以按如下方式使用

<%= form_with model: @person, :builder => MyFormBuilder do |f| %>
  I am a child: <%= f.div_radio_button(:admin, "child") %>
  I am an adult: <%= f.div_radio_button(:admin, "adult") %>
<% end -%>

用于表单构建的标准助手方法集位于 field_helpers 类属性中。

方法
#
B
C
D
E
F
G
H
I
L
M
N
P
R
S
T
U
W

属性

[R] 索引
[R] multipart
[R] multipart?
[RW] object
[RW] object_name
[RW] options

类公共方法

_to_partial_path()

# File actionview/lib/action_view/helpers/form_helper.rb, line 1708
def self._to_partial_path
  @_to_partial_path ||= name.demodulize.underscore.sub!(/_builder$/, "")
end

new(object_name, object, template, options)

# File actionview/lib/action_view/helpers/form_helper.rb, line 1720
def initialize(object_name, object, template, options)
  @nested_child_index = {}
  @object_name, @object, @template, @options = object_name, object, template, options
  @default_options = @options ? @options.slice(:index, :namespace, :skip_default_ids, :allow_method_names_outside_object) : {}
  @default_html_options = @default_options.except(:skip_default_ids, :allow_method_names_outside_object)

  convert_to_legacy_options(@options)

  if @object_name&.end_with?("[]")
    if (object ||= @template.instance_variable_get("@#{@object_name[0..-3]}")) && object.respond_to?(:to_param)
      @auto_index = object.to_param
    else
      raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
    end
  end

  @multipart = nil
  @index = options[:index] || options[:child_index]
end

实例公共方法

button(value = nil, options = {}, &block)

为给定的表单添加提交按钮。当没有给出值时,它会检查对象是新的资源还是旧的,以创建正确的标签

<%= form_with model: @article do |f| %>
  <%= f.button %>
<% end %>

在上面的示例中,如果 @article 是一个新记录,它将使用“创建文章”作为按钮标签;否则,它使用“更新文章”。

这些标签可以使用 I18n 在 helpers.submit 键下进行自定义(与 submit 助手相同),并使用 %{model} 进行翻译插值

en:
  helpers:
    submit:
      create: "Create a %{model}"
      update: "Confirm changes to %{model}"

它还会搜索特定于给定对象的键

en:
  helpers:
    submit:
      article:
        create: "Add %{model}"

示例

button("Create article")
# => <button name='button' type='submit'>Create article</button>

button(:draft, value: true)
# => <button id="article_draft" name="article[draft]" value="true" type="submit">Create article</button>

button do
  content_tag(:strong, 'Ask me!')
end
# => <button name='button' type='submit'>
#      <strong>Ask me!</strong>
#    </button>

button do |text|
  content_tag(:strong, text)
end
# => <button name='button' type='submit'>
#      <strong>Create article</strong>
#    </button>

button(:draft, value: true) do
  content_tag(:strong, "Save as draft")
end
# =>  <button id="article_draft" name="article[draft]" value="true" type="submit">
#       <strong>Save as draft</strong>
#     </button>
# File actionview/lib/action_view/helpers/form_helper.rb, line 2649
def button(value = nil, options = {}, &block)
  case value
  when Hash
    value, options = nil, value
  when Symbol
    value, options = nil, { name: field_name(value), id: field_id(value) }.merge!(options.to_h)
  end
  value ||= submit_default_value

  if block_given?
    value = @template.capture { yield(value) }
  end

  formmethod = options[:formmethod]
  if formmethod.present? && !/post|get/i.match?(formmethod) && !options.key?(:name) && !options.key?(:value)
    options.merge! formmethod: :post, name: "_method", value: formmethod
  end

  @template.button_tag(value, options)
end

check_box(method, options = {}, checked_value = "1", unchecked_value = "0")

别名: checkbox

checkbox(method, options = {}, checked_value = "1", unchecked_value = "0")

返回一个复选框标签,专门用于访问分配给模板的对象(由 object 标识)上的特定属性(由 method 标识)。此对象必须是实例对象(@object),而不是局部对象。目的是 method 返回一个整数,如果该整数大于零,则复选框被选中。可以作为哈希使用 options 传递输入标签上的其他选项。checked_value 默认值为 1,而默认 unchecked_value 设置为 0,这对于布尔值来说很方便。

选项

  • 可以传入标签的任何标准 HTML 属性,例如 :class

  • :checked - truefalse 强制复选框的状态为选中或不选中。

  • :include_hidden - 如果设置为 false,则不会生成下面描述的辅助隐藏字段。

注意点

HTML 规范规定未选中的复选框不成功,因此 Web 浏览器不会发送它们。不幸的是,这会带来一个注意点:如果一个 Invoice 模型有一个 paid 标志,并且在编辑已支付发票的表单中,用户取消选中其复选框,则不会发送 paid 参数。因此,任何类似于批量赋值的习惯用法,例如

@invoice.update(params[:invoice])

不会更新标志。

为了防止这种情况,助手在每个复选框之前生成一个辅助隐藏字段。隐藏字段具有相同的名称,其属性模拟未选中的复选框。

这样,客户端要么只发送隐藏字段(表示复选框未选中),要么发送两个字段。由于 HTML 规范规定键值对必须按表单中出现的顺序发送,并且参数提取获取查询字符串中任何重复键的最后出现,因此这对于普通表单有效。

不幸的是,当复选框位于类似数组的参数中时,这种解决方法不起作用,例如

<%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
  <%= form.checkbox :paid %>
  ...
<% end %>

因为参数名称重复正是 Rails 用于区分数组元素的东西。对于每个具有选中复选框的项目,你将获得一个额外的“幽灵”项目,只有该属性,被分配给“0”。

在这种情况下,最好使用 checkbox_tag 或使用哈希而不是数组。

示例

# Let's say that @article.validated? is 1:
checkbox("validated")
# => <input name="article[validated]" type="hidden" value="0" />
#    <input checked="checked" type="checkbox" id="article_validated" name="article[validated]" value="1" />

# Let's say that @puppy.gooddog is "no":
checkbox("gooddog", {}, "yes", "no")
# => <input name="puppy[gooddog]" type="hidden" value="no" />
#    <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />

# Let's say that @eula.accepted is "no":
checkbox("accepted", { class: 'eula_check' }, "yes", "no")
# => <input name="eula[accepted]" type="hidden" value="no" />
#    <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
也称为: check_box
# File actionview/lib/action_view/helpers/form_helper.rb, line 2473
def checkbox(method, options = {}, checked_value = "1", unchecked_value = "0")
  @template.checkbox(@object_name, method, objectify_options(options), checked_value, unchecked_value)
end

collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)

collection_checkboxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)

包装 ActionView::Helpers::FormOptionsHelper#collection_checkboxes 适用于表单构建器

<%= form_with model: @post do |f| %>
  <%= f.collection_checkboxes :author_ids, Author.all, :id, :name_with_initial %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 909
def collection_checkboxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
  @template.collection_checkboxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
end

collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)

包装 ActionView::Helpers::FormOptionsHelper#collection_radio_buttons 适用于表单构建器

<%= form_with model: @post do |f| %>
  <%= f.collection_radio_buttons :author_id, Author.all, :id, :name_with_initial %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 922
def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
  @template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
end

collection_select(method, collection, value_method, text_method, options = {}, html_options = {})

包装 ActionView::Helpers::FormOptionsHelper#collection_select 适用于表单构建器

<%= form_with model: @post do |f| %>
  <%= f.collection_select :person_id, Author.all, :id, :name_with_initial, prompt: true %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 861
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
  @template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options))
end

color_field(method, options = {})

包装 ActionView::Helpers::FormHelper#color_field 适用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.color_field :favorite_color %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1843
      

date_field(method, options = {})

包装 ActionView::Helpers::FormHelper#date_field 适用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.date_field :born_on %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1895
      

date_select(method, options = {}, html_options = {})

包装 ActionView::Helpers::DateHelper#date_select 适用于表单构建器

<%= form_with model: @person do |f| %>
  <%= f.date_select :birth_date %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/date_helper.rb, line 1237
def date_select(method, options = {}, html_options = {})
  @template.date_select(@object_name, method, objectify_options(options), html_options)
end

datetime_field(method, options = {})

包装 ActionView::Helpers::FormHelper#datetime_field 适用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.datetime_field :graduation_day %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1921
      

datetime_local_field(method, options = {})

包装 ActionView::Helpers::FormHelper#datetime_local_field 适用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.datetime_local_field :graduation_day %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1934
      

datetime_select(method, options = {}, html_options = {})

包装 ActionView::Helpers::DateHelper#datetime_select 用于表单构建器

<%= form_with model: @person do |f| %>
  <%= f.datetime_select :last_request_at %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/date_helper.rb, line 1261
def datetime_select(method, options = {}, html_options = {})
  @template.datetime_select(@object_name, method, objectify_options(options), html_options)
end

email_field(method, options = {})

包装 ActionView::Helpers::FormHelper#email_field 用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.email_field :address %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1986
      

field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])

为给定字段生成 HTML id 属性值

返回 FormBuilder 为给定属性名称生成的 value。

<%= form_with model: @article do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title, aria: { describedby: f.field_id(:title, :error) } %>
  <%= tag.span("is blank", id: f.field_id(:title, :error) %>
<% end %>

在上面的示例中,FormBuilder#text_field 调用构建的 <input type="text"> 元素声明了 aria-describedby 属性,引用了 <span> 元素,共享一个共同的 id 根(在本例中为 article_title)。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1777
def field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])
  @template.field_id(@object_name, method, *suffixes, namespace: namespace, index: index)
end

field_name(method, *methods, multiple: false, index: @options[:index])

为给定名称和字段组合生成 HTML name 属性值

返回 FormBuilder 为给定属性名称生成的 value。

<%= form_with model: @article do |f| %>
  <%= f.text_field :title, name: f.field_name(:title, :subtitle) %>
  <%# => <input type="text" name="article[title][subtitle]"> %>
<% end %>

<%= form_with model: @article do |f| %>
  <%= f.text_field :tag, name: f.field_name(:tag, multiple: true) %>
  <%# => <input type="text" name="article[tag][]"> %>
<% end %>
# File actionview/lib/action_view/helpers/form_helper.rb, line 1797
def field_name(method, *methods, multiple: false, index: @options[:index])
  object_name = @options.fetch(:as) { @object_name }

  @template.field_name(object_name, method, *methods, index: index, multiple: multiple)
end

fields(scope = nil, model: nil, **options, &block)

参见 ActionView::Helpers::FormHelper#fields 辅助方法的文档。

# File actionview/lib/action_view/helpers/form_helper.rb, line 2327
def fields(scope = nil, model: nil, **options, &block)
  options[:allow_method_names_outside_object] = true
  options[:skip_default_ids] = !FormHelper.form_with_generates_ids

  convert_to_legacy_options(options)

  fields_for(scope || model, model, options, &block)
end

fields_for(record_name, record_object = nil, fields_options = nil, &block)

创建特定模型对象的范围,类似于 form_with,但不创建表单标签本身。这使得 fields_for 适用于在同一个表单中指定其他模型对象。

虽然 fields_for 的用法和目的与 form_with 类似,但其方法签名略有不同。与 form_with 一样,它会将一个与特定模型对象关联的 FormBuilder 对象传递给代码块,并在代码块内允许对构建器调用方法以生成与模型对象关联的字段。字段可以以两种方式反映模型对象 - 它们的命名方式(因此提交的值如何在控制器中的 params 哈希中显示)以及首次显示表单字段时显示的默认值。为了独立地指定这两个特征,可以在方法中分别传递对象名称(用符号或字符串表示)和对象本身 -

<%= form_with model: @person do |person_form| %>
  First name: <%= person_form.text_field :first_name %>
  Last name : <%= person_form.text_field :last_name %>

  <%= fields_for :permission, @person.permission do |permission_fields| %>
    Admin?  : <%= permission_fields.checkbox :admin %>
  <% end %>

  <%= person_form.submit %>
<% end %>

在这种情况下,复选框字段将用 HTML input 标签表示,其 name 属性为 permission[admin],提交的值将在控制器中显示为 params[:permission][:admin]。如果 @person.permission 是一个现有记录,具有一个 admin 属性,则复选框在首次显示时的初始状态将反映 @person.permission.admin 的值。

通常可以通过只将模型对象的名称传递给 fields_for 来简化此操作 -

<%= fields_for :permission do |permission_fields| %>
  Admin?: <%= permission_fields.checkbox :admin %>
<% end %>

…在这种情况下,如果 :permission 恰好也是实例变量 @permission 的名称,则输入字段的初始状态将反映该变量的 @permission.admin 属性的值。

或者,您也可以只传递模型对象本身(如果第一个参数不是字符串或符号,fields_for 会意识到名称被省略了) -

<%= fields_for @person.permission do |permission_fields| %>
  Admin?: <%= permission_fields.checkbox :admin %>
<% end %>

并且 fields_for 将从模型对象的 派生出所需的字段名称,例如,如果 @person.permissionPermission 类,则字段的名称仍然是 permission[admin]

注意:这也适用于 FormOptionsHelperDateHelper 中设计为使用对象作为基础的方法,例如 FormOptionsHelper#collection_selectDateHelper#datetime_select.

fields_for 试图对参数进行智能处理,但如果提供了名称和值参数,并且提供的值具有选项 Hash 的形状,它可能会感到困惑。为了消除歧义,显式地传递一个选项 Hash,即使它是空的。

<%= form_with model: @person do |person_form| %>
  ...
  <%= fields_for :permission, @person.permission, {} do |permission_fields| %>
    Admin?: <%= checkbox_tag permission_fields.field_name(:admin), @person.permission[:admin] %>
  <% end %>
  ...
<% end %>

嵌套属性示例

当属于当前范围的对象对某个属性具有嵌套属性写入器时,fields_for 将为该属性生成一个新的范围。这允许您创建表单,这些表单可以一次性设置或更改父对象及其关联的属性。

嵌套属性写入器是根据关联命名的普通 setter 方法。定义这些写入器最常见的方式是使用模型定义中的 accepts_nested_attributes_for 或通过定义具有正确名称的方法。例如::address 关联的属性写入器称为 address_attributes=

将生成一对一或一对多样式的表单构建器取决于普通的 reader 方法是返回一个单个对象还是数组对象。

一对一

考虑一个 Person 类,它从 address reader 方法返回一个单个 Address,并响应 address_attributes= 写入器方法

class Person
  def address
    @address
  end

  def address_attributes=(attributes)
    # Process the attributes hash
  end
end

现在可以使用嵌套的 fields_for 使用此模型,如下所示

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :address do |address_fields| %>
    Street  : <%= address_fields.text_field :street %>
    Zip code: <%= address_fields.text_field :zip_code %>
  <% end %>
  ...
<% end %>

当 address 已经是 Person 上的一个关联时,您可以使用 accepts_nested_attributes_for 来为您定义写入器方法

class Person < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address
end

如果您想通过表单销毁关联的模型,您必须首先使用 accepts_nested_attributes_for:allow_destroy 选项启用它

class Person < ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address, allow_destroy: true
end

现在,当您使用 _destroy 参数的表单元素时,其值为 true,您将销毁关联的模型(例如 1、'1'、true 或 'true')

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :address do |address_fields| %>
    ...
    Delete: <%= address_fields.checkbox :_destroy %>
  <% end %>
  ...
<% end %>

一对多

考虑一个 Person 类,它从 projects reader 方法返回一个 数组 Project 实例,并响应 projects_attributes= 写入器方法

class Person
  def projects
    [@project1, @project2]
  end

  def projects_attributes=(attributes)
    # Process the attributes hash
  end
end

请注意,projects_attributes= 写入器方法实际上是 fields_for 正确识别 :projects 作为集合所必需的,并且在表单标记中设置正确的索引。

当 projects 已经是 Person 上的一个关联时,您可以使用 accepts_nested_attributes_for 来为您定义写入器方法

class Person < ActiveRecord::Base
  has_many :projects
  accepts_nested_attributes_for :projects
end

现在可以使用嵌套的 fields_for 使用此模型。传递给嵌套的 fields_for 调用的代码块将对集合中的每个实例重复执行

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    <% if project_fields.object.active? %>
      Name: <%= project_fields.text_field :name %>
    <% end %>
  <% end %>
  ...
<% end %>

也可以指定要使用的实例

<%= form_with model: @person do |person_form| %>
  ...
  <% @person.projects.each do |project| %>
    <% if project.active? %>
      <%= person_form.fields_for :projects, project do |project_fields| %>
        Name: <%= project_fields.text_field :name %>
      <% end %>
    <% end %>
  <% end %>
  ...
<% end %>

或者指定要使用的集合

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
    Name: <%= project_fields.text_field :name %>
  <% end %>
  ...
<% end %>

如果您想通过表单销毁任何关联的模型,您必须首先使用 accepts_nested_attributes_for:allow_destroy 选项启用它

class Person < ActiveRecord::Base
  has_many :projects
  accepts_nested_attributes_for :projects, allow_destroy: true
end

这将允许您通过为 _destroy 参数添加一个表单元素来指定要销毁的模型,该元素的值为 true(例如 1、'1'、true 或 'true')

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    Delete: <%= project_fields.checkbox :_destroy %>
  <% end %>
  ...
<% end %>

当使用集合时,您可能希望知道数组中每个对象的索引。为此,index 方法在 FormBuilder 对象中可用。

<%= form_with model: @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    Project #<%= project_fields.index %>
    ...
  <% end %>
  ...
<% end %>

请注意,fields_for 将自动生成一个隐藏字段来存储记录的 ID。在某些情况下,不需要此隐藏字段,您可以传递 include_id: false 以阻止 fields_for 自动渲染它。

# File actionview/lib/action_view/helpers/form_helper.rb, line 2289
def fields_for(record_name, record_object = nil, fields_options = nil, &block)
  fields_options, record_object = record_object, nil if fields_options.nil? && record_object.is_a?(Hash) && record_object.extractable_options?
  fields_options ||= {}
  fields_options[:builder] ||= options[:builder]
  fields_options[:namespace] = options[:namespace]
  fields_options[:parent_builder] = self

  case record_name
  when String, Symbol
    if nested_attributes_association?(record_name)
      return fields_for_with_nested_attributes(record_name, record_object, fields_options, block)
    end
  else
    record_object = @template._object_for_form_builder(record_name)
    record_name   = model_name_from_record_or_class(record_object).param_key
  end

  object_name = @object_name
  index = if options.has_key?(:index)
    options[:index]
  elsif defined?(@auto_index)
    object_name = object_name.to_s.delete_suffix("[]")
    @auto_index
  end

  record_name = if index
    "#{object_name}[#{index}][#{record_name}]"
  elsif record_name.end_with?("[]")
    "#{object_name}[#{record_name[0..-3]}][#{record_object.id}]"
  else
    "#{object_name}[#{record_name}]"
  end
  fields_options[:child_index] = index

  @template.fields_for(record_name, record_object, fields_options, &block)
end

file_field(method, options = {})

返回一个文件上传输入标签,专门用于访问分配给模板(由 object 标识)的对象上的指定属性(由 method 标识)。可以使用 options 中的哈希传递输入标签上的其他选项。这些选项将作为 HTML 元素属性标记到 HTML 中,如示例所示。

form_with 代码块中使用此方法将把封闭表单的编码设置为 multipart/form-data

选项

  • 为标签创建标准的 HTML 属性。

  • :disabled - 如果设置为 true,用户将无法使用此输入。

  • :multiple - 如果设置为 true,*在大多数更新的浏览器中*,用户将被允许选择多个文件。

  • :include_hidden - 当 multiple: true 并且 include_hidden: true 时,该字段将以一个 <input type="hidden"> 字段为前缀,该字段的值为空,以支持提交空的文件集合。由于 include_hidden 将默认设置为 config.active_storage.multiple_file_field_include_hidden(如果您没有指定 include_hidden),因此您需要传递 include_hidden: false 以防止在传递 multiple: true 时提交空的文件集合。

  • :accept - 如果设置为一个或多个 mime 类型,则在用户选择文件时会建议他们使用过滤器。您仍然需要设置模型验证。

示例

# Let's say that @user has avatar:
file_field(:avatar)
# => <input type="file" id="user_avatar" name="user[avatar]" />

# Let's say that @article has image:
file_field(:image, :multiple => true)
# => <input type="file" id="article_image" name="article[image][]" multiple="multiple" />

# Let's say that @article has attached:
file_field(:attached, accept: 'text/html')
# => <input accept="text/html" type="file" id="article_attached" name="article[attached]" />

# Let's say that @article has image:
file_field(:image, accept: 'image/png,image/gif,image/jpeg')
# => <input type="file" id="article_image" name="article[image]" accept="image/png,image/gif,image/jpeg" />

# Let's say that @attachment has file:
file_field(:file, class: 'file_input')
# => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 2557
def file_field(method, options = {})
  self.multipart = true
  @template.file_field(@object_name, method, objectify_options(options))
end

grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})

包装 ActionView::Helpers::FormOptionsHelper#grouped_collection_select 用于表单构建器

<%= form_with model: @city do |f| %>
  <%= f.grouped_collection_select :country_id, @continents, :countries, :name, :id, :name %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 873
def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
  @template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @default_html_options.merge(html_options))
end

hidden_field(method, options = {})

返回一个隐藏的输入标签,专门用于访问分配给模板(由 object 标识)的对象上的指定属性(由 method 标识)。可以使用 options 中的哈希传递输入标签上的其他选项。这些选项将作为 HTML 元素属性标记到 HTML 中,如示例所示。

示例

# Let's say that @signup.pass_confirm returns true:
hidden_field(:pass_confirm)
# => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="true" />

# Let's say that @article.tag_list returns "blog, ruby":
hidden_field(:tag_list)
# => <input type="hidden" id="article_tag_list" name="article[tag_list]" value="blog, ruby" />

# Let's say that @user.token returns "abcde":
hidden_field(:token)
# => <input type="hidden" id="user_token" name="user[token]" value="abcde" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 2518
def hidden_field(method, options = {})
  @emitted_hidden_id = true if method == :id
  @template.hidden_field(@object_name, method, objectify_options(options))
end

id()

生成 HTML id 属性值。

返回 <form> 元素的 id 属性。

<%= form_with model: @article do |f| %>
  <%# ... %>

  <% content_for :sticky_footer do %>
    <%= form.button(form: f.id) %>
  <% end %>
<% end %>

在上面的示例中,:sticky_footer 内容区域将存在于 <form> 元素之外。通过声明 form HTML 属性,我们向浏览器暗示生成的 <button> 元素应被视为 <form> 元素的提交按钮,无论它在 DOM 中的位置如何。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1757
def id
  options.dig(:html, :id) || options[:id]
end

label(method, text = nil, options = {}, &block)

返回一个为特定属性(由method标识)的输入字段创建标签的标签,该属性位于模板中分配的对象(由object标识)。标签文本将默认使用属性名称,除非在当前 I18n 本地化设置中找到翻译(通过helpers.label.<modelname>.<attribute>),或者您显式指定它。标签标签上的其他选项可以通过哈希options传递。这些选项将作为 HTML 元素属性添加到 HTML 中,如示例所示,但:value选项除外,该选项旨在针对radio_button标签(其中值用于输入标签的 ID)。

示例

label(:title)
# => <label for="article_title">Title</label>

您可以根据模型和属性名称对标签进行本地化。例如,您可以在您的本地化文件(例如 en.yml)中定义以下内容:

helpers:
  label:
    article:
      body: "Write your entire text here"

然后将导致

label(:body)
# => <label for="article_body">Write your entire text here</label>

本地化也可以仅基于属性名称的翻译(如果您使用的是ActiveRecord)。

activerecord:
  attributes:
    article:
      cost: "Total cost"

label(:cost)
# => <label for="article_cost">Total cost</label>

label(:title, "A short title")
# => <label for="article_title">A short title</label>

label(:title, "A short title", class: "title_label")
# => <label for="article_title" class="title_label">A short title</label>

label(:privacy, "Public Article", value: "public")
# => <label for="article_privacy_public">Public Article</label>

label(:cost) do |translation|
  content_tag(:span, translation, class: "cost_label")
end
# => <label for="article_cost"><span class="cost_label">Total cost</span></label>

label(:cost) do |builder|
  content_tag(:span, builder.translation, class: "cost_label")
end
# => <label for="article_cost"><span class="cost_label">Total cost</span></label>

label(:cost) do |builder|
  content_tag(:span, builder.translation, class: [
    "cost_label",
    ("error_label" if builder.object.errors.include?(:cost))
  ])
end
# => <label for="article_cost"><span class="cost_label error_label">Total cost</span></label>

label(:terms) do
  raw('Accept <a href="/terms">Terms</a>.')
end
# => <label for="article_terms">Accept <a href="/terms">Terms</a>.</label>
# File actionview/lib/action_view/helpers/form_helper.rb, line 2404
def label(method, text = nil, options = {}, &block)
  @template.label(@object_name, method, text, objectify_options(options), &block)
end

month_field(method, options = {})

包装ActionView::Helpers::FormHelper#month_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.month_field :birthday_month %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1947
      

multipart=(multipart)

# File actionview/lib/action_view/helpers/form_helper.rb, line 1700
def multipart=(multipart)
  @multipart = multipart

  if parent_builder = @options[:parent_builder]
    parent_builder.multipart = multipart
  end
end

number_field(method, options = {})

包装ActionView::Helpers::FormHelper#number_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.number_field :age %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1999
      

password_field(method, options = {})

包装ActionView::Helpers::FormHelper#password_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.password_field :password %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1817
      

phone_field(method, options = {})

包装ActionView::Helpers::FormHelper#phone_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.phone_field :phone %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1882
      

radio_button(method, tag_value, options = {})

返回一个单选按钮标签,用于访问模板中分配的对象(由object标识)上的特定属性(由method标识)。如果method的当前值为tag_value,则单选按钮将被选中。

要强制选中单选按钮,请在options哈希中传递checked: true。您也可以在那里传递 HTML 选项。

# Let's say that @article.category returns "rails":
radio_button("category", "rails")
radio_button("category", "java")
# => <input type="radio" id="article_category_rails" name="article[category]" value="rails" checked="checked" />
#    <input type="radio" id="article_category_java" name="article[category]" value="java" />

# Let's say that @user.receive_newsletter returns "no":
radio_button("receive_newsletter", "yes")
radio_button("receive_newsletter", "no")
# => <input type="radio" id="user_receive_newsletter_yes" name="user[receive_newsletter]" value="yes" />
#    <input type="radio" id="user_receive_newsletter_no" name="user[receive_newsletter]" value="no" checked="checked" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 2496
def radio_button(method, tag_value, options = {})
  @template.radio_button(@object_name, method, tag_value, objectify_options(options))
end

range_field(method, options = {})

包装ActionView::Helpers::FormHelper#range_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.range_field :age %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 2012
      

rich_text_area(method, options = {})

别名:rich_textarea

rich_textarea(method, options = {})

包装ActionView::Helpers::FormHelper#rich_textarea用于表单构建器

<%= form_with model: @message do |f| %>
  <%= f.rich_textarea :content %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

也称为别名:rich_text_area
# File actiontext/app/helpers/action_text/tag_helper.rb, line 101
def rich_textarea(method, options = {})
  @template.rich_textarea(@object_name, method, objectify_options(options))
end

search_field(method, options = {})

包装ActionView::Helpers::FormHelper#search_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.search_field :name %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1856
      

select(method, choices = nil, options = {}, html_options = {}, &block)

包装ActionView::Helpers::FormOptionsHelper#select用于表单构建器

<%= form_with model: @post do |f| %>
  <%= f.select :person_id, Person.all.collect { |p| [ p.name, p.id ] }, include_blank: true %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 849
def select(method, choices = nil, options = {}, html_options = {}, &block)
  @template.select(@object_name, method, choices, objectify_options(options), @default_html_options.merge(html_options), &block)
end

submit(value = nil, options = {})

为给定的表单添加提交按钮。当没有给出值时,它会检查对象是新的资源还是旧的,以创建正确的标签

<%= form_with model: @article do |f| %>
  <%= f.submit %>
<% end %>

在上面的示例中,如果@article是一个新记录,它将使用“创建文章”作为提交按钮标签;否则,它将使用“更新文章”。

这些标签可以使用 I18n 在helpers.submit键下进行自定义,并使用%{model}进行翻译插值。

en:
  helpers:
    submit:
      create: "Create a %{model}"
      update: "Confirm changes to %{model}"

它还会搜索特定于给定对象的键

en:
  helpers:
    submit:
      article:
        create: "Add %{model}"
# File actionview/lib/action_view/helpers/form_helper.rb, line 2589
def submit(value = nil, options = {})
  value, options = nil, value if value.is_a?(Hash)
  value ||= submit_default_value
  @template.submit_tag(value, options)
end

telephone_field(method, options = {})

包装ActionView::Helpers::FormHelper#telephone_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.telephone_field :phone %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1869
      

text_area

别名:textarea

text_field(method, options = {})

包装ActionView::Helpers::FormHelper#text_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.text_field :name %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1804
      

textarea(method, options = {})

包装ActionView::Helpers::FormHelper#textarea用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.textarea :detail %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

也称为别名:text_area
# File actionview/lib/action_view/helpers/form_helper.rb, line 1830
      

time_field(method, options = {})

包装ActionView::Helpers::FormHelper#time_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.time_field :born_at %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1908
      

time_select(method, options = {}, html_options = {})

包装ActionView::Helpers::DateHelper#time_select用于表单构建器

<%= form_with model: @race do |f| %>
  <%= f.time_select :average_lap %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/date_helper.rb, line 1249
def time_select(method, options = {}, html_options = {})
  @template.time_select(@object_name, method, objectify_options(options), html_options)
end

time_zone_select(method, priority_zones = nil, options = {}, html_options = {})

包装ActionView::Helpers::FormOptionsHelper#time_zone_select用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.time_zone_select :time_zone, nil, include_blank: true %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 885
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
  @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_html_options.merge(html_options))
end

to_model()

# File actionview/lib/action_view/helpers/form_helper.rb, line 1716
def to_model
  self
end

to_partial_path()

# File actionview/lib/action_view/helpers/form_helper.rb, line 1712
def to_partial_path
  self.class._to_partial_path
end

url_field(method, options = {})

包装ActionView::Helpers::FormHelper#url_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.url_field :homepage %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1973
      

week_field(method, options = {})

包装ActionView::Helpers::FormHelper#week_field用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.week_field :birthday_week %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1960
      

weekday_select(method, options = {}, html_options = {})

包装ActionView::Helpers::FormOptionsHelper#weekday_select用于表单构建器

<%= form_with model: @user do |f| %>
  <%= f.weekday_select :weekday, include_blank: true %>
  <%= f.submit %>
<% end %>

请参考基本助手的文档以了解更多详细信息。

# File actionview/lib/action_view/helpers/form_options_helper.rb, line 897
def weekday_select(method, options = {}, html_options = {})
  @template.weekday_select(@object_name, method, objectify_options(options), @default_html_options.merge(html_options))
end