使用构建对象获取集合时将构建对象附加到集合

Appending build object to collection when fetching collection with build object

Rails 4.2.4 和 Ruby 2.2.3

两个模型关联如下:

class User < ActiveRecord::Base
  has_many :documents

  accepts_nested_attributes_for :documents
end

class Document < ActiveRecord::Base
  belongs_to :user
end

用户控制器有一个动作:

class UsersController < ApplicationController
   def edit
    @user = User.find(params[:id])
    @documents = @user.documents   # List document
    @document =  @user.documents.build   # Build document
  end
end

在这里,我希望 @documents 变量只包含用户文档的集合。但它也附加了 Document #<Document:0x007f2d28431550 id: nil, name: nil, created_at: nil, updated_at: nil, user_id: 2> 的新实例,这是我不想要的。

假设一个 @user 有两个关联的文档。 在 List Document 步骤之后 @documents 变量的值如下:

[#<Document:0x007f2d290b67d0
  id: 95,
  document: "doc1.pdf",
  created_at: Wed, 20 Jan 2016 04:32:16 UTC +00:00,
  updated_at: Wed, 20 Jan 2016 04:32:16 UTC +00:00,
  user_id: 2>,
#<Document:0x008f8d290e87da
  id: 96,
  document: "doc2.pdf",
  created_at: Wed, 20 Jan 2016 04:32:22 UTC +00:00,
  updated_at: Wed, 20 Jan 2016 04:32:22 UTC +00:00,
  user_id: 2>]

@documents.count = 2

但是,在 Build document 步骤之后 @documents 变量的值如下:

[#<Document:0x007f2d290b67d0
  id: 95,
  document: "doc1.pdf",
  created_at: Wed, 20 Jan 2016 04:32:16 UTC +00:00,
  updated_at: Wed, 20 Jan 2016 04:32:16 UTC +00:00,
  user_id: 2>,
#<Document:0x008f8d290e87da
  id: 96,
  document: "doc2.pdf",
  created_at: Wed, 20 Jan 2016 04:32:22 UTC +00:00,
  updated_at: Wed, 20 Jan 2016 04:32:22 UTC +00:00,
  user_id: 2>,
#<Document:0x007f2d28431550 id: nil, name: nil, created_at: nil, updated_at: nil, user_id: 2> ]

但我们还有 @documents.count = 2.

这里,count也是一样的。但是集合包含一个对象。 我如何理解 rails 的这种行为。还有我如何冻结 @documents 以仅获取文档集合。

@documents 指向 @user 的文档。您应该在 @user 而不是 @member 上构建新的 document 才能在 @documents 集合中看到新建的文档。

如下更新您的 edit 操作应该会显示 @user 的三个文档以及 @document 上新建的文档:

class MembersController < ApplicationController
   def edit
    @user = User.find(params[:id])
    @documents = @user.documents   # List document
    @document =  @documents.build   # Build document on `@user`.
  end
end

@documents = @user.documents 添加对 @user.documents 数组的引用。 @user.documents.build 就地改变该数组,因此 @documents 将始终显示新记录。

您有两种选择来解决此问题:

@document 初始化为 Document 并手动设置外键,而不是通过 @documents。这不会将新记录添加到 @user.documents

@documents = @user.documents
@document = Document.new(user: @user)

使用 #dup 复制 documents 数组,而不是引用它。

@documents = @user.documents.dup
@document = @user.documents.build