如何让Devise Invitable适配Rails7的Devise turbo_stream导航格式配置?
解决Devise Invitable适配Turbo Stream的问题
问题根源
当Devise的navigational_formats包含:turbo_stream时,Devise Invitable的控制器在处理表单提交后,会默认尝试重定向到users_url(用户列表页),如果路由里没配置这个路径就会报错;就算加上resources :users,控制器在turbo响应下的逻辑又会触发empty?调用的错误——本质是Devise Invitable的默认逻辑没适配Turbo的响应格式。
方案一:自定义邀请控制器适配Turbo Stream
这是最灵活的解决方式,能完全控制turbo响应:
- 生成自定义的用户邀请控制器:
rails generate devise:controllers users -c invitations - 打开
app/controllers/users/invitations_controller.rb,重写create方法,专门处理turbo_stream格式的响应:class Users::InvitationsController < Devise::InvitationsController def create super do |resource| # 邀请成功且请求是turbo格式时,返回自定义turbo响应 if resource.errors.empty? && request.format.turbo_stream? respond_to do |format| format.turbo_stream do # 示例:添加成功提示到页面,同时重置表单 render turbo_stream: [ turbo_stream.append('flash_notices', partial: 'shared/flash', locals: { message: '邀请已发送' }), turbo_stream.replace('invitation_form', partial: 'devise/invitations/new', locals: { resource: User.new }) ] end end end end end # 可选:重写update方法,处理用户接受邀请后的turbo响应 def update super do |resource| if resource.errors.empty? && request.format.turbo_stream? respond_to do |format| format.turbo_stream do render turbo_stream: turbo_stream.replace('invitation_form', partial: 'users/invitation_success') end end end end end - 在
config/routes.rb中指定使用这个自定义控制器:devise_for :users, controllers: { invitations: 'users/invitations' }
方案二:单独给特定Devise控制器开启Turbo支持
如果不想自定义控制器,可以修改initializers/devise.rb,只给需要Turbo的Devise控制器(比如登录、注册)开启turbo_stream格式,邀请控制器保持默认:
# 先把全局navigational_formats改回默认(去掉:turbo_stream) config.navigational_formats = ['*/*', :html] # 单独给需要Turbo的Devise控制器添加turbo_stream支持 Rails.application.config.to_prepare do Devise::SessionsController.navigational_formats = ['*/*', :html, :turbo_stream] Devise::RegistrationsController.navigational_formats = ['*/*', :html, :turbo_stream] # 其他需要Turbo的Devise控制器(比如密码重置)也可以在这里添加 end
方案三:修复路由并调整默认跳转路径
如果坚持全局开启Turbo格式,可以:
- 在
config/routes.rb中添加用户列表路由(解决users_url报错):resources :users, only: [:index] - 然后自定义邀请成功后的跳转路径,避免默认跳转到用户列表,同时处理turbo响应:
class Users::InvitationsController < Devise::InvitationsController private # 重写邀请成功后的跳转路径 def after_invite_path_for(resource) # 改成你实际需要的页面,比如后台首页 admin_dashboard_path end def create build_resource resource.invite!(current_inviter) do |err| if err respond_with_navigational(resource) { render :new } else set_flash_message! :notice, :send_instructions # turbo格式下返回turbo响应,不使用重定向 if request.format.turbo_stream? render turbo_stream: turbo_stream.append('flash', partial: 'shared/flash', locals: { message: flash[:notice] }) else respond_with resource, location: after_invite_path_for(resource) end end end end end - 别忘了在路由里指定这个自定义控制器。
内容的提问来源于stack exchange,提问作者don_Bigote
相关产品推荐
相关产品推荐

