2013-02-15 55 views
0

我有一個汽車模型和一個品牌模型(每個has_and_belongs_to_many)。我正在努力爲汽車創造一個新品牌。汽車模型接受品牌的嵌套屬性。如何獲取params散列中的數據?

當我嘗試

@car = Car.find(params[:car_id]) 
@brand = @car.brands.build(params[:brand]) 

我得到一個質量分配錯誤:

Can't mass-assign protected attributes: brands 

品牌控制器:

class BrandsController < ApplicationController 
def create 
    debugger 
    @car = Car.find(params[:car_id]) 
    @brand= @car.brands.build(params[:brand]) 
    if @brand.save 
    redirect_to @car 
    else 
    #do something 
    end 
end 
end 

調用調試器

pp params 

表演:

"brand"=>{"brands"=>{"name"=>"BMW"}}, 
"commit"=>"Create Brand", 
"action"=>"create", 
"controller"=>"brands", 
"car_id"=>"4"} 

的看法是這樣的:

<%= form_for([@car, @car.brands.build]) do |f| %> 
    <div class="field"> 
     <%= f.fields_for :brands do |a| %> 
      <%= a.text_field :name, placeholder: "New Brand" %> 
     <% end %> 
    </div> 
    <p><%= f.submit %></p> 
<% end %> 

我希望應用程序是安全的,所以我想在此設置品牌單獨的屬性,而不是通過整個「品牌」散列(順便說一句不起作用)。我如何獲得品牌名稱?喜歡的東西

params[:brands].name? 

編輯:

我可以得到的品牌名稱與 'PARAMS [:品牌] [:品牌] [:名字]'。現在事實證明,品牌表沒有car_id,因爲它使用連接表連接到汽車。

回答

1
<%= form_for @car do |f| %> 
    <div class="field"> 
    <%= f.fields_for :brands do |a| %> 
     <%= a.text_field :name, placeholder: "New Brand" %> 
    <% end %> 
    </div> 
<p><%= f.submit %></p> 
<% end %> 

在你的模型:

class Car < ActiveRecord::Base 
    has_many :brands 
    accepts_nested_attributes_for :brands 
    attr_accessible :brand_attributes 
end 
+0

更改後我仍然得到'Can not mass-assign protected attributes:brands'error – 2013-02-15 15:56:04

+2

Car需要有一個attr_accessible:brand_attributes,因爲該表單助手應該輸出params [:car] [:brand_attributes]成爲提交的一個或多個品牌的散列或陣列。此外,控制器不應該使用brands.build,因爲那是ANAF所做的。該控制器應該只是正常的創建/ update_attrbitues – Cluster 2013-02-15 16:10:16

1

雖然有模型接受屬性另一個是在某些情況下,一個有用的工具,它往往變得繁雜,而不是隻在模型違反了單一責任主體級別,但也在控制器和視圖層。如果您的設計需要更改,最終會使重構變得更加困難。

秉承REST理念,而不是通過汽車創造品牌,使用BrandsController來處理品牌的生命週期。

至於您的安全需求,手動設置模型的屬性不會提供更多的安全性,然後傳遞整個參數散列,假設您正確使用attr_accessible。給它一個可接受參數的白名單將告訴AR接口,其他所有內容都應該被拒絕。

class Brand < ActiveRecord::Base 
    attr_accessible :name 
end 

所以,如果一個品牌屬於一輛車,有人試圖通過黑客一個car_id到形式,它會從哈希拒絕car_id,甚至可能提高根據您的設置異常改變的關係。

config.active_record.mass_assignment_sanitizer = :strict 

這將導致ActiveModel::MassAssignmentSecurity::Error而不是隻輸出到日誌中的警告。

+0

我有一個品牌控制器。我已經更新了問題以顯示它。 – 2013-02-15 17:00:26

+0

如果你有這個問題,那麼爲什麼還要用嵌套的表單呢?看起來你已經擁有了一個嵌套資源,這就是確保創建的品牌和Car之間的鏈接所需要的全部東西,我會放棄表單/模型嵌套並使用form_for(@brand)並完成它。 – Cluster 2013-02-15 21:12:09