3

私の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

invoiceリンクをクリックすると、正しいitemsデータでフォームがインスタンス化されます。

ただし、Create記録しようとするとエラーが発生します。

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

ここで何が欠けているのか、または関連するレコードを含むレコードを複製するよりスマートな方法があるかどうか、誰か教えてもらえますか?

助けてくれてありがとう。

4

2 に答える 2

2

メインオブジェクトとその下の各アイテムを複製するコードは次のとおりです。新しいオブジェクトは保存されず、アイテムも (まだ) 保存されません。

  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
于 2013-06-09T18:20:29.950 に答える
1

エラーメッセージから始めて、これを少し分解しましょう。

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

さて、最初は、ID 4 のアイテムはないと考えたくなるかもしれません。これは、このような単純なことが問題ではないことを確認するための適切な健全性チェックです。この場合、適切なアイテムがあるので、次に進みます。

最初に奇妙に感じたのは、次の数字がないことでしたID=。これは、何が問題なのかを示唆していることがわかりました。

コンソール出力を見てみましょう。私は単に素晴らしいという理由だけで、Cat オブジェクトを使用します。

最初に行うことは、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_at両方updated_atnil. これは通常、オブジェクトがデータベースに保存されていないことを示しています。を探しに行くと、その列さえないことに気付きますCat!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は noがあることを示しているためID、これを確認します。これは、保存されていない場合にのみ当てはまります。

乾杯!

于 2013-06-09T18:13:56.377 に答える