Ruby on Rails: Building a RESTful API with Ruby on Rails and JWT Au......
rails new multi_step_form cd multi_step_form
rails generate model User email:string password_digest:string rails generate model Profile first_name:string last_name:string user:references rails generate model Address street:string city:string zip:string user:references
rails db:migrate
# Gemfile gem 'bcrypt', '~> 3.1.7'
bundle install
# app/models/user.rb class User < ApplicationRecord has_secure_password has_one :profile has_one :address end
mkdir app/forms
# app/forms/user_form.rb
class UserForm
include ActiveModel::Model
attr_accessor :email, :password, :password_confirmation
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
validates :password, presence: true, confirmation: true
end
# app/forms/profile_form.rb class ProfileForm include ActiveModel::Model attr_accessor :first_name, :last_name validates :first_name, :last_name, presence: true end
# app/forms/address_form.rb class AddressForm include ActiveModel::Model attr_accessor :street, :city, :zip validates :street, :city, :zip, presence: true end
rails generate controller Registration new_user new_profile new_address create
# app/controllers/registration_controller.rb
class RegistrationController < ApplicationController
def new_user
@user_form = UserForm.new(session[:user_form])
end
def new_profile
redirect_to new_user_registration_path unless session[:user_form]
@profile_form = ProfileForm.new(session[:profile_form])
end
def new_address
redirect_to new_user_registration_path unless session[:user_form] && session[:profile_form]
@address_form = AddressForm.new(session[:address_form])
end
def create
@user_form = UserForm.new(session[:user_form])
@profile_form = ProfileForm.new(session[:profile_form])
@address_form = AddressForm.new(session[:address_form])
if @user_form.valid? && @profile_form.valid? && @address_form.valid?
user = User.create!(
email: @user_form.email,
password: @user_form.password
)
user.create_profile!(
first_name: @profile_form.first_name,
last_name: @profile_form.last_name
)
user.create_address!(
street: @address_form.street,
city: @address_form.city,
zip: @address_form.zip
)
reset_session
redirect_to root_path, notice: 'Registration completed successfully!'
else
render :new_user
end
end
def update_user
@user_form = UserForm.new(user_form_params)
if @user_form.valid?
session[:user_form] = user_form_params
redirect_to new_profile_registration_path
else
render :new_user
end
end
def update_profile
@profile_form = ProfileForm.new(profile_form_params)
if @profile_form.valid?
session[:profile_form] = profile_form_params
redirect_to new_address_registration_path
else
render :new_profile
end
end
def update_address
@address_form = AddressForm.new(address_form_params)
if @address_form.valid?
session[:address_form] = address_form_params
redirect_to create_registration_path
else
render :new_address
end
end
private
def user_form_params
params.require(:user_form).permit(:email, :password, :password_confirmation)
end
def profile_form_params
params.require(:profile_form).permit(:first_name, :last_name)
end
def address_form_params
params.require(:address_form).permit(:street, :city, :zip)
end
end
<!-- app/views/registration/new_user.html.erb -->
<h2>Step 1: User Information</h2>
<%= form_with model: @user_form, url: update_user_registration_path, method: :patch do |form| %>
<div>
<%= form.label :email %>
<%= form.email_field :email %>
</div>
<div>
<%= form.label :password %>
<%= form.password_field :password %>
</div>
<div>
<%= form.label :password_confirmation %>
<%= form.password_field :password_confirmation %>
</div>
<%= form.submit "Next" %>
<% end %>
<!-- app/views/registration/new_profile.html.erb -->
<h2>Step 2: Profile Information</h2>
<%= form_with model: @profile_form, url: update_profile_registration_path, method: :patch do |form| %>
<div>
<%= form.label :first_name %>
<%= form.text_field :first_name %>
</div>
<div>
<%= form.label :last_name %>
<%= form.text_field :last_name %>
</div>
<%= form.submit "Next" %>
<% end %>
<!-- app/views/registration/new_address.html.erb -->
<h2>Step 3: Address Information</h2>
<%= form_with model: @address_form, url: update_address_registration_path, method: :patch do |form| %>
<div>
<%= form.label :street %>
<%= form.text_field :street %>
</div>
<div>
<%= form.label :city %>
<%= form.text_field :city %>
</div>
<div>
<%= form.label :zip %>
<%= form.text_field :zip %>
</div>
<%= form.submit "Finish" %>
<% end %>
# config/routes.rb Rails.application.routes.draw do root "welcome#index" resource :registration, only: [] do get :new_user, on: :collection patch :update_user, on: :collection get :new_profile, on: :collection patch :update_profile, on: :collection get :new_address, on: :collection patch :update_address, on: :collection get :create, on: :collection end end
# test/forms/user_form_test.rb
require "test_helper"
class UserFormTest < ActiveSupport::TestCase
test "valid user form" do
form = UserForm.new(email: "[email protected]", password: "password", password_confirmation: "password")
assert form.valid?
end
test "invalid without email" do
form = UserForm.new(password: "password", password_confirmation: "password")
assert_not form.valid?
end
end
# test/integration/registration_flow_test.rb
require "test_helper"
class RegistrationFlowTest < ActionDispatch::IntegrationTest
test "successful registration" do
get new_user_registration_path
assert_response :success
patch update_user_registration_path, params: {
user_form
Sign up for free and be the first to get notified about new posts.
2 comments
This was so helpful thanks a lot and cheers this tutorial was so detailed and educational thanks again.
you very welcome Im glad I could help.