3

我是一個新手。我已閱讀API文檔。但仍不明白form_for的工作方式。form_for如何在Ruby on Rails中工作

首先,從Ruby on Rails的教程,後續按鈕形式:

<%= form_for(current_user.relationships.build(followed_id: @user.id)) do |f| %> 
    <div><%= f.hidden_field :followed_id %></div> 
    <%= f.submit "Follow", class: "btn btn-large btn-primary" %> 
<% end %> 

我明白current_user.relationships.build(followed_id: @user.id)意味着一個新紀錄。但爲什麼我們不能只提交併觸發控制器來保存沒有hidden_​​field的記錄?爲什麼我們仍然需要將followed_id發佈到控制器?

其次,在hidden_​​field中,:followed_id的含義是什麼?我認爲這是一個符號,即它只等於「followed_id」而不是id的變量。如果這只是輸入字段的名稱,那麼它的價值是什麼?

第三,form_for怎麼知道提交應該發送到哪裏? form_for將發佈到哪個控制器和操作?

四,params如何配合form_for?在此按鈕的情況下,params[:relationship][:followed_id]將在控制器中返回@user.id。它如何知道第一個哈希屬性是:relationship?我們既沒有提到form_for :relationship也沒有提到form_for @relationship

我知道這些問題可以非常愚蠢,但我真的被卡住了。任何幫助將不勝感激。

回答

3

我沒有做那個教程,所以介意我,如果我不直接回答你的問題。

看看rails guide about form helpers,它會詳細解釋您的問題,可能會以比我更清楚的方式解釋。

form_for(path/to/your/controller/action)是通過POST或GET請求的url路徑創建HTML表單元素的幫助器方法。幫助者根據您在控制器操作中要求做的事情知道它應該是新記錄還是更新記錄。

例如 在你的控制器

def new 
    @my_instance_variable = Myobject.new 
end 

在你看來new.html.erb

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

在你的情況下,邏輯直接寫在助手,你也可以直接寫

<%= form_for Myobject.new %> 

兩者都會導致以下html

<form action="/myobjects/new" method="post"> 
# in this case rails knows its a `POST` request because the route new action 
# is by default a POST request. You can check these routes and their request 
# by using `rake routes` in terminal. 

然後hidden_field是另一個幫手包含一個值,你的情況,將作爲參數,然後保存爲給定對象創建或更新操作傳遞的@user.id。它不會在隱藏字段標記中添加值的原因是因爲您已經有了一個模型關聯,它知道用戶的id,因爲表單的鏈接使用了用戶標識的構建方法。

最後一部分,你需要了解的form_for鏈接邏輯

current_user.relationships 
# implies the association of the current_user has many relationships 
current_user.relationships.build 
# .build is a method to populate a new object that can be save as a new record 
# means you will create a new relationship record by populating the user_id 
# column with the current_user.id and the followed_id with the target @user.id 
+0

非常感謝。這是一個很好的答案。但我仍然感到困惑。首先,如果「form_for」之後的輸入是路徑。然後,form_for Myobject.new和Myobject.build應該引導我們採取行動「新」和「建設」?但相反,它指導我採取行動「創造」。無論如何,只要我明白它如何將我重定向到正確的控制器,這不是一個大問題。 'form_for current_user.relationships.build(followed_id:@ user.id)'中的' –

+0

','form_for'只需要第一部分'current_user.relationships.build'。這意味着最後一部分'(followed_id:@ user.id)'不是必需的,對嗎?還是它扮演一些角色來幫助hidden_​​field的價值?我想我的第一個和第二個問題仍然沒有得到答案。也許我應該花更多時間閱讀你首先建議的Rails指南。謝謝 –

+1

你需要告訴軌道你想用適當的信息建立什麼,所以是的,你需要最後一部分。在有模型關聯時使用構建方法。您可以查看[api](http://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-build)。如果您不添加@ user.id,那麼followed_id將以零結果。 –

1

讀的書Rails的4路,我現在明白的form_for更好了。

11.9.1.5顯示現有值。 如果您正在編輯Person的現有實例,則該對象的屬性值將填充到 表單中。

這樣

,當我們建立使用current_user.relationships.build(followed_id: @user.id)的關係,這種關係實例將被創建和增益屬性followed_id。因此,我們不是「創造」一種關係,而是通過形式來編輯關係。

然後,Rails將知道您正在編輯並將現有屬性「followed_id」加載到該字段。因此,我們不需要像使用f.hidden_field :followed_id, value: @user.id那樣爲該字段賦值。

而我們必須使用字段來傳遞followed_id到params的原因是因爲HTTP服務器是無狀態的,它不記得您正在與哪個用戶建立關係。

一個寫form_for current_user.relationships.build(followed_id: @user.id)而不是標準form_for @relationship的優點是我們不需要寫「如果條件」中的控制器是這樣的:

unless current_user.nil? 
    if current_user.following?(@user) 
    @relationship=current_user.relationships.find_by(followed_id: @user.id) 
    else 
    @relationship=current_user.relationships.new 
    end 
end 

PARAMS將被髮送到其所屬的控制器實例的模型。 「post」方法會去動作創建,「刪除」會去銷燬,「補丁」會去更新,等等。

參數將是一個哈希與另一個哈希裏面像{instace_name:{field_1:value1, field_2:value2}}或全參數如下

Parameters: {"utf8"=>"✓", 
    "authenticity_token"=>"afl+6u3J/2meoHtve69q+tD9gPc3/QUsHCqPh85Z4WU=", 
    "person"=>{"first_name"=>"William", "last_name"=>"Smith"}, 
    "commit"=>"Create"}