Nubtacular
Nubtacular

Reputation: 1397

Rails 4 ActiveRecord Model: correctly using _was to separate two quantites

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

Answers (1)

Mandeep
Mandeep

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

Related Questions