【问题标题】:ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributesActiveModel::MassAssignmentSecurity::Error: 无法批量分配受保护的属性
【发布时间】:2012-05-13 20:25:37
【问题描述】:

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

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 错误。

【问题讨论】:

  • STI 的 rails 默认使用“type”列。最好的解决方案是将类型列重命名为其他名称。不推荐的解决方法是添加模型文件 self.inheritance_column = :some_other_column_that_might_not_exists
  • 是的 - 有关解决使用“类型”列的 STI 问题的信息,请参阅此内容:stackoverflow.com/questions/7134559/…(尽管更好的选择可能是更改列的名称)。跨度>
  • 是的 - 我遇到了这个问题。更改了列名。谢谢!

标签: ruby-on-rails activemodel


【解决方案1】:

几件事:

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

@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/

【讨论】:

  • 如果您尝试同时创建一个有多个孩子的父级怎么办?例如; Post.create(comments)
【解决方案2】:

您是否在学习 Rails 3.2 的同时学习 3.1 教程,例如 Pragmatic Programmer 的“Agile Web Development with Rails”第 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

...您可以继续学习。请记住在编写您的第一个生产应用程序时保持这一点:)

【讨论】:

  • “您是否在使用 Rails 3.2 的同时遵循 3.1 教程,例如 Pragmatic Programmer 的“Agile Web Development with Rails”第 4 版?”这正是我正在做的。 +1 解决我的问题。
  • 这解决了我的问题,我注释掉了这一行:config.active_record.mass_assignment_sanitizer = :strict
【解决方案3】:
  1. 请尝试:打开config/application.rb

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

  3. 真为假

那你就没事了。

PS:记得重启rails控制台。

【讨论】:

    【解决方案4】:

    你应该得到另一个错误,像这样:列'type'被保留用于在继承的情况下存储类。因为不应在活动记录数据库中使用列“类型”。

    【讨论】:

      【解决方案5】:

      我不使用whitelist_attributes,因为我确实希望允许批量分配的用例是用于我的内部逻辑,通常不直接在控制器中进行 CRUD 操作。我建议在这些情况下使用强参数。但是,当您想为特定模型启用批量分配时,您可以这样做

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

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

      【讨论】:

        【解决方案6】:

        你需要在你的模型类中有attr_accesible

        class <model_name> < ActiveRecord::Base
            attr_accessible :<fields_name>
        end
        

        【讨论】:

          【解决方案7】:

          Here 是关于 Rails 中的质量分配是什么以及为什么要进行保护的一些信息。当您确实想要分配受保护的属性时,这很容易解决,但它需要几行额外的代码。

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

          【讨论】:

          • hassle.type = 'sms' 很可能会引发 Sms 类不存在异常
          • 也许吧。我的工作假设是 OP 知道他在 STI 上做什么。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-04
          • 1970-01-01
          • 1970-01-01
          • 2012-09-14
          • 1970-01-01
          相关资源
          最近更新 更多