[RUBY] Implement user management functions in a wizard format

Overview

This time, it's about implementing the user management function in a wizard format. The wizard format is a format in which user registration is performed while transitioning screens.

This time, the registration requirements for the user model are nickname, grade, email, password

Then screen transition to user_info model subject, school, profile

To register.

By the way, user_info is your favorite subject, school, and profile.

Implementation

First, install devise and create a user model.

Email and password are included by default, so add nickname and grade.

Now that we've added the columns, edit the controller as follows:

controllers.application_controller.rb


class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :grade])
  end
end

Next, validate the user model (code omitted)

Then create a view file.

views.devise.registrations.new.html.erb


<h2>User information registration</h2>

<%= form_for(@user, url: user_registration_path) do |f| %>
  <%= render "devise/shared/error_messages", resource: @user %>

  <div class="field">
    <%= f.label :nickname %><br />
    <%= f.text_field :nickname %>
  </div>

  <div class="field">
    <%= f.label :grade %><br />
    <%= f.text_field :grade %>
  </div>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

Create a login screen.

views.home.index.html.erb


<h1>top page</h1>

<% if user_signed_in?%>
  <h2>You are logged in</h2>
  <%= link_to "Log out", destroy_user_session_path, method: :delete %>
<% else %>
  <h2>You are not logged in</h2>
  <%= link_to "sign up", new_user_registration_path %>
  <%= link_to "Login", new_user_session_path %>
<% end %>

Create a user_info model after screen transition.

At this time, do not forget to associate user_id as a foreign key.

After that, the user model and the user_info model are associated.

Next, create a devise controller.

rails g devise:controllers users

Next is routing.

routes.rb


Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
  root to: "home#index"
end

At this point, we will implement to register user_info.

Write a new method in the registrations controller and put the form in the view file.

views/devise/registrations/new.html.erb


<%= form_for(@user, url: user_registration_path) do |f| %>
  <%= render "devise/shared/error_messages", resource: @user %>

---abridgement---

 <div class="actions">
    <%= f.submit "Next" %>
  </div>
<% end %>

The description will increase a little from here. Let's write the create action.

controllers/users/registrations_controller.rb



def create
   @user = User.new(sign_up_params)
    unless @user.valid?
      render :new and return
    end
   session["devise.regist_data"] = {user: @user.attributes}
   session["devise.regist_data"][:user]["password"] = params[:user][:password]
   @user_info = @user.build_user_info
   render :new_user_info
 end

Bring the data described on the first page using session. And the data is formatted by the attributes method.

Create an instance of the UserInfo model linked to the instance @user generated this time with build_user_info. The instance of the UserInfo model generated here is assigned to the instance variable @user_info. Then render to the view of the new_user_info action that displays the page to register the address information.

Let's set the routing of the new_user_info action that displays the page to register user_info and the create_user_info action that registers the address information.

routes.rb


Rails.application.routes.draw do

  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
  devise_scope :user do
    get 'user_infos', to: 'users/registrations#new_user_info'
    post 'user_infos', to: 'users/registrations#create_user_info'
  end

  resources :posts

  root to: "home#index"
end

As described in this routing, we will create a view file to register user_info.

views/devise/registrations/new_user_info.html.erb


<h2>User information registration</h2>

<%= form_for @user_info do |f| %>
  <%= render "devise/shared/error_messages", resource: @user_info %>

  <div class="field">
    <%= f.label :subject, "The subject you want to do your best" %><br />
    <%= f.text_field :subject %>
  </div>

  <div class="field">
    <%= f.label :school, "school name" %><br />
    <%= f.text_field :school %>
  </div>

  <div class="field">
    <%= f.label :profile, "Fill in your self-introduction" %><br />
    <%= f.text_area :profile %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

Let's make the description to save this user_info the controller.

controllers/users/registrations_controller.rb


def create_user_info
    @user = User.new(session["devise.regist_data"]["user"])
    @user_info = UserInfo.new(user_info_params)
      unless @user_info.valid?
        render :new_user_info
      end
    @user.build_user_info(@user_info.attributes)
    @user.save
    session["devise.regist_data"]["user"].clear
    sign_in(:user, @user)
  end

  protected

  def user_info_params
    params.require(:user_info).permit(:subject, :school, :profile)
  end

After saving user, I'm deleting session with .clear. And it is written to log in after being saved.

Finally, create a view that corresponds to the create_user_info action.

views/devise/registrations/create_user_info.html.erb


<h2>Registration has been completed</h2>
<%= link_to "Back to top", root_path%>

that's all.

Impressions

For the first time, we implemented a wizard-style registration function.

I really wanted to implement grade grade with active_hash, but I gave up after suffering from a two-hour error ...

I will try to implement it once and try again if I can afford it.

I'm doing my best every day, but I don't feel much growth. You can't do anything without seeing the article ...

I will do my best.

Recommended Posts

Implement user management functions in a wizard format
Introduce devise in Rails to implement user management functionality
3 Implement a simple interpreter in Java
Implement user management functionality using Devise
Implement a gRPC client in Ruby
Implement a contact form in Rails
Implement something like a stack in Java
How to implement a like feature in Rails
How to implement a like feature in Ajax in Rails
Implement a multi-column IN clause (column: condition = n: n) in DOMA.
Implement user follow function in Rails (I use Ajax) ②
Quickly implement a singleton with an enum in Java
Implement user follow function in Rails (I use Ajax) ①
[Programming complete] §5 Create a review management app in Ruby
Let's take a look at the functions of Keycloak's management console (user edition), user account service