Hà Mai
Hà Mai

Reputation: 53

Rails 6: link_to method: :delete not working

I have an application that uses Rails 6 and Boootstrap gem 4.4.1 In routes i use devise gem:

devise_for :users, controllers: {
    sessions: 'users/sessions',
    confirmations: 'users/confirmations',
    registrations: 'users/registrations'
  }

in views/layout/application.html.slim

doctype html
html
  head
    title
      = full_title(yield(:title))
    meta[name='viewport' content='width=device-width,initial-scale=1' charset='utf-8']
    = csrf_meta_tags
    = csp_meta_tag
    = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
    = javascript_pack_tag 'application', 'data-turbolinks-track': 'reload'
    = render 'layouts/shim'
    = yield(:head) 
  body
    = render 'layouts/header'
    - flash.each do |message_type, message|
      div class=("text-center alert alert-#{message_type}") = message
    = yield
    = render 'layouts/footer'

I use link_to to display user logout path with method: :delete:

= link_to "Log out", destroy_user_session_path, method: :delete

but got error No route matches [GET] "/users/sign_out" even though in app/javascript/application.js i added

//= require jquery
//= require jquery_ujs 

is there any way around this except using button_to?

Upvotes: 1

Views: 1060

Answers (3)

H Zaman
H Zaman

Reputation: 75

I had this problem too. Try https://github.com/rails/rails/issues/44185.

Basically, method is deprecated, and the new way is to use

data: { turbo_method: :delete, turbo_confirm: "Are you sure?" }

instead. If this doesn't work, try running the commands

rails importmap:install
rails turbo:install stimulus:install

first.

It worked for me, at least.

Upvotes: 0

max
max

Reputation: 101811

You're following outdated instructions.

  • Rails 6 defaults to Webpacker and not Sprockets. You're using javascript_pack_tag and not the older javascript_include_tag.
  • Rails 5.1 replaced jquery_ujs with rails_ujs which removes the jQuery dependency.

The "magical" //= comments are called Sprockets directives and do absolutely nothing in Webpacker - its just a comment. Webpacker instead uses the import directive from ES6.

When you generate a Rails 6 app it actually creates an app/javascripts/packs/application.js file which properly sets up Rails UJS, Turbolinks, ActiveStorage and ActionCable.

You can also add it to an existing app by running bin/rails webpacker:install.

// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"

Rails.start()
Turbolinks.start()
ActiveStorage.start()

You then need to start the webpacker development server with ./bin/webpack-dev-server which will serve the assets. Unlike Sprockets its not "bundled" into the rails server command.

is there any way around this except using button_to?

Yes. Fix your javascript setup (recommended) or use config.sign_out_via = [:delete, :get] in config/intializers/devise.rb to just bury the bug.

However in this case I would really recommend that you use button_to as it will let your users log out even if a script error occurs. You can use CSS to style buttons however you want if thats your hangup.

Upvotes: 1

Dorian
Dorian

Reputation: 9055

Maybe there is an error in your JavaScript, check your console, it shouldn’t be a GET but a DELETE (in the network tab it would show a POST with method delete)

Upvotes: 0

Related Questions