略過至內容 略過至搜尋

Action View 表單輔助程式

相較於使用純 HTML,表單輔助程式旨在讓使用資源更加容易。

通常,設計用來建立或更新資源的表單會在多種方式反映資源身分:(i) 表單發送到的網址(表單元素的 action 屬性)應導致請求路由到適當的控制器動作(針對現有資源,這是適當的 :id 參數),(ii) 輸入欄位應命名,讓它們在控制器中的值出現在 params hash 的適當位置,以及 (iii) 對於現有記錄,當表單最初顯示時,對應於資源屬性的輸入欄位應顯示這些屬性的目前值。

在 Rails 中,這通常藉由使用 form_withform_for 建立表單和許多相關輔助程式方法來達成。這些方法會產生適當的 form 標籤,並產生了解表單所針對模型的表單建構函式物件。輸入欄位是透過呼叫在表單建構函式中定義的方法來建立的,這意味著它們能夠產生對應於模型屬性的適當名稱和預設值,以及合適的 ID 等資訊。產生的欄位名稱的慣例讓控制器能夠正確地接收結構化在 params 中的表單資料,而無需您額外費力。

例如,若要建立新的人物,通常會在 PeopleController#new 動作中設定 Person 的新實例 @person,然後在檢視範本中將該物件傳遞給 form_withform_for

<%= form_with model: @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 在幾個地方反映了對資源的了解,像是表單應提交到的路徑,或輸入欄位的名稱。

特別是,感謝所產生的欄位名稱所遵循的慣例,控制器會取得嵌套的 hash params[:person],其中包含表單中設定的 people 屬性。該 hash 即已準備好可以傳遞給 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")

別名:checkbox

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

傳回一個核取方塊標籤,用於存取指定屬性(由 method 識別)在指派給樣版的物件(由 object 識別)。這個物件必須是執行個體物件 (@object),而不是本機物件。method 的目的是傳回一個整數,如果該整數大於零,則核取方塊會被核取。可以透過雜湊以 options 傳遞輸入標籤上的其他選項。預設 checked_value 為 1,而 unchecked_value 會設為 0,這對於布林值來說很方便。

選項

  • 可以傳遞標籤上任何標準 HTML 屬性,例如 :class

  • :checked - truefalse 強制核取方塊的狀態為核取或不核取。

  • :include_hidden - 如果設為 false,則不會產生下面描述的輔助隱藏欄位。

Gotcha

HTML 規範稱未選取的核取方塊不成功,因此網頁瀏覽器不會傳送它們。很遺憾,這會造成一個 gotcha:如果 Invoice 模型有一個 paid 旗標,而且使用者在編輯已付發票的表單中取消選取它的核取方塊時,不會傳送 paid 參數。因此,任意大量的指派慣用語,像是

@invoice.update(params[:invoice])

不會更新旗標。

為了防止這種情況,輔助器會在每一個核取方塊之前產生一個輔助隱藏欄位。隱藏欄位有相同的名稱,而它的屬性會模仿一個未選取的核取方塊。

這樣,客戶端會只傳送隱藏欄位(代表核取方塊未選取),或是傳送兩個欄位。由於 HTML 規範稱鍵值對必須依照它們在表單中出現的順序傳送,而且參數萃取會取得查詢字串中任何重複鍵的最後一個出現,這對一般表單是有用的。

很遺憾,當核取方塊在類似陣列的參數中時,例如

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

因為參數名稱重複正是 Rails 用來區別陣列中每個元素的方式。對於每個核取方塊被選取的項目,你會得到一個只有該屬性、指派為「0」的額外 ghost 項目。

在這種情況下,最好使用 checkbox_tag 或是改用雜湊而不是陣列。

範例

