seque90
seque90

Reputation: 181

How to send a DELETE Request to the browser in RoR 4

I'm working on the Ruby on Rails Tutorial by Michael Hartl (I'm a noob).

In the application I want to delete a micropost, but whenever I try to execute it in the browser, it tells me that there is Routing Error. "No route matches [GET] "/microposts/3"

This is the code that I have in _micropost.html.erb

<tr>
    <td class="micropost">
        <span class="content"><%= micropost.content %></span>
        <span class="timestamp">
            Posted <%= time_ago_in_words(micropost.created_at) %> ago
        </span>
    </td>
    <% if current_user?(micropost.user) %>
    <td>
        <%= link_to "delete", micropost, :method => :delete,
                                         :confirm => "You sure?",
                                         :title => micropost.content %>
    </td>
    <% end %>
</tr>
</tr>

I already have the Javascript code that fakes the request according to the book

<head>
  <title><%= title %></title>
  <%= csrf_meta_tag %>
  <%= render 'layouts/stylesheets' %>
  <%= javascript_include_tag :all %>
</head>

and this is part of my routes.rb

Rails.application.routes.draw do

  get 'sessions/new'

  resources :users
  resources :sessions, :only => [:new, :create, :destroy]
  resources :microposts, :only => [:create, :destroy]

  match '/signup', :to => 'users#new', via: [:get, :post]
  match '/signin', :to => 'sessions#new', via: [:get, :post]
  match '/signout', :to => 'sessions#destroy', via: [:get, :post]
  match '/contact', :to => 'pages#contact', via: [:get, :post]
  match '/about', :to => 'pages#about', via: [:get, :post]
  match '/help', :to => 'pages#help', via: [:get, :post]
  match '/:id', :to => 'users#show', via: [:get, :post]

  root :to => 'pages#home'

Here is the application.js

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .

And the micropost_controller.rb

class MicropostsController < ApplicationController

    before_filter :authenticate, :only => [:create, :destroy]
    before_filter :authorized_user, :only => :destroy

    def create
        @micropost = current_user.microposts.build(micropost_params)
        if @micropost.save
            flash[:success] = "Micropost created!"
            redirect_to root_path
        else
            @feed_items = []
            render 'pages/home'
        end
    end

    def destroy
        @micropost.destroy
        redirect_back_or root_path
    end

    private
        def micropost_params
            params.require(:micropost).permit(:content)
        end

        def authorized_user
            @micropost = Micropost.find(params[:id])
            redirect_to root_path unless current_user?(@micropost.user)
        end
end

I've founded this answer, but the "button_to" method doesn't seem to solve my problem: Delete link sends "Get" instead of "Delete" in Rails 3 view

Thank you very much in advance for any answer.

Upvotes: 1

Views: 1045

Answers (1)

glyuck
glyuck

Reputation: 3397

Make sure you have

//= require jquery
//= require jquery_ujs

in your application.js. Also review browser's javascript console after page loaded. Maybe there are some javascript errors, they can block jquery_ujs from working.

Also, note that you need to change :confirm => "You sure?" to :data=> {:confirm => "You sure?"}

Explanation: RUBY is trying to be RESTful, so it's sending PATCH requests for edit action, DELETE requests for destroy action. But most browsers can only submit GET and POST forms. Hyper-links are always opened via GET (and link_to generates <a href=...> tag). So rails do some hackery and "emulate" DELETE, PUT and PATCH requests.

form_tag helper creates additional hidden input: <input name="_method" type="hidden" value="delete" />, then Rails parses requests parameters and assumes that it's DELETE request. You can read about it in documentation.

link_to 'delete', '/some/url', :method => :delete, in its turn, will generate following html: <a href="/some/url/" data-method="delete">delete</a>. Then jquery_ujs javascript intercepts all clicks on links with data-method attribute and creates hidden form with method="POST" and, yes, hidden input with name="_method" value="delete", then this form is submitted. Take a look at jquery_ujs source code, it's rather straightforward.

SO if you see GET request in server console after clicking link with method: :destroy, most likely, there are some problems with javascript.

Upvotes: 4

Related Questions