如何在Ruby on Rails中复制记录及其相关记录?

时间:2022-09-22 18:09:27

In my Rails app I have invoices and their associated items.

在我的Rails应用程序中,我有发票和相关的项目。

In my InvoicesController I added this method:

在我的InvoicesController中我添加了这个方法:

def duplicate
  invoice = Invoice.find(params[:id])
  @invoice = invoice.dup
  invoice.items.each do |item|
    @invoice.items << item
  end      
  render :new    
end

def create
  @invoice = current_user.invoices.build(params[:invoice])    
  if @invoice.save
    flash[:success] = "Invoice created."
    redirect_to edit_invoice_path(@invoice)
  else
    render :new
  end
end

Clicking the link instantiates a form with the correct invoice and items data.

单击链接实例化具有正确发票和项目数据的表单。

However, when trying to Create the record I get an error:

但是,当尝试创建记录时,我得到一个错误:

Couldn't find Item with ID=4 for Invoice with ID=

Can anybody tell me what I am missing here or if there's a smarter way to duplicate a record including its associated records?

有人能告诉我我在这里缺少什么吗?或者如果有更聪明的方法来复制一个记录,包括它的相关记录?

Thanks for any help.

感谢任何帮助。

2 个解决方案

#1


2  

Here's cose that will duplicate the main object, and each of the items underneath it. The new object will not be saved, nor will the items (yet).

这里的cose将复制主对象,以及它下面的每个项目。新对象不会被保存,项目也不会被保存。

  def duplicate
    dup.tap do |new_invoice|
      items.each do |item|
        new_invoice.items.push item.dup
      end
    end
  end

And a quick test to prove the things:

一个快速的测试来证明

require 'test_helper'

class InvoiceTest < ActiveSupport::TestCase

  def original_invoice
    Invoice.create(number: 5).tap do |invoice|
      invoice.items.create(name: "a", price: "5")
      invoice.items.create(name: "b", price: "50")
    end
  end
  test "duplication" do
    new_invoice = original_invoice.duplicate
    new_invoice.save
    assert_equal 2, new_invoice.items.count
  end
end

#2


1  

Let's deconstruct this a little bit, starting with your error message.

让我们从错误消息开始,稍微解构一下这个问题。

Couldn't find Item with ID=4 for Invoice with ID=

找不到ID=4的项目,找不到ID=的发票

Now, at first thought, one might be tempted to consider that there is no Item with ID 4. It's a good sanity check to make sure that simple things like this aren't the issue. In this case, we have the appropriate item, so we can move on.

现在,在最初的想法中,人们可能会认为ID 4没有项。这是一个很好的健全检查,以确保像这样的简单事情不是问题。在这种情况下,我们有合适的项目,所以我们可以继续前进。

What struck me as odd at first was the lack of a number following ID=. It turns out that this hints as to what the problem is.

最初让我感到奇怪的是ID=后面缺少一个数字。事实证明,这暗示了问题是什么。

Let's have a look at some console output. I will be using Cat objects, simply because they are awesome.

让我们看一下控制台输出。我将会使用猫的对象,仅仅是因为它们太棒了。

The first thing we want to do is to get a Cat:

我们要做的第一件事就是养一只猫:

Cat.first
=> Cat Load (0.2ms)  SELECT "cats".* FROM "cats" LIMIT 1
=> #<Cat id: 2, age: 6, birthdate: "2013-06-08", color: "brown", name: "Aaron", gender: "m", created_at: "2013-06-08 21:44:22", updated_at: "2013-06-08 21:44:22", user_id: 1> 

After we have the cat, let's duplicate it.

等我们有了猫,让我们把它复制一份。

Cat.first.dup
Cat Load (0.3ms)  SELECT "cats".* FROM "cats" LIMIT 1
=> #<Cat age: 6, birthdate: "2013-06-08", color: "brown", name: "Aaron", gender: "m", created_at: nil, updated_at: nil, user_id: 1> 

What do we notice about the duplicated cat? Well, for starters, both created_at and updated_at are nil. This is usually a sign that the object hasn't be saved to the database. If we go to look for the Cat's ID, we notice that there isn't even a column for that!

关于复制的猫我们注意到了什么?首先,created_at和updated_at都为nil。这通常表示对象没有保存到数据库中。如果我们去寻找猫的ID,我们会注意到甚至没有一个列来记录它!

Let's try saving the new object.

让我们尝试保存新对象。

Cat.first.dup.save
Cat Load (0.3ms)  SELECT "cats".* FROM "cats" ORDER BY "cats"."id" DESC LIMIT 1
(0.1ms)  begin transaction
SQL (0.7ms)  INSERT INTO "cats" ("age", "birthdate", "color", "created_at", "gender", "name", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?)  [["age", 6], ["birthdate", Sat, 08 Jun 2013], ["color", "brown"], ["created_at", Sun, 09 Jun 2013 18:10:47 UTC +00:00], ["gender", "m"], ["name", "Aaron"], ["updated_at", Sun, 09 Jun 2013 18:10:47 UTC +00:00], ["user_id", 1]]
(0.7ms)  commit transaction
=> true 

Now, if we call Cat.last, it will return this object.

现在,如果我们叫猫的话。最后,它将返回这个对象。

Cat.last
Cat Load (0.3ms)  SELECT "cats".* FROM "cats" ORDER BY "cats"."id" DESC LIMIT 1
=> #<Cat id: 11, age: 6, birthdate: "2013-06-08", color: "brown", name: "Aaron", gender: "m", created_at: "2013-06-09 18:10:47", updated_at: "2013-06-09 18:10:47", user_id: 1> 

