Rails: updating the quantity in the shopping cart

Ruby is new here. I am navigating through Agile Web Development with Rails. In chapter 11, you are asked to add a “reduce quantity” button to items in your shopping cart. I went ahead and tried to implement an increase link.

The problem is that it does nothing when I click the links.

line_items_controller.rb

def decrease
  @cart = current_cart
  @line_item = @cart.decrease(params[:id])

  respond_to do |format|
    if @line_item.save
      format.html { redirect_to store_path, notice: 'Item was successfully updated.' }
      format.js { @current_item = @line_item }
      format.json { head :ok }
    else
      format.html { render action: "edit" }
      format.json { render json: @line_item.errors, status: :unprocessable_entity}
    end
  end
end

def increase
  @cart = current_cart
  @line_item = @cart.increase(params[:id])

  respond_to do |format|
    if @line_item.save
      format.html { redirect_to store_path, notice: 'Item was successfully updated.' }
      format.js   { @current_item = @line_item }
      format.json { head :ok }
    else
      format.html { render action: "edit" }
      format.json { render json: @line_item.errors, status: :unprocessable_entity }
    end
  end
end

cart.rb

def decrease(line_item_id)
  current_item = line_items.find(line_item_id)
  if current_item.quantity > 1
    current_item.quantity -= 1
  else
    current_item.destroy
  end
  current_item
end

def increase(line_item_id)
  current_item = line_items.find(line_item_id)
  current_item.quantity += 1
  current_item
end

routes.rb

resources :line_items do
  put 'decrease', on: :member
  put 'increase', on: :member
end

_line_item.html.erb

<% if line_item == @current_item %>
<tr id="current_item">
<% else %>
<tr>
<% end %>
  <td><%= line_item.quantity %> &times;</td> 
  <td><%= line_item.product.title %></td>
  <td class="item_price"><%= number_to_currency(line_item.total_price) %></td>
  <td><%= link_to "-", decrease_line_item_path(line_item), method: :put, remote: true %></td>
  <td><%= link_to "+", increase_line_item_path(line_item), method: :put, remote: true %></td>
  <td><%= button_to 'Remove Item', line_item, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>

/line_items/increase.js.erb

$('#cart').html("<%= escape_javascript(render(@cart)) %>");
$('#current_item').css({'background-color':'#88ff88'}).animate({'background-color':'#114411'}, 1000);

/line_items/decrease.js.erb

$('#cart').html("<%= escape_javascript(render(@cart)) %>");
$('#current_item').css({'background-color':'#88ff88'}).animate({'background-color':'#114411'}), 1000);
if ($('#cart tr').length==1) {
  // Hide the cart
  $('#cart').hide('blind', 1000);
}

Let me know if I forgot something important. Thanks in advance!

---- ---- EDIT

I changed the code to what Rich wrote, and this is what appears in the console when I click the "+" link.

Started GET "/line_items/25/qty" for ::1 at 2016-01-30 23:49:11 -0600

ActionController::RoutingError (No route matches [GET] "/line_items/25/qty"):

, , qty, , . , JS, , , ?

---- 2 ----

POST , , :

Started POST "/line_items/25/qty" for ::1 at 2016-01-31 09:49:04 -0600
Processing by LineItemsController#qty as JS
  Parameters: {"id"=>"25"}
Completed 500 Internal Server Error in 38ms (ActiveRecord: 0.0ms)

