跳至内容 跳至搜索

Action View 表单帮助器

与使用原始 HTML 相比,表单帮助器旨在让使用资源变得更加容易。

通常,用于创建或更新资源的表单以多种方式反映资源的身份:(i) 表单发送到的 URL(表单元素的 action 属性)应导致请求被路由到适当的控制器操作(对于现有资源,应在 :id 参数中使用适当的值),(ii) 输入字段的命名方式应使它们的值在控制器中出现在 params 哈希中的适当位置,(iii) 对于现有记录,当最初显示表单时,对应于资源属性的输入字段应显示这些属性的当前值。

在 Rails 中,这通常是通过使用 form_for 和一些相关的帮助器方法来创建表单来实现的。form_for 会生成一个适当的 form 标记,并生成一个表单构建器对象,该对象知道表单所涉及的模型。通过调用表单构建器上定义的方法来创建输入字段,这意味着它们能够生成与模型属性相对应的适当名称和默认值,以及方便的 ID 等。生成字段名称中的约定允许控制器在 params 中接收结构良好的表单数据,而无需你进行任何操作。

例如,要创建新人员,你通常会在 PeopleController#new 操作中设置 Person 的新实例 @person,并在视图模板中将该对象传递给 form_for

<%= form_for @person do |f| %>
  <%= f.label :first_name %>:
  <%= f.text_field :first_name %><br />

  <%= f.label :last_name %>:
  <%= f.text_field :last_name %><br />

  <%= f.submit %>
<% end %>

为此生成的 HTML 将是(模数格式)

<form action="/people" class="new_person" id="new_person" method="post">
  <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
  <label for="person_first_name">First name</label>:
  <input id="person_first_name" name="person[first_name]" type="text" /><br />

  <label for="person_last_name">Last name</label>:
  <input id="person_last_name" name="person[last_name]" type="text" /><br />

  <input name="commit" type="submit" value="Create Person" />
</form>

如你所见,HTML 在多个地方反映了资源的知识,比如表单应该提交到的路径,或者输入字段的名称。

特别是,由于遵循了生成字段名称中的约定,控制器获得一个嵌套哈希 params[:person],其中包含表单中设置的人员属性。该哈希已准备好传递给 Person.new

@person = Person.new(params[:person])
if @person.save
  # success
else
  # error handling
end

有趣的是,上一个示例中的完全相同的视图代码可用于编辑一个人。如果 @person 是一个现有记录,名称为“John Smith”,ID 为 256,则上面的代码将产生

<form action="/people/256" class="edit_person" id="edit_person_256" method="post">
  <input name="_method" type="hidden" value="patch" />
  <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
  <label for="person_first_name">First name</label>:
  <input id="person_first_name" name="person[first_name]" type="text" value="John" /><br />

  <label for="person_last_name">Last name</label>:
  <input id="person_last_name" name="person[last_name]" type="text" value="Smith" /><br />

  <input name="commit" type="submit" value="Update Person" />
</form>

请注意,端点、默认值和提交按钮标签是针对 @person 量身定制的。这样做是因为涉及的帮助器知道资源是新记录还是不是,并相应地生成 HTML。

控制器将再次在 params[:person] 中接收表单数据,准备好传递给 Person#update

if @person.update(params[:person])
  # success
else
  # error handling
end

这就是你通常处理资源的方式。

方法
C
D
E
F
H
L
M
N
P
R
S
T
U
W
包含的模块

实例公共方法