# Let's say that @article.validated? is 1:
checkbox("article", "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("puppy", "gooddog", {}, "yes", "no")
# => <input name="puppy[gooddog]" type="hidden" value="no" />
#    <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />

checkbox("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" />
別名:check_box
# File actionview/lib/action_view/helpers/form_helper.rb, line 1347
def checkbox(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 1378
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 日期格式的 字串 作為「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 1442
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 日期時間格式的 字串 作為「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" />
別名如下:datetime_local_field
# File actionview/lib/action_view/helpers/form_helper.rb, line 1515
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 1569
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: @article 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 %>

  <%= textarea :commenter, :biography %>
  <%= checkbox_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 1080
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(記錄名稱, 記錄物件 = nil, 選項 = {}, &區塊)

在具體模型物件周圍建立一個範圍,就像 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 %>

在這種情況下,核取方塊欄位將由具有 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.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.permission 的類別為 Permission,則該欄位仍將被命名為 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_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 回傳 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 %>

當使用集合時,您可能想要知道陣列中每個物件的索引。基於這個目的,索引方法在 FormBuilder 物件中提供。

<%= form_with model: @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 1029
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_with 區塊中使用此方法會將封裝表單的編碼設為 multipart/form-data

選項

  • 建立標籤的標準 HTML 屬性。

  • :disabled - 如果設為 true,使用者將無法使用此輸入。

  • :multiple - 如果設為 true,*在大部分的最新瀏覽器* 中,使用者可以選擇多個檔案。

  • :include_hidden - 當 multiple: trueinclude_hidden: true 時,此欄位會以 <input type="hidden"> 欄位當作開頭,並帶有空白值,以支援提交空白的檔案集合。

  • :accept - 如果設定為一個或多個 mime-type,則當使用者選擇檔案時,系統會建議使用一個篩選條件。您仍必須設定模型驗證。

範例

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

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

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

file_field(:article, :image, accept: 'image/png,image/gif,image/jpeg')
# => <input type="file" id="article_image" name="article[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 1248
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(記錄,選項 = {},&區段)

建立一個表單,讓使用者可以建立或更新特定模型物件的屬性。

這個方法可以用幾種稍有不同的方式,這取決於你多希望依賴 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.textarea :biography %><br />
  Admin?    : <%= f.checkbox :admin %><br />
  <%= f.submit %>
<% end %>

傳遞給區塊的變數 fFormBuilder 物件,包含傳遞給 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 最右邊的引數是一個選項雜湊(hash),其為選用 -

  • :url - 要將表單提交到的 URL。這可以用和傳遞給 url_forlink_to 的值相同的方式表示。因此,例如,您可以直接使用命名路由。當模型是由字串或符號表示時(如同上面範例),若未指定 :url 選項,預設表單會傳回目前的 URL(我們會在下面說明 form_for 另一種以資源為導向的用法,其中不需要明確指定 URL)。

  • :namespace - 表單的命名空間,用於確保表單元素的 ID 屬性唯一。此命名空間屬性會在產生的 HTML ID 中加上底線前置。

  • :method - 提交表單時要使用的 HTTP 方法,通常是「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 : <%= textarea :person, :biography %>
  Admin?    : <%= checkbox_tag "person[admin]", "1", @person.company.admin? %>
  <%= f.submit %>
<% end %>

這對於 FormOptionsHelperDateHelper 中的方法也適用,這些方法是用來處理物件當作基礎,例如 FormOptionsHelper#collection_selectDateHelper#datetime_select

form_for 和模型物件

在以上的範例中,要建立或編輯的物件是由傳遞給 form_for 的符號表示,我們已經注意到也可以使用字串來表示。不過,你也可以傳遞模型物件本身給 form_for。例如,如果 @article 是你想要編輯的現有記錄,你可以使用以下方式建立表單:

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

這種寫法和大方向的幾個小例外一樣。首先,用來命名表單中輸入元素的前綴(也就是在 params hash 中表示他們的鍵)實際上取自於該物件的類別,例如 params[:article],前提是該物件的類別是 Article。不過,你可以使用 :as 選項來覆寫這個設定,例如 -

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

會產生 params[:client]

其次,當表格第一次顯示時所顯示的欄位值,是取自於傳遞給 form_for 的物件的屬性,不論該物件是不是一個實例變數。因此,例如,如果我們有一個表示現有記錄的區域變數 article

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

會產生一個欄位欄位其初始狀態反映的是 article 屬性的現有值的表單。

面向資源的樣式

在剛剛顯示的範例中,儘管沒有明確指出,我們仍然需要使用 :url 選項來指定表單要傳送往哪裡。不過,如果傳遞給 form_for 的記錄是資源,就能做進一步的簡化,亦即,這個記錄對應到一組 RESTful 路徑,例如使用 config/routes.rb 中的 resources 方法所定義的。在這種情況下,Rails 會自動從記錄本身推斷出適當的 URL。例如,

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

等同於類似以下的程式碼

<%= form_for @article, as: :article, url: article_path(@article), method: :patch, html: { class: "edit_article", id: "edit_article_45" } do |f| %>
  ...
<% end %>

對於新記錄

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

等同於類似以下的程式碼

<%= form_for @article, as: :article, url: articles_path, html: { class: "new_article", id: "new_article" } do |f| %>
  ...
<% end %>

不過,你還是可以覆寫個別的慣例,例如

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

你可以透過傳遞 url: false 來略過 action 屬性

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

你也可以設定回答格式,如下

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

對於命名空間的路徑,例如 admin_article_url

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

如果你的資源有定義關聯,例如,在路由設定正確的情況下,你想要將留言新增到文件中

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

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

設定方法

你可以透過設定選項 hash 中的

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

來強制表單使用完整的 HTTP 動詞陣列。如果動詞不是 HTML 表單原生支援的 GET 或 POST,這個表單會設定為 POST,而且會有一個稱為 _method 的隱藏輸入元件,來攜帶伺服器要詮釋的預定動詞。

低調 JavaScript

指定選項 hash 中的

remote: true

會建立一個表單,讓低調 JavaScript 驅動程式修改其行為。表單提交會和接收方所看到的正規提交相同(所有元素都在 params 中)。

範例

<%= form_for(@article, 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 選項

你可以透過傳遞資料 hash 來直接設定資料屬性,但所有其他 HTML 選項都必須包在 HTML 鍵中。範例

<%= form_for(@article, 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。

在以下範例中,Article 模型在 NoSQL 資料庫中儲存了許多 Comment,因此沒有 Comment 的主鍵。

範例

<%= form_for(@article) 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.textarea :biography %>
  <%= f.checkbox :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 436
def form_for(record, options = {}, &block)
  raise ArgumentError, "Missing block" unless block_given?

  case record
  when String, Symbol
    model       = false
    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: false, scope: nil, url: nil, format: nil, **options, &block)

根據混合的 URL、範圍或模型建立一個表單標籤。

# Using just a URL:
<%= form_with url: articles_path do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/articles" 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: :article, url: articles_path do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/articles" method="post">
  <input type="text" name="article[title]" />
</form>

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

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

表單中的參數可根據名稱巢狀在控制器中存取。因此,名為 titlearticle[title] 的輸入可分別存取為 params[:title]params[:article][:title]

為了便於比較,以上範例省略了送出按鈕,以及自動產生的隱藏欄位,這些欄位啟用 UTF-8 支援,並增加了一個用於跨網站請求偽造防護的真確性標記。

面向資源的樣式

在剛才顯示的許多範例中,傳遞給 form_with:model 是一個資源。它對應到一組 RESTful 路由,最有可能透過 config/routes.rb 中的 resources 定義。

因此,傳遞此類模型記錄時,Rails 會推論出 URL 和方法。

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

等同於類似以下的程式碼

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

對於新記錄

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

等同於類似以下的程式碼

<%= form_with scope: :article, url: articles_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[:article] 變成 params[:blog]

  • :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: @article, url: super_articles_path) %>
<%= form_with(model: @article, scope: :blog) %>
<%= form_with(model: @article, format: :json) %>
<%= form_with(model: @article, authenticity_token: false) %> # Disables the token.

對於命名空間的路徑,例如 admin_article_url

<%= form_with(model: [ :admin, @article ]) 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 %>

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

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

對於 FormOptionsHelperDateHelper 中的方法也適用,這些方法旨在將物件作為基礎,例如 FormOptionsHelper#collection_selectDateHelper#datetime_select

設定方法

你可以透過設定選項 hash 中的

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

來強制表單使用完整的 HTTP 動詞陣列。如果動詞不是 HTML 表單原生支援的 GET 或 POST,這個表單會設定為 POST,而且會有一個稱為 _method 的隱藏輸入元件,來攜帶伺服器要詮釋的預定動詞。

設定 HTML 選項

您可以在資料哈希中直接設定資料屬性,但 id 和 class 等 HTML 選項必須封裝在 HTML 鍵內

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

會產生

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

移除隱藏的模型 ID

form_with 方法會自動將模型 ID 納入表單中,作為隱藏欄位。這用於維持表單資料與其對應模型之間的關聯。有些 ORM 系統在層疊模型中不使用 ID,這種情況下,您會希望停用隱藏的 ID。

在以下範例中,Article 模型在 NoSQL 資料庫中儲存了許多 Comment,因此沒有 Comment 的主鍵。

<%= form_with(model: @article) 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.textarea :biography %>
  <%= form.checkbox :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 756
def form_with(model: false, scope: nil, url: nil, format: nil, **options, &block)
  raise ArgumentError, "Passed nil to the :model argument, expect an object or false" if model.nil?

  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 = {})

傳回一個隱藏式輸入標籤,專門用來存取指定屬性 (由 method 指定) 在指定給樣板的物件上 (由 object 指定)。可以在哈希中傳遞其他選用輸入標籤,做為 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(:article, :tag_list)
# => <input type="hidden" id="article_tag_list" name="article[tag_list]" value="#{@article.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 1215
def hidden_field(object_name, method, options = {})
  Tags::HiddenField.new(object_name, method, self, options).render
end

標籤(object_name,方法,content_or_options = nil,options = nil,&區塊)

傳回標籤標記,根據指定屬性(經由程式碼方法指定)標註一個輸入欄位,該屬性在指定的物件中(經由物件指定)。標籤文字預設為屬性名稱,除非目前 I18n 區域設定找到翻譯(經由helpers.label.<modelname>.<attribute>),或您明確地指定。標籤標記可透過雜湊與 options 傳遞其他選項。這些選項會以 HTML 元素屬性標記在 HTML 中,如所示範,唯獨 :value 選項例外,它設計為讓標籤標記鎖定 radio_button 標記(值會用在輸入標記的 ID 中)。

範例

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

您可以依模型與屬性名稱來定位化您的標籤。例如,您可以在區域設定中定義以下內容(例如,en.yml)

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

如此會產生

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

定位化也可以只根據屬性名稱的翻譯(如果您使用 ActiveRecord

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

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

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

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

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

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

label(:article, :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(:article, :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 1152
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

月欄位(object_name,方法,options = {})

傳回類型為「月」的 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 1534
def month_field(object_name, method, options = {})
  Tags::MonthField.new(object_name, method, self, options).render
end

數字欄位(object_name,方法,options = {})

傳回類型為「數字」的輸入標記。

選項

支援與 FormTagHelper#number_field_tag 相同的選項。

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

密碼欄位(object_name,方法,options = {})

傳回「密碼」類型輸入標記,根據指定屬性(經由程式碼方法指定)標註一個輸入欄位,該屬性在指定的物件中(經由物件指定)。輸入標記可透過雜湊與 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 1197
def password_field(object_name, method, options = {})
  Tags::PasswordField.new(object_name, method, self, options).render
end

電話欄位(object_name,方法,options = {})

單選按鈕(object_name,方法,標籤值,options = {})

傳回一個單選按鈕標籤,用來存取指定屬性(由 method 指定)在指定給樣板的物件中(由 object 指定)。如果 method 的目前值是 tag_value,單選按鈕會被選取。

若要強迫單選按鈕被選取,請在 options hash 中傳入 checked: true。您也可以在那邊傳入 HTML 選項。

# Let's say that @article.category returns "rails":
radio_button("article", "category", "rails")
radio_button("article", "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("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 1370
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 = {})

傳回一個種類為”範圍”的輸入標籤。

選項

支援與 FormTagHelper#range_field_tag 相同的選項。

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

rich_text_area(object_name, method, options = {})

別名: rich_textarea

rich_textarea(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_textarea :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_textarea :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>
也稱作別名: rich_text_area
# File actiontext/app/helpers/action_text/tag_helper.rb, line 87
def rich_textarea(object_name, method, options = {})
  Tags::ActionText.new(object_name, method, self, options).render
end

search_field(object_name, method, options = {})

傳回一個種類為 “搜尋” 的輸入,用來存取指定屬性(由 method 指定)在指定給樣板的物件中(由 object_name 指定)。有些瀏覽器可能會以不同的方式來設定種類為 “搜尋” 的輸入。

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 1401
def search_field(object_name, method, options = {})
  Tags::SearchField.new(object_name, method, self, options).render
end

telephone_field(object_name, method, options = {})

傳回一個種類為 “電話” 的 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 1410
def telephone_field(object_name, method, options = {})
  Tags::TelField.new(object_name, method, self, options).render
end

text_area(object_name, method, options = {})

別名:textarea

text_field(object_name, method, options = {})

傳回一個 “text” 型式的輸入標籤,客製化為存取指定屬性(由 method 識別)在配賦給範本(由 object 識別)的物件上。輸入標籤上的其他選項可以傳遞為含有 options 的雜湊。這些選項會標註為 HTML 元素屬性,如所示範例。

範例

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

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

text_field(:article, :title,  maxlength: 30, class: "title_input")
# => <input type="text" id="article_title" name="article[title]" maxlength="30" size="30" value="#{@article.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 1176
def text_field(object_name, method, options = {})
  Tags::TextField.new(object_name, method, self, options).render
end

textarea(object_name, method, options = {})

傳回一個 textarea 開啟與關閉標籤集,客製化為存取指定屬性(由 method 識別)在配賦給範本(由 object 識別)的物件上。輸入標籤上的其他選項可以傳遞為含有 options 的雜湊。

範例

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

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

textarea(: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>

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

time_field(object_name, method, options = {})

傳回一個 “time” 類型的 text_field

預設值是透過嘗試使用 “%T.%L” 對物件的值呼叫 strftime 而產生的。如果您傳遞 include_seconds: false,則會透過嘗試使用 “%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" />

預設情況下,所提供的時間會包含秒數而格式化。透過傳遞 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 1480
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 1560
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" />

預設值是透過嘗試使用 “%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 1551
def week_field(object_name, method, options = {})
  Tags::WeekField.new(object_name, method, self, options).render
end