NameError (undefined local variable or method `current_cart' for #<LineItemsController:0x007fbfb11ea730>):
  app/controllers/line_items_controller.rb:70:in `qty'

, , current_cart increase decrease, qty.

+5
2

, :

#config/routes.rb
resources :line_items do
   match :qty, action: :qty, via: [:post, :delete], on: :member #-> url.com/line_items/qty
end

#app/models/line_item.rb
class LineItem < ActiveRecord::Base
   after_update :check_qty, if: "qty_changed?"

   private

   def check_qty
     self.destroy if self.qty.zero?
   end
end 

#app/controllers/line_items_controller.rb
class LineItemsController < ApplicationController
   def qty
      @cart = current_cart
      @item = @cart.line_items.find params[:id]

      if request.post? #-> increment
         method = "increment"
      elsif request.delete? #-> decrement
         method = "decrement"
      end

      @item.send(method, :qty, params[:qty])

      respond_to do |format|
          if @item.save
             format.html { redirect_to store_path, notice: 'Item was successfully updated.' }
             format.js   { @current_item = @line_item }
             format.json { head :ok }
          else
             format.html { render action: "edit" }
             format.json { render json: @line_item.errors, status: :unprocessable_entity}
         end
     end
   end
end

( qty) . , 1 qty:

 <%= button_to "+", line_items_qty_path(@line_item), params: { qty: 5 } %>

 <%= link_to "-", line_items_qty_path(line_item), method: :post, remote: true %>
 <%= link_to "+", line_items_qty_path(line_item), method: :delete, remote: true %>

, .

- , , " ". , " "... , , - .

, , , . ( ); JS:

#app/views/line_items/qty.js.erb
alert("test");

, .

, . , line_items ( , Rails ).

, , , , , .


, ( , db):

enter image description here

, , . .


, , , GET ; POST DELETE . - :

 <%= link_to "-", line_items_qty_path(line_item), method: :post, remote: true %>

, () - , method POST DELETE


2

current_cart, , .

" " Railscast -

#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
   before_filter :current_cart
   helper_method :current_cart

   private

   def current_cart
     @current_cart = session[:cart_id] ? Cart.find(session[:cart_id]) : Cart.create
     session[:cart_id] = @current_cart.id if @current_cart.new_record?
   end
end
+2

, - ? - / , Ajax - - ( remote: true). @Richard Peck, . , , get put ( , get post, Rails , )

  resources :line_items do
    get 'decrease', on: :member
    get 'increase', on: :member
  end

, StackExchange, increase/decrease , :

line_items_controller.rb

  before_action :set_cart, only: [:create, :decrease, :increase]

, , ( , ).

line_items_controller.rb:

  def decrease
    product = Product.find(params[:product_id])
    @line_item = @cart.remove_product(product)

    respond_to do |format|
      if @line_item.save
        format.html { redirect_to cart_path, notice: 'Line item was successfully updated.' }
        format.js
        format.json { render :show, status: :ok, location: @line_item }
      else
        format.html { render :edit }
        format.json { render json: @line_item.errors, status: :unprocessable_entity }
      end
    end
  end

  def increase
    product = Product.find(params[:product_id])
    @line_item = @cart.add_product(product)

    respond_to do |format|
      if @line_item.save
        format.html { redirect_to :back, notice: 'Line item was successfully updated.' }
        format.js
        format.json { render :show, status: :ok, location: @line_item }
      else
        format.html { render :edit }
        format.json { render json: @line_item.errors, status: :unprocessable_entity }
      end
    end
  end

cart.rb

  def add_product(product)
    current_item = line_items.find_by(product_id: product.id)
    if current_item
      current_item.quantity += 1
    else
      current_item = line_items.build(product_id: product.id)
    end
    current_item
  end

  def remove_product(product)
    current_item = line_items.find_by(product_id: product.id)
    if current_item.quantity > 1
      current_item.quantity -= 1
    elsif current_item.quantity = 1
      current_item.destroy
    end
    current_item
  end

:

<td><%= link_to "-", decrease_line_item_path(product_id: line_item.product), class:"btn btn-danger" %></td>
<td><%= link_to "+", increase_line_item_path(product_id: line_item.product), class:"btn btn-success" %></td>

, ? , , - , Ajax ? :

https://stackoverflow.com/questions/40551425/rails-ajax-jquery-cant-make-to-render-changes-without-page-refresh

+2

Source: https://habr.com/ru/post/1626669/


All Articles