Rails 6结合devise使用时link_to的method: :delete失效如何解决?
问题根因
该报错本质是 UJS(Unobtrusive JavaScript)没有正常加载,导致link_to指定的method: :delete没有被拦截处理,浏览器直接发送了GET请求,而Devise默认的登出路由仅支持DELETE请求,因此触发路由不匹配错误。
原有配置不生效是因为Rails 6默认使用Webpacker管理JavaScript资源,app/javascript/application.js是Webpacker的入口文件,不支持旧版Asset Pipeline使用的//= require导入语法,因此之前写的JQuery和jquery_ujs导入规则完全没有生效。
可选解决方法(除button_to外)
方法1:正确导入UJS(最推荐)
Rails 6+官方推荐使用@rails/ujs替代旧的jquery_ujs,无需依赖JQuery即可实现method属性拦截等功能,配置步骤如下:
- 终端执行命令安装依赖:
yarn add @rails/ujs - 修改
app/javascript/application.js,添加如下导入和初始化代码:
import Rails from "@rails/ujs" Rails.start()
配置完成后重启服务,link_to的method: :delete就可以正常生效了。
如果坚持要使用jquery_ujs,可以按如下方式配置:
- 安装依赖:
yarn add jquery jquery-ujs - 修改
app/javascript/application.js:
import $ from 'jquery' window.$ = window.jQuery = $ import 'jquery-ujs'
方法2:修改Devise路由允许GET请求登出(不推荐,安全性较低)
可以直接修改Devise配置,允许登出接口接受GET请求,无需依赖UJS即可直接点击链接登出,修改config/routes.rb中的Devise配置即可:
devise_for :users, sign_out_via: [:get, :delete], controllers: { sessions: 'users/sessions', confirmations: 'users/confirmations', registrations: 'users/registrations' }
方法3:手动编写JS拦截点击事件
可以自行编写JavaScript代码拦截登出链接的点击事件,手动发送DELETE请求,示例代码如下:
- 给
link_to添加自定义类名方便选择:
= link_to "Log out", destroy_user_session_path, class: "logout-link"
- 在
app/javascript/application.js中添加拦截逻辑:
document.querySelector('.logout-link')?.addEventListener('click', function(e) { e.preventDefault() fetch(this.href, { method: 'DELETE', headers: { 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content, 'Content-Type': 'application/json' } }).then(() => window.location.href = '/') })
内容的提问来源于stack exchange,提问作者Hà Mai
相关产品推荐
相关产品推荐

