Search code examples
ruby-on-railsdeviseruby-on-rails-7devise-invitable

How to use Devise Invitable with Rails 7 and Turbo Stream


I have a Rails 7 app with Devise 4.9 and Devise Invitable 2.0.7.

In initializers/devise.rb I have set this navigational_formats to:

config.navigational_formats = ['*/*', :html, :turbo_stream]

This allows the devise forms to work correctly.

However, this config breaks the devise invitation forms for example: This form app/views/devise/invitations/new.html.erb has

<%= form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :post }) do |f| %>

If I try to submit this form I get this error:

undefined method `users_url' for #<Users::InvitationsController:0x00000000050dc0>

If I add this to my routes

resources :users

Then I get this error when I submit the form:

undefined method `empty?' for #<User id: nil,  ...

If I add data: {turbo: false} to the invitation's form_for, then the form will submit BUT it will not work with turbo stream.

How do I make Devise Invitable work with this Devise configuration?

config.navigational_formats = ['*/*', :html, :turbo_stream]

Or how should i handle this situation?


Solution

  • The "Application error" in the rails error view had this:

    ActionView::MissingTemplate: Missing template users/invitations/new, devise/invitations/new, devise/new, application/new with {:locale=>[:en], :formats=>[:turbo_stream], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}

    This error is saying "I couldn't find your 'new' template."

    I was able to make the invitation form work like this:

    In app/views/devise/invitations/new.html.erb:

    <%= render "form", resource: resource %>
    

    In app/views/devise/invitations/new.turbo_stream.erb:

    <%= turbo_stream.replace dom_id(resource) do %>
      <%= render "form", resource: resource %>
    <% end %>
    

    In app/views/devise/invitations/_form.html.erb I made the form_for like normal but added an id that was equal to dom_id(resource):

    <%= form_for(resource, as: resource_name, url: user_invitation_path, html: { method: :post, id: dom_id(resource) }) do |f| %>
    

    This will prevent the error because Rails finds the new.turbo_stream.erb file and replaced the partial (if the form submission has errors).

    For more info, see: https://rubydoc.info/github/hotwired/turbo-rails/Turbo/StreamsHelper