2013-01-18 54 views
0

我不确定这是否是范围问题或其他问题,但我在更新测试中的对象时遇到问题:单元。Rails - 更新的对象没有保存?

有趣的是,所有的功能在开发模式下完美地工作,但只要我切换到耙测试:单元,这一切休息。

下面是相关代码:

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量(已根据上次更改日志)。有趣的是,在函数本身中,数量字段正在更新为两个。它甚至保存到SQL数据库。但是,当我调用cart.line_items时,它甚至有更新的字段,但它不保存新的数量(根据最后一个日志已经更改)。

回答

3

Rails不具有默认的标识映射。这意味着,只要你做一个LineItem.find(1)和另一LineItem.find(1)你会得到从同一行中的数据库中的数据的创建,但没有它们之间的任何连接两个不同的对象。如果其中一个被更改并保存到数据库中,另一个对象不会知道它并仍然有旧数据。

在你的榜样,你正在做的line_items.find_by_product_id(product.id)这将做一个查找和每次都返回一个新的对象。与先前加载到cart.line_items的任何LineItem对象没有关系。

有两种选择,更新陈旧的对象的数据。其中之一是.reload方法,该方法将从数据库中重新加载一个对象的所有数据。另一种选择是将true传递给cart.line_items关联。类似于cart.line_items(true)的调用将强制对数据库的新查询获取所有行项目。

,此错误只打你的测试过程中,原因很简单:在发展模式,插入和阅读,通常在两个单独的请求完成,因此所有的对象都是新鲜从数据库每次加载。

+0

感谢您的解释。但是,重新加载不适合我。 'cart.line_items.reload'清空购物车,(它现在有0个对象),如同'cart.lines_items(true)'。有关如何正确重新载入的任何建议?另外,如何选择相同的对象,而不是使用.find()并生成一个新对象? – Xiv

+0

更新:只需要做一个cart.list_items.each {| item | item.reload} m逐个重新加载对象。 – Xiv