【问题标题】:Can't mass-assign protected attributes: document无法批量分配受保护的属性:文档
【发布时间】:2014-07-18 13:05:23
【问题描述】:

我有两个模型 Employee 和 Documents 如下:

Employee.rb

class Employee < ActiveRecord::Base
  has_one :document #,dependent: :destroy
  attr_accessible :age, :dob, :empNo, :first_name, :gender, :last_name, :middle_name, :document_attributes
  accepts_nested_attributes_for :document
  validates :first_name, presence: true , length: { maximum: 50 }
  validates :empNo, presence: true, uniqueness:{ case_sensitive: false }
  validates_length_of :empNo, :minimum => 5, :maximum => 5

  #before save { |user| user.email = email.downcase }
end

文档.rb

class Document < ActiveRecord::Base
  belongs_to :employee,foreign_key: "empno"
  attr_accessible :idate, :iedate, :insuranceno, :iqamano, :iqedate, :iqidate, :passportno, :pedate, :pidate, :vedate, :vidate, :visano
end

控制器文件是employees_controller.rb(我只展示了new,create,show funcs)

  def show
    @employee = Employee.find(params[:id])
    @document=Document.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @employee }
    end
  end

  # GET /employees/new
  # GET /employees/new.json
  def new
    @employee = Employee.new
    @document= Document.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render :json=>{:employee=> @employee,:document=>@document}, status: :created, :location=>{:employee=> @employee,:document=>@document} }
    end
  end

  # POST /employees
  # POST /employees.json
  def create
    @employee = Employee.create!(params[:employee])
    @document = Document.create!(params[:document])
    respond_to do |format|
      if @employee.save and @document.save
        format.html { redirect_to @employee, notice: 'Employee was successfully created.' }
        format.json { render :json=>{:employee=> @employee,:document=>@document}, status: :created, location: @employee }
      else
        format.html { render action: "new" }
        format.json { render json: @employee.errors, status: :unprocessable_entity }
      end
    end
  end

当我创建一个新员工时,我收到以下错误

 ActiveModel::MassAssignmentSecurity::Error in EmployeesController#create
 Can't mass-assign protected attributes: document

requsts 参数很好,如下所示

{"utf8"=>"✓",
 "authenticity_token"=>"vXSnbdi+wlAhR5p8xXvTWhi85+AVZgOZufClx73gc8Q=",
 "employee"=>{"empNo"=>"11111",
 "first_name"=>"Thaha",
 "middle_name"=>"Muhammed",
 "last_name"=>"Hashim",
 "age"=>"25",
 "gender"=>"M",
 "dob(1i)"=>"2014",
 "dob(2i)"=>"7",
 "dob(3i)"=>"18",
 "document"=>{"passportno"=>"bycucde63"}},
 "commit"=>"Create Employee"}

我已经浏览了几乎所有关于 stackoverflow 的帖子来处理这个问题,而且大部分问题都与

  1. 不使用attr_accessible
  2. 不使用accepts_nested_attributes_for
  3. 不使用:document_attributes

如果我将config.active_record.whitelist_attributes 的值更改为 false,那么错误就会消失(开发人员日志中存在相同的警告)并且 两个模型都已创建,但只有员工模型的属性是当文档模型的属性为 nil 时,填充传递的值。

编辑 #1 如果我尝试将 :document 添加到 attr_accessible ,则会收到以下错误

ActiveRecord::AssociationTypeMismatch in EmployeesController#create 

我在这里做错了什么?

【问题讨论】:

    标签: ruby-on-rails-3 nested-attributes mass-assignment


    【解决方案1】:

    了解批量分配

    Mass Assignment 是 Rails 赋予使用参数​​散列构造对象的行为的名称。它是“批量赋值”,因为您通过单个赋值运算符为属性分配多个值。

    下面的sn-ps对Post模型的name和topic属性进行批量赋值:

    Post.new(:name => "John", :topic => "Something")
    
    Post.create(:name => "John", :topic => "Something")
    
    Post.update_attributes(:name => "John", :topic => "Something")
    

    为了使其工作,您的模型必须允许对您传入的哈希中的每个属性进行批量分配。

    有两种情况会失败:

    您有一个不包括 :nameattr_accessible 声明

    您有一个attr_protected,其中确实包括:name

    最近成为默认设置,必须通过 attr_accessible 手动将属性列入白名单,以便批量分配成功。在此之前,默认情况下属性是可分配的,除非它们被显式列入 attr_protected 的黑名单或任何其他属性被列入 attr_accessible 的白名单。

    【讨论】:

      【解决方案2】:

      我想,这里最简单的方法是将 :document 添加到 attr_accessible。 如果此处未列出某个属性,ActiveRecord 将不允许您“批量分配”它们。

      关于我的评论,你最终会得到这样的结果:

      ...   
      "dob(3i)"=>"18",
      "document"=><#Document ...>}, # {"passportno"=>"bycucde63"} is just a Hash, not a Document, that's why it raises "ActiveRecord::AssociationTypeMismatch"
      "commit"=>"Create Employee"}
      

      在代码中,如:

      def create
        @document = Document.create!(params[:document])
        @employee = Employee.create!(params[:employee].merge(:document => @document))
      

      【讨论】:

      • 查看有问题的编辑。它不起作用。添加:document_attributes 应该是解决这里的许多帖子的工作,即使这对我不起作用
      • 啊,我想,我明白了。试试这个:您必须从“文档”字段转换/创建一个文档。由于那里只有值,AR 不会自动从“document”=>{“passportno”=>“bycucde63”} 创建文档。这只是一个哈希。因此,将 :document 添加到 attr_accessible 然后首先创建一个 Document(从 :document 参数中),然后批量分配给 Employee
      • 我会试试这个。但请查看ryandaigle.com/articles/2009/2/1/…。为什么它不再工作了?
      猜你喜欢
      • 2011-09-04
      • 1970-01-01
      • 2012-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多