Reputation: 1397
I'm building an ecommerce app and I'm a bit stuck. I don't want to create a new line_item if the product is the same. Here is my cart.rb model
class Cart < ActiveRecord::Base
has_many :line_items, dependent: :destroy
has_many :products
def add_product(product_id, size, color, quantity)
current_item = line_items.find_by_product_id(product_id)
if current_item
current_item.quantity = 20
current_item.quantity += current_item.quantity_was
else
current_item = line_items.build(product_id: product_id, size: size, color: color, quantity: quantity)
end
current_item
end
def total_price
line_items.to_a.sum { |item| item.total_price }
end
end
line_items controller (where a new line gets created in the cart):
class LineItemsController < InheritedResources::Base
def create
@cart = current_cart
product = Product.find(params[:product_id])
size = params[:product][:size]
color = params[:product][:color]
quantity = params[:product][:quantity]
@line_item = @cart.add_product(product.id, size, color, quantity)
respond_to do |format|
if @line_item.save
format.html { redirect_to products_customer_cart_url,
notice: 'You have added an item to your cart.' }
#format.js { @current_item = @line_item }
format.json { render json: @line_item,
status: :created, location: @line_item }
else
format.html { render action: "new" }
format.json { render json: @line_item.errors,
status: :unprocessable_entity }
end
end
end
def destroy
@cart = current_cart
@line_item = LineItem.find(params[:id])
@line_item.destroy
respond_to do |format|
format.js {}
end
end
end
products show.html.erb below (where you select the item):
<%= form_for(@product, url: line_items_path(product_id: @product.id), html: {method: "update"}) do |f| %>
<%= image_tag("https://s3.amazonaws.com/blah/mens_black_front.jpg" %>
<table>
<tr><td>Size:</td> <%= f.select(:size, @male_shirt_sizes.map { |value| value }, :include_blank => 'Select Size') %></td><tr>
<tr><td>Color:</td> <%= f.select(:color, @shirt_colors.map { |value| value }, :include_blank => 'Select Color') %></td><tr>
<tr><td>Quantity:</td> <%= f.select(:quantity, @quantity.map { |value| value }, :include_blank => 'Select Quantity') %></td><tr>
</table>
<%= f.submit "Add to Cart", :class => "btn btn-mega btn-primary", :id => "add-to-cart-btn" %>
<% end %>
-Now, as you can see I just put the number 20 in there for now to test it out.
-So say I go to add an item initially, quantity of 4.
-That line_item will now have a quantity of 4.
-Now when I go to add that same product with a different quantity (whether it be 1, 2, 3, 4 or 5), it'll add the int 20 (as it should, because 20 is hardcoded in there).
But how would I dynamically add the 'new' quantity, to add the initial quantity to the latest quantity?
Upvotes: 0
Views: 139
Reputation: 9173
I have answered a similar question here. Will post a summary
But how would I dynamically add the 'new' quantity, to add the initial quantity to the latest quantity?
The problem is your submit button takes it to the create action of your item and hence creating a new item inside your cart
Fix:
You need to make a new action with post route request(to find that item) and then update its quantity inside that action.
If you look at your button or rather i should say form for creating a new item then it's the path or url part in your form which takes it to your method inside your controller. If you change its url then it will take it to your custom method.
For that to work, you need js
to dynamically change the url or your form after a user has clicked on your Add to Cart button. Something like:
$(document).on("click","your_button_class",function(){
$(this).closest("your_form_class").attr("action","path_of_new_method");
});
You will also have to supply your items id by this form by adding a hidden field or something and then find that item inside controller method with that id to update its quantity.
Note: You need to call this js after your form is submitted and a new item is already created else it can trouble you.
Upvotes: 1