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

时间:2013-06-09 17:37:50

标签: ruby-on-rails ruby ruby-on-rails-3 activerecord ruby-on-rails-3.2

在我的Rails应用中,我有invoices及其关联的items

在我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

点击该链接会使用正确的invoiceitems数据来实例化表单。

然而,当尝试Create记录时,我收到错误:

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

有人能告诉我这里缺少什么,或者是否有更聪明的方法来复制记录包括其相关记录?

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

这是将复制主要对象及其下方的每个项目的cose。不会保存新对象,也不会保存项目。

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

快速测试证明事情:

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

答案 1 :(得分:1)

让我们从你的错误信息开始解构这一点。

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

现在,首先想到的是,人们可能会想到没有ID为4的物品。这是一个很好的理智检查,以确保这样的简单事情不是问题。在这种情况下,我们有适当的项目,所以我们可以继续前进。

起初奇怪的是,ID=之后缺少一个数字。事实证明,这暗示了问题所在。

让我们来看看一些控制台输出。我会使用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> 

我们养了猫后,让我们复制它。

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> 

我们对重复的猫有什么看法?好吧,对于初学者来说,created_atupdated_at都是nil。这通常表示对象尚未保存到数据库中。如果我们去查找Cat的{​​{1}},我们会注意到甚至没有专栏!

让我们尝试保存新对象。

ID

现在,如果我们调用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 ,它将返回此对象。

Cat.last

您的问题是,在复制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> 时,您不会将其保存到数据库中。 Invoice确认了这一点,因为它告诉我们重复的Couldn't find Item with ID=4 for Invoice with ID=没有Invoice,只有在未保存的情况下才会这样。

干杯!