0

I'm writing Shop using Sinatra. I implemented adding to Basket, but I can't make deleting from Basket work.

My class App:

    get "/basket" do #working
      products_in_basket = FetchBasket.new.call
      erb :"basket/show", locals: { basket: products_in_basket }
    end

    post "/basket" do #working
      AddToBasket.new(params).call
      redirect "/"
    end


  delete "basket/:id" do # doesn't work
     DeleteBasket.new(params).call
     redirect "/"
end

My DeleteBasket:

module Shop
    class DeleteBasket
    attr_reader :product_id, :id

    def initialize(params)
      @id =  params.fetch("id").to_i
      @product_id = params.fetch("product_id").to_i

    end
    def call
      basket = FetchBaskets(id) # finds Basket instance with given id

      return unless basket

      reduce_basket_quantity(basket)



    def reduce_basket_quantity(basket)
      if basket.quantity >= 1
        basket.quantity -= 1
        #warehouse = FetchWarehouseProduct.new.call(product_id)
        #warehouse.quantity += quantity
      else
        BASKET.delete(basket)
      end
       end
    end
  end
end

Delete in views:

    <td>   <form action="/basket/<%=b.id%>" method="post">
    <input type="hidden" name="_method" value="delete">
    <input type="hidden" name="product_id" value=<%= b.product_id %>>
  <input type="hidden" name="id" value=<%= b.id %>>
    <button type="submit">Delete</button>
  </form>

It doesn't redirect to home page as it should, and it doesn't change basket quantity by 1. It simply does nothing.

Jes
  • 323
  • 2
  • 18

2 Answers2

0

I think to most obvious reason is you are not calling the delete http method, but post instead:

<form action="/basket/<%=b.id%>" method="post">

Normally you would fix this by using

<form action="/basket/<%=b.id%>" method="delete">

but this is not yet supported according to this answer.

I think your best bet is to define your delete route as a post

  post "delete-basket/:id" do
     DeleteBasket.new(params).call
     redirect "/"
  end

and then write

<form action="/delete-basket/<%=b.id%>" method="post">
Community
  • 1
  • 1
Martin Konecny
  • 57,827
  • 19
  • 139
  • 159
0

Remember how we said that in an HTML form we can specify the HTTP verb that is supposed to be used for making the request like so:

<form action="/monstas" method="post">
  ...
</form>

This makes the form POST to /monstas, instead of the default GET.

Now, it’s probably fair to say that every sane person in the world would expect that it is also possible to make that a PUT, or DELETE request. Like so:

<form action="/monstas" method="delete">
  ...
</form>

Except that … it’s not. Today’s browsers still do not allow sending HTTP requests using any other verb than GET and POST.

The reasons for why that still is the case in 2015 are either fascinating or sad, depending how you look at it [1] But for now we’ll just need to accept that, and work around it.

Sinatra (as well as Rails, and other frameworks) therefore support “faking” requests to look as if they were PUT or DELETE requests on the application side, even though in reality they’re all POST requests.

This works by adding a hidden form input tag to the form, like so:

<input name="_method" type="hidden" value="delete" />

Source: https://webapps-for-beginners.rubymonstas.org/resources/fake_methods.html

Rztprog
  • 13
  • 6