render devise forms natively with this one neat hotwire native trick

Hello Hotwire Weekly readers,

It was an honor to be included in the most recent edition of Hotwire Weekly!

If you love Rails and or Hotwire, please connect with me on LinkedIn here or on the bird app here.

Recently I added the standard Devise authentication library to a Rails 8 hotwire app. However, I noticed that my Hotwire native app would render the web versions of the sign in and sign up forms. This stumped me until I remembered from Joe Masilotti’s ‘Hotwire Native For Rails Developers’ book that I had created a ConfigurationsController in the Rails app that would tell the associated hotwire native apps to render a native modal for forms. However, due to pattern matching in that controller, these form page links had to end in /new or /edit

Ok now lets take a look at the standard Devise routes…

# Registration Routes: 
/users/sign_up -> devise/registrations#new 
/users -> devise/registrations#create 
/users/edit -> devise/registrations#edit 
/users -> devise/registrations#update (PUT/PATCH) 
/users -> devise/registrations#destroy (DELETE) 

# Session Routes: 
/users/sign_in -> devise/sessions#new 
/users/sign_in -> devise/sessions#create (POST) 
/users/sign_out -> devise/sessions#destroy (DELETE) 

# Password Routes: 
/users/password/new -> devise/passwords#new 
/users/password -> devise/passwords#create (POST) 
/users/password/edit-> devise/passwords#edit 
/users/password -> devise/passwords#update (PUT)

Ah, there’s our problem. The Sign Up and Sign In form links are at users/sign_up and users/sign_up… That is going to evade our /new and /edit pattern matching and cause our devise forms to render in the non-native web views within the apps. Thankfully there is an easy solution to this… We just need to re-map our devise sign in and sign up links to end with /new or /edit!

There may be better ways to do this but I achieved this my simply remapping the routes like so:

devise_scope :user do
  get 'sign_ins/new' => 'devise/sessions#new', as: :new_sign_in
  get 'sign_ups/new' => 'devise/registrations#new', as: :new_sign_up
end

This means that my sign up and sign in URLs are now sign_ups/new and sign_ins/new – Now I get the native modal UI experience for free, just buy making these few small changes that make the registration forms to open up in the native style modal as seen below. Ive got some work to do on adding the bootstrap stying to the form fields and buttons but you get the idea!

# Don't forget to change the sign-in and sign-up links in your web app to the 'new_sign_in_path' and 'new_sign_in_path' paths so nothing breaks in the web app! 

# To be thorough you'll also want to update the links at devise/shared/_links.html.erb to the new paths.

Update: Joe (from the Hotwire Native for Rails Developers book) got in touch and also suggested this alternative approach – He says that updating your ConfigurationsContrtoller like the code below should also do the trick. Either way, you should now be all set on getting Devise forms to work natively with your hotwire native apps now!

class ConfigurationsController < ApplicationController
  def ios_v1
    render json: {
      settings: {},
      rules: [
        {
          patterns: [
            "/new$",
            "/edit$",
            "/users/sign_in",
            "/users/sign_up"
          ],
          properties: {
            context: "modal"
          }
        },
        # ...
      ]
    }
  end
end