ActiveModel :: MassAssignmentSecurity ::错误:无法批量分配受保护的属性

如果我尝试执行以下代码:

hassle = rota.hassles.create(:sender => user1, :receiver => user2, :type => "sms") 

我发现以下错误:

 Failure/Error: hassle = rota.hassles.create(:sender => user1, :receiver => user2, :type => "sms") ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: type 

我不确定这意味着什么。 我已经使:type是必须的,所以如果我删除它,我得到一个SQL错误。

几件事:

质量分配通常意味着将属性传递给调用,该调用将对象创建为属性哈希的一部分。 也就是说,您将哈希中的一堆属性传递给创建新对象的调用。 例如:

 @user = User.create({:name => "My name", :user_type => "nice_user"}) 

但是,Rails包含一些基本的安全规则,这意味着默认情况下不能以这种方式分配所有属性 。 您必须事先指定哪些可以。 你这样做:

 class User < ActiveRecord::Base attr_accessible :name, :user_type end 

如果未指定属性是attr_accessible ,并且您将其传入以创建对象,则会收到您发布的错误。

这里有更多细节:

http://api.rubyonrails.org/v3.2.9/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html

另一种方法是在第一次创建记录时设置一些属性,然后在其后设置其他属性 - 如下所示:

 # In this example `user_type` is not attr_accessible so it needs to be set specifically @user = User.create({:name => "My name"}) @user.user_type = "nice_user" @user.save 

此外,如果您在使用列名称type遇到问题,因为rails感到困惑并且认为您想要使用单表inheritance(STI),请检查此问题的答案以了解如何解决它: http:/ /guides.rubyonrails.org/

您是否正在使用Rails 3.2,同时遵循3.1教程,例如Pragmatic Programmer的“使用Rails进行敏捷Web开发”第4版? 然后查看http://guides.rubyonrails.org/3_2_release_notes.html 。

您的问题是从Rails 3.1到3.2默认情况下,Active Record模型的质量分配保护检查设置为“严格”。 注释掉这些文件中的相应行:

 config/environments/development.rb config/environments/test.rb 

……你继续学习很好。 在编写第一个生产应用程序时,请记住保持这种效果:)

  1. 请尝试:打开config/application.rb

  2. 找到config.active_record.whitelist_attributes = true的行

  3. 将true更改为false

那你就没事了。

PS:记得重新启动rails控制台。

你应该得到另一个错误,如下所示:列’type’保留用于存储inheritance的类。 因为列’类型’不应在活动记录数据库中使用。

我不使用whitelist_attributes因为我想要允许批量分配的用例是我的内部逻辑,通常不直接在Controller中用于CRUD操作。 我建议在这些情况下使用强对数。 但是当你想为特定模型启用质量分配时

 class Foo < ActiveRecord::Base # disables mass-assigment attr_protected end 

这基本上将attr_protected设置为空数组([])

这里有一些关于Rails中的质量分配以及为什么保护到位的信息。 当你真的想要分配一个受保护的属性时,它很容易解决,但它需要额外的几行。

 hassle = rota.hassles.build(:sender => user1, :receiver => user2) hassle.type = 'sms' hassle.save