Rails中的Helper方法

tag類的Helper

form_tag

<%= form_tag("/search", method: "get") do %>
  <%= label_tag(:q, "Search for:") %>
  <%= text_field_tag(:q) %>
  <%= submit_tag("Search") %>
<% end %>
#生成HTML如下
<form accept-charset="UTF-8" action="/search" method="get">
  <label for="q">Search for:</label>
  <input id="q" name="q" type="text" />
  <input name="commit" type="submit" value="Search" />
</form>
#生成的表單的每個input屬性都有ID屬性,其值和name屬性的值是一樣的

form_tag({controller: "people", action: "search"}, method: "get", class: "nifty_form")
#第二個hash參數為html屬性
<form accept-charset="UTF-8" action="/people/search" method="get" class="nifty_form">

復選框

<%= check_box_tag(:pet_dog, "12") %>

<input id="pet_dog" name="pet_dog" type="checkbox" value="12" />

單選框

<%= radio_button_tag(:age, "child") %>

<input id="age_child" name="age" type="radio" value="child" />

處理模型對象

#如果控制器定義了@person實例變量,有屬性name ="Henry"
<%= text_field(:person, :name) %>
#生成如下
<input id="person_name" name="person[name]" type="text" value="Hery" />
#params獲取的值為
{'person' => {'name' => 'Henry'}}
#可以使用params[:person][:name]獲取提交的值
#如果@person實例是數據庫表nurse_aid_person,那么產生的代碼如下
<input id="person_name" name="nurse_aid_person[name]" type="text" value="Hery" />

Hash

#Hash可以隨意嵌套
<input id="person_address_city" name="person[address][city]" type="text" 
  value="New York"/>
#獲取的params為
{'person'=>{'address'=>{'city'=>'New York'}}}
params[:person][:address][:city]

數組

#一般情況下Rails回忽略重復的參數名
<input name="person[phone_number][]" type="text"/>
<input name="person[phone_number][]" type="text"/>
<input name="person[phone_number][]" type="text"/>
#params[:person][:phone_number]是一個數組

Hash和數組結合

<input name="addresses[][line1]" type="text"/>
<input name="addresses[][line2]" type="text"/>
<input name="addresses[][city]" type="text"/>
#params[:addresses]值是一個由Hash組成的數組

form_for表單綁定對象

<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :body, size: "60x12" %>
  <%= f.submit "Create" %>
<% end %>

<form action="/articles/create" method="post" class="nifty_form">
  <input id="article_title" name="article[title]" type="text" />
  <textarea id="article_body" name="article[body]" cols="60" rows="12"></textarea>
  <input name="commit" type="submit" value="Create">
</form>

fields_for方法

#同一表單中編輯多個模型對象時經常使用fields_for方法。
#eg、有個Person模型,和ContactDetail模型關聯
<%= form_for @person, url: {action: "create"} do |person_form| %>
  <%= person_form.text_field :name %>
  <%= fields_for @person.contact_detail do |contact_details_form| %>
    <%= contact_details_form.text_field :phone_number %>
  <% end %>
<% end %>

#生成的HTML代碼如下
<form action="/people/create" class="new_person" id="new_person" method="post">
  <input id="person_name" name="person[name]" type="text" />
  <input id="contact_detail_phone_number" name="contact_detail[phone_number]" type="text" />
</form>

命名空間

#admin命名空間
form_for [:admin, @article] #admin_article_path(@article)

form_for[:admin, :management, @article]

文件處理

上傳文件

#params[:picture]
<%= form_tag({action: :upload}, multipart: true) do %>
  <%= file_field_tag 'picture' %>
<% end %>

#params[:person][:picture]
<%= form_for @person do |f| %>
  <%= f.file_field :picture %>
<% end %>

處理上傳

#可以使用CarrierWave和Paperclip等第三方庫
def upload
  upload_io = params[:person][:picture]
  File.open(Rails.root.join('public', uploads, upload_io.original_filename), 'wb') do |file|
    file.write(uploaded_io.read)
  end
end

使用Ajax上傳文件

<%= form_for @person, builder: LabellingFormBuilder do |f| %>
  <%= f.text_field :first_name %>
<% end %>
#定制表單構造器
class LabellingFormBuilder < ActionView::Helpers::FormBuilder
  def text_field(attribute, options=[])
    label(attribute) + super
  end
end

外部資源

#如果不需要access_token的話,可以關閉,如果需要,設置authenticity_token的值
<%= form_tag 'http://www.baidu.com', authenticity_token:  false do %>
...
<% end %>

復雜的表單

class Person < ActiveRecord::Base
  has_many :addresses
  accepts_nested_attributes_for :addresses, allow_destroy: true,
    reject_if: lambda{|attributes| attributes['kind'].blank?}
#自動為Person對象創建address_attributes=方法,用于創建、更新、刪除地址操作
end

class Address < ActiveRecord::Base
  belongs_to :person
end

嵌套表單

<%= form_for @person do |f| %>
  Addresses:
  <ul>
    <%= fields_for @person.addresses do |addresses_form| %>
      <li>
        <%= addresses_form.label :kind %>
        <%= addresses_form.text_field :kind %>

        <%= addresses_form.label :street %>
        <%= addresses_form.text_field :street %>
      </li>
    <% end %>
  </ul>
<% end %>

如果關聯支持嵌套屬性,fields_for方法會為關聯中的每個元素執行一遍代碼塊,如果沒有Address,就不執行,一般做法是在控制器中構建一個或者多個空的子屬性。這樣至少會有一組字段顯示出來。

def new
  @person = Person.new
  2.times { @person.addresses.build }
end

如果用戶提交了兩個地址,提交的參數如下

{
  'person' => {
    'name' => 'John Doe',
    'addresses_attributes' => {
      '0' => {
        'kind' => 'Home',
        'street' => '221b Baker Street'
      },
      '1' => {
        'kind' => 'Office',
        'street' => '31 Spooner Street'
      }
    }
  }
}

控制器端

def create
  @person = Person.new(person_params)
end

private
  def person_params
    params.require(:person).permit(:name, addresses_attributes:[:id, :kind, :street])
  end

刪除屬性

#表單
<%= form_for @person do |f| %>
  Addresses:
  <ul>
    <%= f.fields_for :addresses do |addresses_form| %>
      <li>
  #如果屬性組成的hash中包含_destroy鍵,且值為1或true,就會刪除對象
        <%= addresses_form.check_box :_destroy%>
        <%= addresses_form.label :kind %>
        <%= addresses_form.text_field :kind %>
        ...
      </li>
    <% end %>
  </ul>
<% end %>

修改控制器中的參數白名單

def person_params
  params.require(:person).
    permit(:name, addresses_attributes: [:id, :kind, :street, :_destroy])
end
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,836評論 18 139
  • HTML表單 在HTML中,表單是 ... 之間元素的集合,它們允許訪問者輸入文本、選擇選項、操作對象等等,然后將...
    蘭山小亭閱讀 3,436評論 2 14
  • 22年12月更新:個人網站關停,如果仍舊對舊教程有興趣參考 Github 的markdown內容[https://...
    tangyefei閱讀 35,207評論 22 257
  • 爬蟲就是從網絡上發現你想要數據的工具。 大互聯網公司 我原來在互聯網公司,覺得獲取數據so easy。只要你需要,...
    jacksu在簡書閱讀 2,207評論 2 0
  • 趕著夏天的尾巴,我們來說說筆記本散熱問題。筆記本電腦相比傳統臺式機的優勢和特點就是輕薄,但因此也造成筆記本機體內部...
    玩機社閱讀 479評論 1 1