如果我尝试执行以下代码:
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错误。
答案 0 :(得分:63)
一些事情:
批量分配通常意味着将属性传递给调用,该调用将对象创建为属性哈希的一部分。也就是说,您将哈希中的一堆属性传递给创建新对象的调用。例如:
@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感到困惑并认为您想要使用单表继承(STI),请检查此问题的答案以查看如何解决它:http://guides.rubyonrails.org/
答案 1 :(得分:7)
您是否正在使用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
......你继续学习很好。在编写第一个生产应用程序时,请记住保持这种效果:)
答案 2 :(得分:5)
请尝试:打开config/application.rb
找到config.active_record.whitelist_attributes = true
将true更改为false
那你就没事了。
PS:记得重新启动rails控制台。
答案 3 :(得分:2)
你应该得到另一个错误,如下所示:列'type'保留用于在继承的情况下存储类。因为列'类型'不应在活动记录数据库中使用。
答案 4 :(得分:1)
我不使用whitelist_attributes
,因为我想要允许批量分配的用例是我的内部逻辑,通常不直接在Controller中用于CRUD操作。我建议在这些情况下使用强对数。但是,如果要为特定模型启用质量分配,则执行
class Foo < ActiveRecord::Base
# disables mass-assigment
attr_protected
end
这基本上将attr_protected
设置为空数组([])
答案 5 :(得分:0)
Here是关于Rails中的质量分配是什么以及为什么保护到位的一些信息。当你真的想要分配一个受保护的属性时,它很容易出现,但它需要额外的几行。
hassle = rota.hassles.build(:sender => user1, :receiver => user2)
hassle.type = 'sms'
hassle.save