check_box(object_name, 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.check_box :paid %>
  ...
<% end %>

因为参数名称重复正是 Rails 试图区分数组元素的地方。对于每个带有选中复选框的项目,您都会获得一个仅具有该属性的额外幽灵项目,分配给“0”。

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

示例

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

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

check_box("eula", "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" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1343
def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
  Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render
end

color_field(object_name, method, options = {})

返回类型为“color”的 text_field

color_field("car", "color")
# => <input id="car_color" name="car[color]" type="color" value="#000000" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1373
def color_field(object_name, method, options = {})
  Tags::ColorField.new(object_name, method, self, options).render
end

date_field(object_name, method, options = {})

返回类型为“日期”的 text_field

date_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" />

默认值通过尝试对对象的值调用使用“%Y-%m-%d”的 strftime 来生成,这使其对 DateTimeActiveSupport::TimeWithZone 的实例表现得符合预期。您仍然可以通过明确传递“value”选项来覆盖它,例如。

@user.born_on = Date.new(1984, 1, 27)
date_field("user", "born_on", value: "1984-05-12")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-05-12" />

您可以通过将 DateTime 的实例传递给选项哈希来创建“min”和“max”属性的值。

date_field("user", "born_on", min: Date.today)
# => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" />

或者,您可以将格式化为 ISO8601 日期形式的 String 作为“min”和“max”的值传递。

date_field("user", "born_on", min: "2014-05-20")
# => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1437
def date_field(object_name, method, options = {})
  Tags::DateField.new(object_name, method, self, options).render
end

datetime_field(object_name, method, options = {})

返回类型为“datetime-local”的 text_field

datetime_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" />

默认值通过尝试对对象的值调用使用“%Y-%m-%dT%T”的 strftime 来生成,这使其对 DateTimeActiveSupport::TimeWithZone 的实例表现得符合预期。

@user.born_on = Date.new(1984, 1, 12)
datetime_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="1984-01-12T00:00:00" />

您可以通过将 DateTime 的实例传递给选项哈希来创建“min”和“max”属性的值。

datetime_field("user", "born_on", min: Date.today)
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />

或者,您可以将格式化为 ISO8601 日期时间的 String 作为“min”和“max”的值传递。

datetime_field("user", "born_on", min: "2014-05-20T00:00:00")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />

默认情况下,提供的日期时间将包括秒进行格式化。您可以通过传递 include_seconds: false 来仅呈现日期、小时和分钟。

@user.born_on = Time.current
datetime_field("user", "born_on", include_seconds: false)
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="2014-05-20T14:35" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1510
def datetime_field(object_name, method, options = {})
  Tags::DatetimeLocalField.new(object_name, method, self, options).render
end

datetime_local_field(object_name, method, options = {})

别名:datetime_field

email_field(object_name, method, options = {})

返回类型为“email”的 text_field

email_field("user", "address")
# => <input id="user_address" name="user[address]" type="email" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1564
def email_field(object_name, method, options = {})
  Tags::EmailField.new(object_name, method, self, options).render
end

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

使用显式范围或模型对输入字段进行范围限定。类似于 form_with 使用 :scope:model 的方式,但它不会输出表单标记。

# Using a scope prefixes the input field names:
<%= fields :comment do |fields| %>
  <%= fields.text_field :body %>
<% end %>
# => <input type="text" name="comment[body]">

# Using a model infers the scope and assigns field values:
<%= fields model: Comment.new(body: "full bodied") do |fields| %>
  <%= fields.text_field :body %>
<% end %>
# => <input type="text" name="comment[body]" value="full bodied">

# Using +fields+ with +form_with+:
<%= form_with model: @post do |form| %>
  <%= form.text_field :title %>

  <%= form.fields :comment do |fields| %>
    <%= fields.text_field :body %>
  <% end %>
<% end %>

form_with 非常相似,会生成与范围或模型关联的 FormBuilder 实例,因此任何生成的字段名称都会以传递的范围或从 :model 推断的范围为前缀。

与其他表单帮助程序混合使用

虽然 form_with 使用 FormBuilder 对象,但可以混合匹配独立的 FormHelper 方法和 FormTagHelper 中的方法

<%= fields model: @comment do |fields| %>
  <%= fields.text_field :body %>

  <%= text_area :commenter, :biography %>
  <%= check_box_tag "comment[all_caps]", "1", @comment.commenter.hulk_mode? %>
<% end %>

对于 FormOptionsHelperDateHelper 中旨在以对象为基础的方法(例如 FormOptionsHelper#collection_selectDateHelper#datetime_select),也是如此。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1077
def fields(scope = nil, model: nil, **options, &block)
  options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)

  if model
    model   = _object_for_form_builder(model)
    scope ||= model_name_from_record_or_class(model).param_key
  end

  builder = instantiate_builder(scope, model, options)
  capture(builder, &block)
end

fields_for(record_name, record_object = nil, options = {}, &block)

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

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

<%= form_for @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.check_box :admin %>
  <% end %>

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

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

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

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

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

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

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

并且 fields_for 将从模型对象的中推导出字段的必需名称,例如,如果 @person.permissionPermission 类,则字段仍将命名为 permission[admin]

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

嵌套属性示例

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

嵌套属性写入器是根据关联命名的普通设置器方法。定义这些写入器的最常见方法是,在模型定义中使用 `accepts_nested_attributes_for`,或通过定义一个具有适当名称的方法。例如:关联 `:address` 的属性写入器称为 `address_attributes=`。

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

一对一

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

class Person
  def address
    @address
  end

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

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

<%= form_for @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_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :address do |address_fields| %>
    ...
    Delete: <%= address_fields.check_box :_destroy %>
  <% end %>
  ...
<% end %>

一对多

考虑一个 Person 类,它从 `projects` 读取器方法返回一个 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_for @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_for @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_for @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_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    Delete: <%= project_fields.check_box :_destroy %>
  <% end %>
  ...
<% end %>

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

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

请注意,如果 fields_for 响应 persisted?,它将自动生成一个隐藏字段来存储记录的 ID。在某些情况下,不需要此隐藏字段,你可以传递 include_id: false 来阻止 fields_for 自动呈现它。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1026
def fields_for(record_name, record_object = nil, options = {}, &block)
  options = { model: record_object, allow_method_names_outside_object: false, skip_default_ids: false }.merge!(options)

  fields(record_name, **options, &block)
end

file_field(object_name, method, options = {})

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

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

选项

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

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

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

  • :include_hidden - 当 multiple: trueinclude_hidden: true 时,该字段将以一个值为空的 <input type="hidden"> 字段作为前缀,以支持提交一个空的文件集合。

  • :accept - 如果设置为一个或多个 MIME 类型,用户在选择文件时将被建议使用一个过滤器。你仍然需要设置模型验证。

示例

file_field(:user, :avatar)
# => <input type="file" id="user_avatar" name="user[avatar]" />

file_field(:post, :image, multiple: true)
# => <input type="file" id="post_image" name="post[image][]" multiple="multiple" />

file_field(:post, :attached, accept: 'text/html')
# => <input accept="text/html" type="file" id="post_attached" name="post[attached]" />

file_field(:post, :image, accept: 'image/png,image/gif,image/jpeg')
# => <input type="file" id="post_image" name="post[image]" accept="image/png,image/gif,image/jpeg" />

file_field(:attachment, :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 1245
def file_field(object_name, method, options = {})
  options = { include_hidden: multiple_file_field_include_hidden }.merge!(options)

  Tags::FileField.new(object_name, method, self, convert_direct_upload_option_to_url(options.dup)).render
end

form_for(record, options = {}, &block)

创建一个表单,允许用户创建或更新特定模型对象的属性。

此方法可以以几种略有不同的方式使用,具体取决于你希望在多大程度上依赖 Rails 根据模型自动推断表单的构建方式。对于一个通用的模型对象,可以通过向 form_for 传递一个表示我们关注的对象的字符串或符号来创建一个表单

<%= form_for :person do |f| %>
  First name: <%= f.text_field :first_name %><br />
  Last name : <%= f.text_field :last_name %><br />
  Biography : <%= f.text_area :biography %><br />
  Admin?    : <%= f.check_box :admin %><br />
  <%= f.submit %>
<% end %>

传递给块的变量 f 是一个 FormBuilder 对象,它包含了传递给 form_for:person 所表示的模型对象的相关知识。在 FormBuilder 上定义的方法用于生成绑定到此模型的字段。因此,例如,

<%= f.text_field :first_name %>

将扩展为

<%= text_field :person, :first_name %>

这将生成一个 HTML <input> 标签,其 name 属性为 person[first_name]。这意味着当提交表单时,用户输入的值将作为 params[:person][:first_name] 在控制器中可用。

对于使用 FormBuilder 以这种方式生成的字段,如果 :person 也恰好是实例变量 @person 的名称,则表单最初显示时显示的字段的默认值(例如,在编辑现有记录的情况下)将是 @person 的相应属性的值。

form_for 最右边的参数是一个可选的选项哈希表 -

  • :url - 提交表单的 URL。这可以表示为传递给 url_forlink_to 的值。因此,例如,你可以直接使用命名路由。当模型由字符串或符号表示时(如上例所示),如果未指定 :url 选项,则默认情况下表单将发送回当前 URL(我们将在下面描述 form_for 的另一种面向资源的用法,其中不需要显式指定 URL)。

  • :namespace - 表单的命名空间,以确保表单元素的 id 属性的唯一性。命名空间属性将在生成的 HTML id 上加上下划线前缀。

  • :method - 提交表单时使用的方法,通常是“get”或“post”。如果使用“patch”、“put”、“delete”或其他动词,则会添加一个名称为 _method 的隐藏输入,以通过 post 模拟动词。

  • :authenticity_token - 在表单中使用的真实性令牌。仅在需要传递自定义真实性令牌字符串或根本不添加真实性令牌字段(通过传递 false)时使用。远程表单可以通过设置 config.action_view.embed_authenticity_token_in_remote_forms = false 来省略嵌入式真实性令牌。当对表单进行片段缓存时,这很有用。远程表单从 meta 标签获取真实性令牌,因此除非支持没有 JavaScript 的浏览器,否则无需嵌入。

  • :remote - 如果设置为 true,将允许非侵入式 JavaScript 驱动程序控制提交行为。

  • :enforce_utf8 - 如果设置为 false,则不会输出名称为 utf8 的隐藏输入。

  • :html - 表单标签的可选 HTML 属性。

另外请注意,form_for 不会创建一个排他范围。仍然可以使用独立的 FormHelper 方法和 FormTagHelper 的方法。例如

<%= form_for :person do |f| %>
  First name: <%= f.text_field :first_name %>
  Last name : <%= f.text_field :last_name %>
  Biography : <%= text_area :person, :biography %>
  Admin?    : <%= check_box_tag "person[admin]", "1", @person.company.admin? %>
  <%= f.submit %>
<% end %>

这还适用于 FormOptionsHelperDateHelper 中的方法,这些方法被设计为使用对象作为基础,如 FormOptionsHelper#collection_selectDateHelper#datetime_select

form_for 与模型对象

在上面的示例中,要创建或编辑的对象由传递给 form_for 的符号表示,并且我们注意到也可以等效地使用字符串。但是,也可以将模型对象本身传递给 form_for。例如,如果 @post 是要编辑的现有记录,则可以使用以下方式创建表单

<%= form_for @post do |f| %>
  ...
<% end %>

这的行为几乎与前面概述的一样,只有几个小例外。首先,用于命名表单中输入元素的前缀(因此是 params 哈希中表示它们的键)实际上是从对象的派生的,例如,如果对象的类是 Post,则为 params[:post]。但是,可以使用 :as 选项覆盖此项,例如 -

<%= form_for(@person, as: :client) do |f| %>
  ...
<% end %>

将导致 params[:client]

其次,表单最初显示时的字段值取自传递给 form_for 的对象的属性,无论该对象是否是实例变量。因此,例如,如果我们有一个表示现有记录的局部变量 post

<%= form_for post do |f| %>
  ...
<% end %>

将生成一个表单,其字段的初始状态反映 post 的属性的当前值。

面向资源的样式

在刚刚显示的示例中,尽管没有明确指出,但我们仍然需要使用 :url 选项来指定将表单发送到的位置。但是,如果传递给 form_for 的记录是资源,即它对应于一组 RESTful 路由(例如,使用 config/routes.rb 中的 resources 方法定义),则可以进一步简化。在这种情况下,Rails 将简单地从记录本身推断出适当的 URL。例如,

<%= form_for @post do |f| %>
  ...
<% end %>

然后等效于类似以下内容

<%= form_for @post, as: :post, url: post_path(@post), method: :patch, html: { class: "edit_post", id: "edit_post_45" } do |f| %>
  ...
<% end %>

对于新记录

<%= form_for(Post.new) do |f| %>
  ...
<% end %>

相当于类似内容

<%= form_for @post, as: :post, url: posts_path, html: { class: "new_post", id: "new_post" } do |f| %>
  ...
<% end %>

但是,您仍然可以覆盖各个约定,例如

<%= form_for(@post, url: super_posts_path) do |f| %>
  ...
<% end %>

您可以通过传递 url: false 来省略 action 属性

<%= form_for(@post, url: false) do |f| %>
  ...
<% end %>

您还可以设置答案格式,如下所示

<%= form_for(@post, format: :json) do |f| %>
  ...
<% end %>

对于命名空间路由,例如 admin_post_url

<%= form_for([:admin, @post]) do |f| %>
 ...
<% end %>

如果您的资源已定义关联,例如,您希望在路由设置正确的情况下向文档添加评论

<%= form_for([@document, @comment]) do |f| %>
 ...
<% end %>

其中 @document = Document.find(params[:id])@comment = Comment.new

设置方法

您可以通过设置

method: (:get|:post|:patch|:put|:delete)

在选项哈希中强制表单使用完整的 HTTP 动词数组。如果动词不是 HTML 表单本机支持的 GET 或 POST,则表单将设置为 POST,并且名为 _method 的隐藏输入将承载服务器解释的目标动词。

非侵入式 JavaScript

指定

remote: true

在选项哈希中创建一个表单,该表单将允许非侵入式 JavaScript 驱动程序修改其行为。表单提交将像接收方看到的常规提交一样工作(params 中的所有元素)。

示例

<%= form_for(@post, remote: true) do |f| %>
  ...
<% end %>

为此生成的 HTML 将是

<form action='http://www.example.com' method='post' data-remote='true'>
  <input name='_method' type='hidden' value='patch' />
  ...
</form>

设置 HTML 选项

您可以通过传入数据哈希直接设置数据属性,但所有其他 HTML 选项都必须包装在 HTML 键中。示例

<%= form_for(@post, data: { behavior: "autosave" }, html: { name: "go" }) do |f| %>
  ...
<% end %>

为此生成的 HTML 将是

<form action='http://www.example.com' method='post' data-behavior='autosave' name='go'>
  <input name='_method' type='hidden' value='patch' />
  ...
</form>

删除隐藏的模型 ID

form_for 方法自动将模型 ID 作为隐藏字段包含在表单中。这用于保持表单数据与其关联模型之间的关联。一些 ORM 系统不会在嵌套模型上使用 ID,因此在这种情况下,您希望能够禁用隐藏 ID。

在以下示例中,Post 模型在其内部存储了许多 Comment,它们存储在 NoSQL 数据库中,因此没有评论的主键。

示例

<%= form_for(@post) do |f| %>
  <%= f.fields_for(:comments, include_id: false) do |cf| %>
    ...
  <% end %>
<% end %>

自定义表单生成器

您还可以使用自定义 FormBuilder 类构建表单。子类化 FormBuilder 并覆盖或定义更多帮助器,然后使用您的自定义生成器。例如,假设您创建了一个帮助器来自动向表单输入添加标签。

<%= form_for @person, url: { action: "create" }, builder: LabellingFormBuilder do |f| %>
  <%= f.text_field :first_name %>
  <%= f.text_field :last_name %>
  <%= f.text_area :biography %>
  <%= f.check_box :admin %>
  <%= f.submit %>
<% end %>

在这种情况下,如果您使用此

<%= render f %>

渲染的模板是 people/_labelling_form,引用表单构建器的局部变量称为 labelling_form

自定义 FormBuilder 类会自动与嵌套 fields_for 调用的选项合并,除非显式设置。

在很多情况下,你可能希望将上述内容包装在另一个帮助器中,因此你可以执行类似以下操作

def labelled_form_for(record_or_name_or_array, *args, &block)
  options = args.extract_options!
  form_for(record_or_name_or_array, *(args << options.merge(builder: LabellingFormBuilder)), &block)
end

如果你不需要将表单附加到模型实例,请查看 FormTagHelper#form_tag

表单到外部资源

当你构建表单到外部资源时,有时你需要设置真实性令牌或仅渲染表单而不使用它,例如当你将数据提交到支付网关时,字段的数量和类型可能会受到限制。

要设置真实性令牌,你需要传递一个 :authenticity_token 参数

<%= form_for @invoice, url: external_url, authenticity_token: 'external_token' do |f| %>
  ...
<% end %>

如果你根本不想渲染真实性令牌字段,只需传递 false

<%= form_for @invoice, url: external_url, authenticity_token: false do |f| %>
  ...
<% end %>
# File actionview/lib/action_view/helpers/form_helper.rb, line 434
def form_for(record, options = {}, &block)
  raise ArgumentError, "Missing block" unless block_given?

  case record
  when String, Symbol
    model       = nil
    object_name = record
  else
    model       = record
    object      = _object_for_form_builder(record)
    raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
    object_name = options[:as] || model_name_from_record_or_class(object).param_key
    apply_form_for_options!(object, options)
  end

  remote = options.delete(:remote)

  if remote && !embed_authenticity_token_in_remote_forms && options[:authenticity_token].blank?
    options[:authenticity_token] = false
  end

  options[:model]                               = model
  options[:scope]                               = object_name
  options[:local]                               = !remote
  options[:skip_default_ids]                    = false
  options[:allow_method_names_outside_object]   = options.fetch(:allow_method_names_outside_object, false)

  form_with(**options, &block)
end

form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)

基于混合 URL、作用域或模型创建表单标记。

# Using just a URL:
<%= form_with url: posts_path do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/posts" method="post">
  <input type="text" name="title">
</form>

# With an intentionally empty URL:
<%= form_with url: false do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form method="post">
  <input type="text" name="title">
</form>

# Adding a scope prefixes the input field names:
<%= form_with scope: :post, url: posts_path do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/posts" method="post">
  <input type="text" name="post[title]">
</form>

# Using a model infers both the URL and scope:
<%= form_with model: Post.new do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/posts" method="post">
  <input type="text" name="post[title]">
</form>

# An existing model makes an update form and fills out field values:
<%= form_with model: Post.first do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/posts/1" method="post">
  <input type="hidden" name="_method" value="patch">
  <input type="text" name="post[title]" value="<the title of the post>">
</form>

# Though the fields don't have to correspond to model attributes:
<%= form_with model: Cat.new do |form| %>
  <%= form.text_field :cats_dont_have_gills %>
  <%= form.text_field :but_in_forms_they_can %>
<% end %>
# =>
<form action="/cats" method="post">
  <input type="text" name="cat[cats_dont_have_gills]">
  <input type="text" name="cat[but_in_forms_they_can]">
</form>

表单中的参数可根据其名称嵌套在控制器中访问。因此,名为 titlepost[title] 的输入分别可作为 params[:title]params[:post][:title] 访问。

为了便于比较,上述示例省略了提交按钮,以及启用 UTF-8 支持并添加跨站点请求伪造保护所需的真实性令牌的自动生成的隐藏字段。

面向资源的样式

在刚刚显示的许多示例中,传递给 form_with:model 是一个资源。它对应于一组 RESTful 路由,很可能通过 config/routes.rb 中的 resources 定义。

因此,在传递此类模型记录时,Rails 会推断出 URL 和方法。

<%= form_with model: @post do |form| %>
  ...
<% end %>

然后等效于类似以下内容

<%= form_with scope: :post, url: post_path(@post), method: :patch do |form| %>
  ...
<% end %>

对于新记录

<%= form_with model: Post.new do |form| %>
  ...
<% end %>

相当于类似内容

<%= form_with scope: :post, url: posts_path do |form| %>
  ...
<% end %>

form_with 选项

  • :url - 表单提交到的 URL。类似于传递给 url_forlink_to 的值。例如,你可以直接使用命名路由。当传递 :scope 而没有 :url 时,表单只会提交到当前 URL。

  • :method - 提交表单时使用的方法,通常为“get”或“post”。如果使用“patch”、“put”、“delete”或其他动词,则会添加一个名为 _method 的隐藏输入,以通过 post 模拟动词。

  • :format - 表单提交到的路由的格式。在提交到其他资源类型(如 :json)时很有用。如果传递了 :url,则会跳过。

  • :scope - 输入字段名称的前缀范围,以及控制器中提交的参数分组方式。

  • :namespace - 表单的命名空间,以确保表单元素的 id 属性的唯一性。命名空间属性将在生成的 HTML id 上加上下划线前缀。

  • :model - 一个模型对象,用于推断 :url:scope,以及填充输入字段值。因此,如果 title 属性设置为“Ahoy!”,则 title 输入字段的值将为“Ahoy!”。如果模型是一个新记录,则会生成一个创建表单,但如果是一个现有记录,则会生成一个更新表单。传递 :scope:url 以覆盖默认值。例如,将 params[:post] 变成 params[:article]

  • :authenticity_token - 表单中使用的真实性令牌。使用自定义真实性令牌覆盖,或传递 false 以完全跳过真实性令牌字段。在提交到外部资源(如支付网关)时很有用,外部资源可能会限制有效字段。远程表单可以通过设置 config.action_view.embed_authenticity_token_in_remote_forms = false 来省略嵌入式真实性令牌。当对表单进行片段缓存时,这很有用。远程表单从 meta 标签获取真实性令牌,因此除非您支持没有 JavaScript 的浏览器,否则无需嵌入。

  • :local - 是否使用标准 HTTP 表单提交。当设置为 true 时,表单通过标准 HTTP 提交。当设置为 false 时,表单作为“远程表单”提交,由 Rails UJS 作为 XHR 处理。当未指定时,行为是从 config.action_view.form_with_generates_remote_forms 派生的,其中配置的值实际上是 local 值的相反值。从 Rails 6.1 开始,该配置选项默认为 false(其效果等同于传递 local: true)。在之前的 Rails 版本中,该配置选项默认为 true(等同于传递 local: false)。

  • :skip_enforcing_utf8 - 如果设置为 true,则不会输出名称为 utf8 的隐藏输入。

  • :builder - 覆盖用于构建表单的对象。

  • :id - 可选的 HTML id 属性。

  • :class - 可选的 HTML class 属性。

  • :data - 可选的 HTML 数据属性。

  • :html - 表单标记的其他可选 HTML 属性。

示例

如果不传递块,form_with 只会生成一个打开表单标记。

<%= form_with(model: @post, url: super_posts_path) %>
<%= form_with(model: @post, scope: :article) %>
<%= form_with(model: @post, format: :json) %>
<%= form_with(model: @post, authenticity_token: false) %> # Disables the token.

对于命名空间路由,例如 admin_post_url

<%= form_with(model: [ :admin, @post ]) do |form| %>
  ...
<% end %>

如果您的资源已定义关联,例如,您希望在路由设置正确的情况下向文档添加评论

<%= form_with(model: [ @document, Comment.new ]) do |form| %>
  ...
<% end %>

其中 @document = Document.find(params[:id])

与其他表单帮助程序混合使用

虽然 form_with 使用 FormBuilder 对象,但可以混合匹配独立的 FormHelper 方法和 FormTagHelper 中的方法

<%= form_with scope: :person do |form| %>
  <%= form.text_field :first_name %>
  <%= form.text_field :last_name %>

  <%= text_area :person, :biography %>
  <%= check_box_tag "person[admin]", "1", @person.company.admin? %>

  <%= form.submit %>
<% end %>

对于 FormOptionsHelperDateHelper 中旨在以对象为基础的方法(例如 FormOptionsHelper#collection_selectDateHelper#datetime_select),也是如此。

设置方法

您可以通过设置

method: (:get|:post|:patch|:put|:delete)

在选项哈希中强制表单使用完整的 HTTP 动词数组。如果动词不是 HTML 表单本机支持的 GET 或 POST,则表单将设置为 POST,并且名为 _method 的隐藏输入将承载服务器解释的目标动词。

设置 HTML 选项

你可以直接在数据哈希中设置数据属性,但 id 和 class 之外的 HTML 选项必须包装在 HTML 键中

<%= form_with(model: @post, data: { behavior: "autosave" }, html: { name: "go" }) do |form| %>
  ...
<% end %>

生成

<form action="/posts/123" method="post" data-behavior="autosave" name="go">
  <input name="_method" type="hidden" value="patch" />
  ...
</form>

删除隐藏的模型 ID

form_with 方法自动将模型 id 作为隐藏字段包含在表单中。这用于维护表单数据与其关联模型之间的关联。一些 ORM 系统在嵌套模型中不使用 ID,因此在这种情况下,你希望能够禁用隐藏 id。

在以下示例中,Post 模型在其内部存储了许多 Comment,它们存储在 NoSQL 数据库中,因此没有评论的主键。

<%= form_with(model: @post) do |form| %>
  <%= form.fields(:comments, skip_id: true) do |fields| %>
    ...
  <% end %>
<% end %>

自定义表单生成器

您还可以使用自定义 FormBuilder 类构建表单。子类化 FormBuilder 并覆盖或定义更多帮助器,然后使用您的自定义生成器。例如,假设您创建了一个帮助器来自动向表单输入添加标签。

<%= form_with model: @person, url: { action: "create" }, builder: LabellingFormBuilder do |form| %>
  <%= form.text_field :first_name %>
  <%= form.text_field :last_name %>
  <%= form.text_area :biography %>
  <%= form.check_box :admin %>
  <%= form.submit %>
<% end %>

在这种情况下,如果你使用

<%= render form %>

渲染的模板是 people/_labelling_form,引用表单构建器的局部变量称为 labelling_form

自定义 FormBuilder 类会自动与嵌套 fields 调用的选项合并,除非它被显式设置。

在很多情况下,你可能希望将上述内容包装在另一个帮助器中,因此你可以执行类似以下操作

def labelled_form_with(**options, &block)
  form_with(**options.merge(builder: LabellingFormBuilder), &block)
end
# File actionview/lib/action_view/helpers/form_helper.rb, line 755
def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
  options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)

  if model
    if url != false
      url ||= if format.nil?
        polymorphic_path(model, {})
      else
        polymorphic_path(model, format: format)
      end
    end

    model   = convert_to_model(_object_for_form_builder(model))
    scope ||= model_name_from_record_or_class(model).param_key
  end

  if block_given?
    builder = instantiate_builder(scope, model, options)
    output  = capture(builder, &block)
    options[:multipart] ||= builder.multipart?

    html_options = html_options_for_form_with(url, model, **options)
    form_tag_with_body(html_options, output)
  else
    html_options = html_options_for_form_with(url, model, **options)
    form_tag_html(html_options)
  end
end

hidden_field(object_name, method, options = {})

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

示例

hidden_field(:signup, :pass_confirm)
# => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{@signup.pass_confirm}" />

hidden_field(:post, :tag_list)
# => <input type="hidden" id="post_tag_list" name="post[tag_list]" value="#{@post.tag_list}" />

hidden_field(:user, :token)
# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1212
def hidden_field(object_name, method, options = {})
  Tags::HiddenField.new(object_name, method, self, options).render
end

label(object_name, method, content_or_options = nil, options = nil, &block)

返回一个标签标签,专门用于标记分配给模板的对象(由 object 标识)上的指定属性(由 method 标识)的输入字段。除非在当前 I18n 区域设置中找到翻译(通过 helpers.label.<modelname>.<attribute>),否则标签文本将默认为属性名称,或者你明确指定它。标签标签上的其他选项可以作为哈希与 options 一起传递。这些选项将作为 HTML 元素属性标记到 HTML 中,如所示示例,但 :value 选项除外,该选项旨在针对 radio_button 标签(其中值用于输入标签的 ID)。

示例

label(:post, :title)
# => <label for="post_title">Title</label>

你可以根据模型和属性名称本地化你的标签。例如,你可以在区域设置中定义以下内容(例如 en.yml)

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

然后将导致

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

本地化也可以完全基于属性名称的翻译(如果你正在使用 ActiveRecord

activerecord:
  attributes:
    post:
      cost: "Total cost"

label(:post, :cost)
# => <label for="post_cost">Total cost</label>

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

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

label(:post, :privacy, "Public Post", value: "public")
# => <label for="post_privacy_public">Public Post</label>

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

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

label(:post, :terms) do
  raw('Accept <a href="/terms">Terms</a>.')
end
# => <label for="post_terms">Accept <a href="/terms">Terms</a>.</label>
# File actionview/lib/action_view/helpers/form_helper.rb, line 1149
def label(object_name, method, content_or_options = nil, options = nil, &block)
  Tags::Label.new(object_name, method, self, content_or_options, options).render(&block)
end

month_field(object_name, method, options = {})

返回类型为“month”的 text_field

month_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="month" />

默认值通过尝试对对象的值调用带有“%Y-%m”的 strftime 生成,这使得它可以按预期对 DateTimeActiveSupport::TimeWithZone 的实例进行处理。

@user.born_on = Date.new(1984, 1, 27)
month_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-01" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1529
def month_field(object_name, method, options = {})
  Tags::MonthField.new(object_name, method, self, options).render
end

number_field(object_name, method, options = {})

返回类型为“number”的输入标签。

选项

支持与 FormTagHelper#number_field_tag 相同的选项。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1573
def number_field(object_name, method, options = {})
  Tags::NumberField.new(object_name, method, self, options).render
end

password_field(object_name, method, options = {})

返回一个“password”类型输入标签,该标签专门用于访问分配给模板(由 object 标识)的对象上的指定属性(由 method 标识)。输入标签上的其他选项可以作为哈希与 options 传递。这些选项将作为 HTML 元素属性标记到 HTML 中,如所示示例。出于安全原因,此字段默认情况下为空;如果不需要,请通过 options 传递一个值。

示例

password_field(:login, :pass, size: 20)
# => <input type="password" id="login_pass" name="login[pass]" size="20" />

password_field(:account, :secret, class: "form_input", value: @account.secret)
# => <input type="password" id="account_secret" name="account[secret]" value="#{@account.secret}" class="form_input" />

password_field(:user, :password, onchange: "if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }")
# => <input type="password" id="user_password" name="user[password]" onchange="if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }"/>

password_field(:account, :pin, size: 20, class: 'form_input')
# => <input type="password" id="account_pin" name="account[pin]" size="20" class="form_input" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1194
def password_field(object_name, method, options = {})
  Tags::PasswordField.new(object_name, method, self, options).render
end

phone_field(object_name, method, options = {})

别名:telephone_field

radio_button(object_name, method, tag_value, options = {})

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

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

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

# Let's say that @user.receive_newsletter returns "no":
radio_button("user", "receive_newsletter", "yes")
radio_button("user", "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 1365
def radio_button(object_name, method, tag_value, options = {})
  Tags::RadioButton.new(object_name, method, self, tag_value, options).render
end

range_field(object_name, method, options = {})

返回类型为“range”的输入标签。

选项

支持与 FormTagHelper#range_field_tag 相同的选项。

# File actionview/lib/action_view/helpers/form_helper.rb, line 1582
def range_field(object_name, method, options = {})
  Tags::RangeField.new(object_name, method, self, options).render
end

rich_text_area(object_name, method, options = {})

返回一个 trix-editor 标签,它实例化 Trix JavaScript 编辑器以及一个 Trix 在更改时写入的隐藏字段,以便在提交表单时发送内容。

选项

  • :class - 默认为“trix-content”,它确保应用默认样式。

  • :value - 向 HTML 输入标签添加默认值。

  • [:data][:direct_upload_url] - 默认为 rails_direct_uploads_url

  • [:data][:blob_url_template] - 默认为 rails_service_blob_url(":signed_id", ":filename")

示例

rich_text_area :message, :content
# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>

rich_text_area :message, :content, value: "<h1>Default message</h1>"
# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Default message</h1>">
# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
# File actiontext/app/helpers/action_text/tag_helper.rb, line 76
def rich_text_area(object_name, method, options = {})
  Tags::ActionText.new(object_name, method, self, options).render
end

search_field(object_name, method, options = {})

返回类型为“search”的输入,用于访问分配给模板(由 object_name 标识)的对象上的指定属性(由 method 标识)。类型为“search”的输入可能被某些浏览器以不同的方式设置样式。

search_field(:user, :name)
# => <input id="user_name" name="user[name]" type="search" />
search_field(:user, :name, autosave: false)
# => <input autosave="false" id="user_name" name="user[name]" type="search" />
search_field(:user, :name, results: 3)
# => <input id="user_name" name="user[name]" results="3" type="search" />
#  Assume request.host returns "www.example.com"
search_field(:user, :name, autosave: true)
# => <input autosave="com.example.www" id="user_name" name="user[name]" results="10" type="search" />
search_field(:user, :name, onsearch: true)
# => <input id="user_name" incremental="true" name="user[name]" onsearch="true" type="search" />
search_field(:user, :name, autosave: false, onsearch: true)
# => <input autosave="false" id="user_name" incremental="true" name="user[name]" onsearch="true" type="search" />
search_field(:user, :name, autosave: true, onsearch: true)
# => <input autosave="com.example.www" id="user_name" incremental="true" name="user[name]" onsearch="true" results="10" type="search" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1396
def search_field(object_name, method, options = {})
  Tags::SearchField.new(object_name, method, self, options).render
end

telephone_field(object_name, method, options = {})

返回类型为“tel”的 text_field

telephone_field("user", "phone")
# => <input id="user_phone" name="user[phone]" type="tel" />
别名:phone_field
# File actionview/lib/action_view/helpers/form_helper.rb, line 1405
def telephone_field(object_name, method, options = {})
  Tags::TelField.new(object_name, method, self, options).render
end

text_area(object_name, method, options = {})

返回一个针对访问分配给模板(由 object 标识)的对象上的指定属性(由 method 标识)而定制的 textarea 开头和结尾标签集。输入标签上的其他选项可以作为带有 options 的哈希传递。

示例

text_area(:post, :body, cols: 20, rows: 40)
# => <textarea cols="20" rows="40" id="post_body" name="post[body]">
#      #{@post.body}
#    </textarea>

text_area(:comment, :text, size: "20x30")
# => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
#      #{@comment.text}
#    </textarea>

text_area(:application, :notes, cols: 40, rows: 15, class: 'app_input')
# => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input">
#      #{@application.notes}
#    </textarea>

text_area(:entry, :body, size: "20x20", disabled: 'disabled')
# => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled">
#      #{@entry.body}
#    </textarea>
# File actionview/lib/action_view/helpers/form_helper.rb, line 1275
def text_area(object_name, method, options = {})
  Tags::TextArea.new(object_name, method, self, options).render
end

text_field(object_name, method, options = {})

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

示例

text_field(:post, :title, size: 20)
# => <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" />

text_field(:post, :title, class: "create_input")
# => <input type="text" id="post_title" name="post[title]" value="#{@post.title}" class="create_input" />

text_field(:post, :title,  maxlength: 30, class: "title_input")
# => <input type="text" id="post_title" name="post[title]" maxlength="30" size="30" value="#{@post.title}" class="title_input" />

text_field(:session, :user, onchange: "if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }")
# => <input type="text" id="session_user" name="session[user]" value="#{@session.user}" onchange="if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }"/>

text_field(:snippet, :code, size: 20, class: 'code_input')
# => <input type="text" id="snippet_code" name="snippet[code]" size="20" value="#{@snippet.code}" class="code_input" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1173
def text_field(object_name, method, options = {})
  Tags::TextField.new(object_name, method, self, options).render
end

time_field(object_name, method, options = {})

返回一个“time”类型的text_field

默认值通过尝试对对象的 value 调用“%T.%L”格式的strftime生成。如果你传递include_seconds: false,它将通过尝试对对象的 value 调用“%H:%M”格式的strftime进行格式化。也可以通过传递“value”选项来覆盖此项。

选项

支持与FormTagHelper#time_field_tag相同的选项。

示例

time_field("task", "started_at")
# => <input id="task_started_at" name="task[started_at]" type="time" />

您可以通过将 DateTime 的实例传递给选项哈希来创建“min”和“max”属性的值。

time_field("task", "started_at", min: Time.now)
# => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />

或者,你可以传递一个格式化为 ISO8601 时间的String作为“min”和“max”的值。

time_field("task", "started_at", min: "01:00:00")
# => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />

默认情况下,提供的 times 将以包括秒的形式进行格式化。你可以通过传递include_seconds: false仅呈现小时和分钟。如果你在时间戳格式中排除秒,一些浏览器将呈现一个更简单的 UI。

time_field("task", "started_at", value: Time.now, include_seconds: false)
# => <input id="task_started_at" name="task[started_at]" type="time" value="01:00" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1475
def time_field(object_name, method, options = {})
  Tags::TimeField.new(object_name, method, self, options).render
end

url_field(object_name, method, options = {})

返回一个“url”类型的text_field

url_field("user", "homepage")
# => <input id="user_homepage" name="user[homepage]" type="url" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1555
def url_field(object_name, method, options = {})
  Tags::UrlField.new(object_name, method, self, options).render
end

week_field(object_name, method, options = {})

返回一个“week”类型的text_field

week_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="week" />

默认值通过尝试对对象的 value 调用“%Y-W%W”格式的strftime生成,这使得它对DateTimeActiveSupport::TimeWithZone的实例表现如预期。

@user.born_on = Date.new(1984, 5, 12)
week_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-W19" />
# File actionview/lib/action_view/helpers/form_helper.rb, line 1546
def week_field(object_name, method, options = {})
  Tags::WeekField.new(object_name, method, self, options).render
end