0

これがスコープの問題なのかどうかはわかりませんが、test:unit 内のオブジェクトの更新に問題があります。

興味深いことに、開発モードではすべての機能が完全に動作しますが、rake test:unit に切り替えるとすぐにすべてが機能しなくなります。

関連するコードは次のとおりです。

  class Cart < ActiveRecord::Base

  def add_product(product)
    current_item = line_items.find_by_product_id(product.id)
    if current_item
      Rails::logger.debug "Incrementing quantity"
      Rails::logger.debug current_item.quantity
      current_item.quantity += 1
      Rails::logger.debug current_item.quantity
    else
      current_item = line_items.build(product_id: product.id,
                                     price: product.price)
    end
    Rails::logger.debug "Added Product"
    Rails::logger.debug current_item.quantity
    current_item
  end

および関連するテスト

  test "create new cart with one item added twice" do
    cart = Cart.new
    cart.add_product(products(:one)).save!
    assert_equal 1, cart.line_items.size
    assert_equal 36.00, cart.total_price
    Rails::logger.debug cart.line_items.to_a
    cart.add_product(products(:one)).save!
    Rails::logger.debug "Added second item"
    Rails::logger.debug cart.line_items.to_a
    Rails::logger.debug cart.total_price
    assert_equal 1, cart.line_items.size
    assert_equal 72.00, cart.total_price
  end

そして、ログ出力は次のとおりです。

Incrementing quantity
1
2
Added Product
2
   (0.1ms)  SAVEPOINT active_record_1
   (0.3ms)  UPDATE "line_items" SET "quantity" = 2, "updated_at" = '2013-01-18 15:27:06.958210' WHERE "line_items"."id" = 980190963
   (0.1ms)  RELEASE SAVEPOINT active_record_1
Added second item
[#<LineItem id: 980190963, product_id: 1, cart_id: nil, created_at: "2013-01-18 15:27:06", updated_at: "2013-01-18 15:27:06", quantity: 1, price: 36>]
36

新しい数量 (最後のログに従って変更されました)。興味深いことに、関数自体の中で、数量フィールドが 2 に更新されています。SQL データベースにも保存されます。しかし、cart.line_items を呼び出すと、更新されたフィールドさえありますが、新しい数量 (最後のログに従って変更された) は保存されません。

4

1 に答える 1

3

Rails にはデフォルトで ID マップがありません。LineItem.find(1)これは、aと別の操作を行うたびLineItem.find(1)に、データベース内の同じ行のデータから作成された 2 つの別個のオブジェクトが取得されることを意味しますが、それらの間に接続はありません。それらの1つが変更されてデータベースに保存された場合、他のオブジェクトはそれを認識せず、古いデータを保持しています。

あなたの例line_items.find_by_product_id(product.id)では、毎回新しいオブジェクトを検索して返すことを行っています。LineItem以前に にロードされたオブジェクトへの接続はありませんcart.line_items

古いオブジェクトのデータを更新するには、2 つのオプションがあります。それらの 1 つは.reload、データベースから 1 つのオブジェクトのすべてのデータを再ロードするメソッドです。trueもう 1 つのオプションは、関連付けにa を渡すことcart.line_itemsです。cart.line_items(true) のような呼び出しは、データベースへの新しいクエリを強制して、すべての項目を取得します。

このバグがテスト中にのみ発生する理由は単純です。開発モードでは、通常、挿入と読み取りは 2 つの別々の要求で行われるため、すべてのオブジェクトが毎回データベースから新たにロードされます。

于 2013-01-18T15:48:57.420 に答える