Your problem is that, while you are duplicating the Invoice, you aren't saving it to the database. Couldn't find Item with ID=4 for Invoice with ID= confirms this as it tells us the duplicated Invoice has no ID, which would only be the case if it had not been saved.

您的问题是,当您复制发票时,并没有将其保存到数据库中。ID=的发票找不到ID=4的项目,这是ID=的发票确认,告诉我们重复的发票没有ID,如果没有保存,就会是这样。

Cheers!

干杯!

#1


2  

Here's cose that will duplicate the main object, and each of the items underneath it. The new object will not be saved, nor will the items (yet).

这里的cose将复制主对象,以及它下面的每个项目。新对象不会被保存,项目也不会被保存。

  def duplicate
    dup.tap do |new_invoice|
      items.each do |item|
        new_invoice.items.push item.dup
      end
    end
  end

And a quick test to prove the things:

一个快速的测试来证明

require 'test_helper'

class InvoiceTest < ActiveSupport::TestCase

  def original_invoice
    Invoice.create(number: 5).tap do |invoice|
      invoice.items.create(name: "a", price: "5")
      invoice.items.create(name: "b", price: "50")
    end
  end
  test "duplication" do
    new_invoice = original_invoice.duplicate
    new_invoice.save
    assert_equal 2, new_invoice.items.count
  end
end

#2


1  

Let's deconstruct this a little bit, starting with your error message.

让我们从错误消息开始,稍微解构一下这个问题。

Couldn't find Item with ID=4 for Invoice with ID=

找不到ID=4的项目,找不到ID=的发票

Now, at first thought, one might be tempted to consider that there is no Item with ID 4. It's a good sanity check to make sure that simple things like this aren't the issue. In this case, we have the appropriate item, so we can move on.

现在,在最初的想法中,人们可能会认为ID 4没有项。这是一个很好的健全检查,以确保像这样的简单事情不是问题。在这种情况下,我们有合适的项目,所以我们可以继续前进。

What struck me as odd at first was the lack of a number following ID=. It turns out that this hints as to what the problem is.

最初让我感到奇怪的是ID=后面缺少一个数字。事实证明,这暗示了问题是什么。

Let's have a look at some console output. I will be using Cat objects, simply because they are awesome.

让我们看一下控制台输出。我将会使用猫的对象,仅仅是因为它们太棒了。

The first thing we want to do is to get a Cat:

我们要做的第一件事就是养一只猫:

Cat.first
=> Cat Load (0.2ms)  SELECT "cats".* FROM "cats" LIMIT 1
=> #<Cat id: 2, age: 6, birthdate: "2013-06-08", color: "brown", name: "Aaron", gender: "m", created_at: "2013-06-08 21:44:22", updated_at: "2013-06-08 21:44:22", user_id: 1> 

After we have the cat, let's duplicate it.

等我们有了猫,让我们把它复制一份。

Cat.first.dup
Cat Load (0.3ms)  SELECT "cats".* FROM "cats" LIMIT 1
=> #<Cat age: 6, birthdate: "2013-06-08", color: "brown", name: "Aaron", gender: "m", created_at: nil, updated_at: nil, user_id: 1> 

What do we notice about the duplicated cat? Well, for starters, both created_at and updated_at are nil. This is usually a sign that the object hasn't be saved to the database. If we go to look for the Cat's ID, we notice that there isn't even a column for that!

关于复制的猫我们注意到了什么?首先,created_at和updated_at都为nil。这通常表示对象没有保存到数据库中。如果我们去寻找猫的ID,我们会注意到甚至没有一个列来记录它!

Let's try saving the new object.

让我们尝试保存新对象。

Cat.first.dup.save
Cat Load (0.3ms)  SELECT "cats".* FROM "cats" ORDER BY "cats"."id" DESC LIMIT 1
(0.1ms)  begin transaction
SQL (0.7ms)  INSERT INTO "cats" ("age", "birthdate", "color", "created_at", "gender", "name", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?)  [["age", 6], ["birthdate", Sat, 08 Jun 2013], ["color", "brown"], ["created_at", Sun, 09 Jun 2013 18:10:47 UTC +00:00], ["gender", "m"], ["name", "Aaron"], ["updated_at", Sun, 09 Jun 2013 18:10:47 UTC +00:00], ["user_id", 1]]
(0.7ms)  commit transaction
=> true 

Now, if we call Cat.last, it will return this object.

现在,如果我们叫猫的话。最后,它将返回这个对象。

Cat.last
Cat Load (0.3ms)  SELECT "cats".* FROM "cats" ORDER BY "cats"."id" DESC LIMIT 1
=> #<Cat id: 11, age: 6, birthdate: "2013-06-08", color: "brown", name: "Aaron", gender: "m", created_at: "2013-06-09 18:10:47", updated_at: "2013-06-09 18:10:47", user_id: 1> 

Your problem is that, while you are duplicating the Invoice, you aren't saving it to the database. Couldn't find Item with ID=4 for Invoice with ID= confirms this as it tells us the duplicated Invoice has no ID, which would only be the case if it had not been saved.

您的问题是,当您复制发票时,并没有将其保存到数据库中。ID=的发票找不到ID=4的项目,这是ID=的发票确认,告诉我们重复的发票没有ID,如果没有保存,就会是这样。

Cheers!

干杯!