2011-08-06 75 views
3

所以在我的應用程序中,我有一個人模型has_many說明。我現在需要在每個人的展示頁面上添加一個表單,以便爲該人員添加新的說明。到目前爲止,我有以下形式。但是它不會將人員的ID傳遞給描述創建操作。Form_For新相關型號

<%= form_for @person.descriptions.new do |f| %> 

    <fieldset class="input"> 
     <%= f.label :name %> 
     <%= f.text_field :name %> 
    </fieldset> 

    <fieldset class="input"> 
     <%= f.label :description %> 
     <%= f.text_area :description %> 
    </fieldset> 

    <fieldset class="button"> 
     <%= f.submit "Post" %> 
    </fieldset> 

<% end %> 

PARAMS傳遞

{"utf8"=>"✓", 
"authenticity_token"=>"OQY8Xcfm6wtWHXp9GjFfM4ICX79smPwyvfVcaDn+C2s=", 
"description"=>{"name"=>"Test", 
"description"=>"This is a test"}, 
"commit"=>"Post"} 

回答

6

通過構建它的人對象,而不是形式

所以在表演動作創建展示行動的人控制的描述對象,你將不得不

#You probably have something like this already 
    @person = Person.find(params[:id]) 
    #Now do this 
    @description = @person.descriptions.build 

然後改變你的form_for使用@description

這是一個不太理想的解決方案,因爲你會發現這個帖子回到描述控制器,但你可以在form_for

另外,依靠ID來查找控制器操作中的記錄是錯誤的。有人可以輕鬆地更改瀏覽器中的代碼,以便在person對象上使用不同的ID。你應該仔細考慮這一點。很多時候你會發現一個人只能編輯他們自己的描述,因此在處理這種場景時,基於當前登錄用戶的current_user對象通常用於顯示和編輯操作。

更新

忘了提,當窗體回控制器您已按上述同樣的方式在保存之前建立在對人的描述。因此,您需要找到不再依賴ID的人使用當前登錄的用戶。 希望幫助

++更新2 ++

而且上面我覺得你真的需要的form_for @person使用,然後使用fields_for:描述和accepts_nested_attributes_for添加:描述你的人的模型,所以你最終會有這樣的事情。

<%= form_for @person do |f| %> 
    <%= f.fields_for :description do |desc_builder| 
    <fieldset class="input"> 
     <%= desc_builder.label :name %> 
     <%= desc_builder.text_field :name %> 
    </fieldset> 

    <fieldset class="input"> 
     <%= desc_builder.label :description %> 
     <%= desc_builder.text_area :description %> 
    </fieldset> 
    <%end%> 
    <fieldset class="button"> 
     <%= f.submit "Post" %> 
    </fieldset> 

<% end %> 

在您的Person模型添加以下

class Person < ActiveRecord::Base 
#... Add this line 
    accepts_nested_attributes_for :descriptions, :reject_if => proc { |attributes| attributes['name'].blank? && attributes['description'].blank? } 
#... --- 
在你的節目行動的人控制

然後,只需建立上面的描述

#You probably have something like this already 
    @person = Person.find(params[:id]) 
    #Now do this 
    @description = @person.descriptions.build # add an if @person.descriptions.empty? here if you only ever want one description per person. 

上面的代碼將用於安排指示您的表單將被重新發回到會自動創建描述記錄的個人控制器更新操作。根本不需要更改任何其他控制器代碼。

這是因爲的form_for @person將安排URL去更新行動,它已經是一個現有的人

的fields_for將爲描述字段安排嵌套在PARAMS人領域內散列更新操作獲取。

最後,accept_nested_attributes_for將安排描述記錄根據需要自動創建或更新。 :reject_if => proc安排它,以便如果名稱和描述都爲空白,則不會創建新記錄。你顯然可以包含更多的領域,改變條件或者沒有全部。無論您的要求如何。

希望這會讓你感動。 如果你覺得有需要,你可以在這裏找到更多關於accepting_nested_attributes的信息 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

+0

同意,這是一個更好的方法。 – skorks

+0

只是爲了澄清,這不是爲了當前用戶來描述他們的自我。這是給任何訪問者描述這個人的。所以我不確定這是否會影響您發佈的解決方案 –

+0

不,它不會影響答案。你試過了嗎?但是你確定你想讓喬改變弗雷德的描述嗎? – jamesc

0

,最簡單的方式,以確保你得到@person對象的ID在你的PARAMS哈希,是簡單地將其添加爲您表單上的隱藏字段例如:

hidden_field(:person, :id) 

此外,您可能應該在Persons控制器中創建模板描述,而不是在您的視圖中創建新描述。

+0

你應該永遠不要依賴id的視圖。他們很容易被惡意用戶更改 – jamesc

+0

@jamesw爲什麼這很重要?驗證是否可以創建新的「描述」並將其分配給「人員」將由服務器端由控制器處理......或者我是否錯過了某些內容? – AJP

+0

隱藏字段以及可見字段都很容易受到用戶在瀏覽器中的操作的影響。您不能指望按照最初提供的方式將相同的用戶ID發送回控制器。只要想一想,惡意用戶可能會造成什麼破壞,或者甚至只是有人在玩遊戲,如果他們在發佈表單之前更改瀏覽器中的ID – jamesc