无法批量分配受保护的属性

我的features文件看到了这个:

 Given there are the following users: | email | password | admin | | admin@ticketee.com | password | true | 

并且我的user模型没有将admin属性声明为attr_accessible以防止批量分配。 因此,我已经对user_steps.rb文件进行了更改以解决此问题。

 Given /^there are the following users:$/ do |table| table.hashes.each do |attributes| unconfirmed = attributes.delete("unconfirmed") == "true" @user = User.create!(attributes) @user.update_attribute("admin", attributes["admin"] == "true") @user.confirm! unless unconfirmed end end 

现在这应该按照这本书 – Rails3的实际工作。 我也检查了他们在线仓库的代码。 用黄瓜运行它会产生以下错误:

 Can't mass-assign protected attributes: admin (ActiveModel::MassAssignmentSecurity::Error) ./features/step_definitions/user_steps.rb:4:in `block (2 levels) in ' ./features/step_definitions/user_steps.rb:2:in `each' ./features/step_definitions/user_steps.rb:2:in `/^there are the following users:$/' features/creating_projects.feature:7:in `Given there are the following users:' 

任何帮助将不胜感激。 我真的不知道这里有什么问题。

非常感谢!

在用户模型中添加:

 attr_accessible :admin 

更新:

admin属性可以是批量分配的,任何黑客都可以通过使用参数发送它来轻松设置它。

我通过更改步骤定义来实现此目的:

  Given /^there are the following users:$/ do |table| table.hashes.each do |attributes| unconfirmed = attributes.delete("unconfirmed") == "true" admin = attributes.delete("admin") == "true" @user = User.create!(attributes) @user.admin = admin @user.confirm! unless unconfirmed end end 

为什么不使用@user.admin = attributes["admin"] == "true"

您将需要从属性哈希中删除管理员值 – 所以完整的代码将是

 admin = attributes.delete("admin") == "true" ... @user = User.new(attributes) @user.admin = admin @user.save! 

我改变了User.create! 到User.new + @ user.save,因为您正在设置属性但不保存模型。 如果@ user.confirm! 保存模型你不会看到任何错误,但依靠其他方法的副作用并不是一个好习惯。 最好是明确的。

假设这是基于“Rails 3 in Action”,示例代码实际上具有相同的问题。 从日志中:

 WARNING: Can't mass-assign protected attributes: admin (0.1ms) SELECT 1 FROM "users" WHERE "users"."email" = 'sfcarroll2@gmail.com' LIMIT 1 User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."confirmation_token" = 'f9zDB57RDXsziBdGpmnW' LIMIT 1 

但是,在config / environments / development.rb文件中,未设置mass_assignment_sanitizer 。 默认情况下,新的rails 3.2项目将设置此项。 如果注释掉,代码将执行。 默认设置为:

 config.active_record.mass_assignment_sanitizer = :strict 

然后,示例代码使用私有方法set_admin设置属性。 这是一个很好的编码实践吗? 我不确定但它有效。

顺便说一下,这是一本很棒的书。

我认为最简单的方法是:

 Given /^there are the following users:$/ do |table| table.hashes.each do |attributes| unconfirmed = attributes.delete("unconfirmed") == "true" # this will delete the attribute unconfirmed from first # scenario on the signing_in.feature but it's also make a variable unconfirmed true (2 in one action) admin = attributes.delete("admin") == "true" @user = User.create!(attributes) @user.update_attribute("admin", "true") if admin # with the user and password, it will create the user as admin. @user.confirm! unless unconfirmed # this is work for the second scenario check rails 3 in action page 152. end end 

这样您就可以从属性中删除admin属性,以便创建新用户; 没有质量分配属性错误。 但是对于“测试”目的,如果admin为true,我们将admin变量分配给user.admin属性。 这里的事情是你不会让用户模型上的管理员可以保护你的网站免受攻击,但我们这样做是为了通过我们的测试。 在您的网站上,您必须实现一种安全的方式来在用户创建后更新用户。