2013-02-15 64 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