2013-01-18 5 views
0

이것이 범위 문제인지 여부는 확실하지 않지만 테스트 : 단위로 개체를 업데이트하는 데 문제가 있습니다.레일 - 업데이트 된 개체가 저장되지 않습니까?

재미있는 점은 모든 기능이 개발 모드에서 완벽하게 작동한다는 것입니다. 그러나 레이크 테스트로 전환하자마자, 모든 기능이 중단됩니다. 로그 출력

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 

EW 량 (마지막에 따른 변경된

여기서 중요한 코드의 로그). 흥미롭게도 함수 자체 내에서 수량 필드는 2로 업데이트됩니다. 심지어 SQL 데이터베이스에 저장됩니다. 그러나 cart.line_items를 호출하면 업데이트 된 필드도 있지만 마지막 수량에 따라 변경된 새 수량은 저장되지 않습니다.

답변

3

기본적으로 레일스에는 ID 맵이 없습니다. 즉, LineItem.find(1)과 다른 LineItem.find(1)을 수행 할 때마다 데이터베이스의 동일한 데이터 행에서 생성되지만 두 개의 객체 간에는 아무런 연결이없는 두 개의 개별 객체가 생성됩니다. 그 중 하나가 변경되고 데이터베이스에 저장되면 다른 개체는 그것에 대해 알지 못하고 이전 데이터를 유지합니다.

예에서 line_items.find_by_product_id(product.id)은 검색을 수행 할 때마다 새 객체를 반환합니다. 이전에 cart.line_items에로드 된 LineItem 개체에 연결되어 있지 않습니다.

부실 개체에 대한 데이터를 업데이트하는 두 가지 옵션이 있습니다. 그 중 하나는 .reload 메소드로 데이터베이스에서 하나의 오브젝트에 대한 모든 데이터를 다시로드합니다. 다른 옵션은 truecart.line_items 연결로 전달하는 것입니다. cart.line_items (true)와 같은 호출은 데이터베이스에 대한 모든 쿼리를 강제 실행하여 모든 광고 항목을 가져옵니다.

테스트 중에이 버그가 발생하는 이유는 간단합니다. 개발 모드에서 삽입 및 읽기는 일반적으로 두 개의 개별 요청으로 이루어 지므로 모든 개체가 매번 데이터베이스에서 새로로드됩니다.

+0

설명해 주셔서 감사합니다. 그러나 새로 고침이 작동하지 않습니다. 'cart.line_items.reload'는 cart.bin_items (true)와 같이 카트를 비 웁니다 (이제는 0 개의 객체가 있음). 제대로 다시로드하는 방법에 대한 제안? 또한 .find()를 사용하고 새 객체를 생성하는 대신 동일한 객체를 선택하는 방법은 무엇입니까? – Xiv

+0

업데이트 : 그냥 할 필요가 cart.list_items.each {| item | item.reload} 개체를 하나씩 다시로드합니다. – Xiv

관련 문제