Many web applications require you to build a multi step form especially for things like user registration or checkout flow.
In this blog, we will walk through how to create a multi-step form in Ruby on Rails.
🧩 Why Use a Multi-Step Form?
Let’s quickly look at why you might want a multi-step form:
Increases completion rates as users are more likely to finish shorter steps than one long form.
Improves UX: Long forms can overwhelm users. Breaking them into steps makes the process feel lighter.
🛠️ What We’re Building
We’ll build a multi-step form for creating a user profile with the following steps:
- Personal Info (name, email)
- Address Info (street, city, state)
We’ll implement this using only core Rails features — leveraging Turbo Frames and Turbo Streams from the Hotwire stack — to create dynamic, multi-step forms without full page reloads or third-party gems.
📦 Prerequisites
- Basic knowledge of Rails controllers, views, models, and forms
- Basic knowledge of
turbo_frame_tag
andturbo_stream
🚀 Step-by-Step Implementation
Create a new app
rails new multistep_form_app
cd multistep_form_app
rails db:create
Scaffold User
This will create the controller, views, model, migration and also update the routes file
rails generate scaffold User name:string email:string street:string city:string state:string
rails db:migrate
Update root route to root "users#index"
And your page should look like this
Multi step logic
Now we want the new.html.erb view file on app/views/users/
to be a multi form.
Step 1 - Split the form partial
In the form partial, update the route and wrap both the name and email fields in a turbo_frame_tag "step1"
It should be like this
Step 2 - Create step2 partial
In app/views/users
create a new partial file and name it _step2.html.erb
. This is where we will have Address information and submit button.
Add the following code to it
Step 3 - Create collection route on user resource
Add a collection to the users resource route.
This route will be used when submitting each step of the form.
resources :users do
collection do
post "next_step"
end
end
Step 4 - Create next_step method on users_controller.rb
Add this method to users_controller.rb
def next_step
@name, @email, @next_step = params.values_at(:name, :email, :step)
respond_to do |format|
format.html
format.turbo_stream
end
end
On the next_step method, we will grab and save both name and email and also the current step.
We will be using turbo_stream to replace step1 contents with step2 contents
Final step
On app/views/users
create a file next_step.turbo_stream.erb
and add the following code to it
<%= turbo_stream.replace "step#{@next_step.to_i}" do %>
<%= render partial: "step#{@next_step.to_i + 1}", locals: { name: @name, email: @email } %>
<% end %>
The code above basically replaces anything with turbo frame tag "step#{@next_step.to_i}"
which in our case is step1
with the partial file we created earlier step2
.
It also passes the 2 variable (name & email) to the partial.
Now with that, you can create a new user.
Your final form should look like this
✅ Optional Enhancements
- Add validation logic before proceeding to the next step
- Allow users to go back to previous steps
- Style the form with Tailwind or Bootstrap
- Add a progress indicator
Top comments (0)