I've been creating a cart feature in rails and I have the following models:
Cart:
class Cart < ActiveRecord::Base
has_many :items
end
Item:
class Item < ActiveRecord::Base
belongs_to :cart
belongs_to :product
end
An item also has a quantity attribute.
Now, I have an instance method on cart that given an item will either a) save the item to the database and associate it with the cart or b) if the item with the product_id already exists, simply update the quantity.
The code for this is below:
def add_item(item)
if(item.valid?)
current_item = self.items.find_by(product_id: item.product.id)
if(current_item)
current_item.update(quantity: current_item.quantity += item.quantity.to_i)
else
self.items << item
end
self.save
end
end
And this works fine.
However, I wanted to test this in the console so i opened up the console in sandbox mode and ran the following commands:
cart = Cart.new #create a cart
cart.add_item(Item.new(product: Product.find(1), quantity: 5)) #Add 5 x Product 1
cart.items #lists items, I can see 5 x Product 1 at this point.
cart.add_item(Item.new(product: Product.find(1), quantity: 3)) #Add 3 x Product 1
cart.items #lists items, still shows 5 x Product 1, not 8x
cart.items.reload #reload collectionproxy
cart.items #lists items, now with 8x Product 1
Here i create a cart, add a purchase of 5 x Product 1 and i can see this in the cart.items. If then add another purchase of 3 x Product 1, the cart.items still lists the purchase as 5 x Product 1 until i manually reload the collection proxy.
I can add more products and these will show up, it is just when updating an existing one, it does not update the collection.
I have tests around this method too which pass.
before(:each) do
@cart = create(:cart)
@product = create(:product)
@item = build(:item, product: @product, quantity: 2)
end
context "when the product already exists in the cart" do
before(:each) {@cart.add_item(@item)}
it "does not add another item to the database" do
expect{@cart.add_item(@item)}.not_to change{Item.count}
end
it "does not add another item to the cart" do
expect{@cart.add_item(@item)}.not_to change{@cart.items.count}
end
it "updates the quantity of the existing item" do
@cart.add_item(@item)
expect(@cart.items.first.quantity).to eq 4
end
end
context "when a valid item is given" do
it "adds the item to the database" do
expect{@cart.add_item(@item)}.to change{CartItem.count}.by(1)
end
it "adds the item to the cart" do
expect{@cart.add_item(@item)}.to change{@cart.items.size}.by(1)
end
end
What i want to know is, why do i have to reload the CollectionProxy when I use this method in the console?