[RUBY] Implement user edit / update function without using devise

Introduction

This time, I will explain how to implement the user's My Page and then make it possible to edit the profile.

Prerequisites

・ Devise has been installed ・ Implemented new user registration/login function by devise

Development environment

Ruby 2.6.5 Rails 6.0.0 MySQL 5.6.50

procedure

1) User details (implementation of My Page)

First, create a users controller separate from the devise one. Execute the following command in the terminal.

Terminal


$ rails g controller users show

After creating the controller, edit the file as follows.

controllers/users_controller


class UsersController < ApplicationController
  before_action :set_user, only: [:show]

  def show; end

  private

  def set_user
    @user = User.find(params[:id])
  end

end

Next, set the routing as well.

config/routes.rb


#Add to the existing description
resources :users, only: [:show] 

This completes the setting of the path and action to My Page. Next, we will describe the view.

It will be described in views/users/show.html.erb. That's all for the implementation of My Page.

2) Implementation of user editing function

From here on, it's just my case, so please keep it as a reference.

First, I made the DB design (** migration file **) as follows.

The devise uses table only creates the nickname column.

devise_create_users.rb



class DeviseCreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :nickname, null: false
      t.string :email,              null: false, default: ''
      t.string :encrypted_password, null: false, default: ''
      #abridgement
end

Next, we will design a table for the profile. Execute the following command in the terminal (In my case, I created a intro model for my profile)

Terminal


$ rails g model intro

Edit the migration file.

create_intros.rb



class CreateIntros < ActiveRecord::Migration[6.0]
  def change
    create_table :intros do |t|
      t.string :image
      t.string :first_name
      t.string :last_name
      t.string :website
      t.text   :profile
      t.references :user, foreign_key: true
      t.timestamps
    end
  end
end

This completes the table design.

2-1) Model association settings

Next, regarding the association, I made the following settings.

models/user.rb


has_one :intro

models/intro.rb


belongs_to :user

In this way, we have a one-to-one relationship.

2-2) Routing and action settings

config/routes.rb


resources :users, only: [:show] 
resources :intros, only: [:new, :create, :edit, :update]

I did the routing as above, not ** nesting **. The reason is that the table for user editing seems to be similar to the table for posting tweets etc. as an image.

As with actions, I think it would be easier to implement if you have an image that ** replaces the posting function with user editing ** as an image.

Next, define the action.

controllers/intros_controller.rb


class IntrosController < ApplicationController
 #Handling of unlogged-in users
  before_action :authenticate_user!, only: [:new, :edit]
  #Refactoring
  before_action :set_intro, only: [:edit, :update]
 
  def new
    @intro = Intro.new
   #Prevent already registered users from transitioning to the new registration page
  if Intro.find_by(user_id: current_user.id)
      redirect_to root_path
    end
  end
  
  def create
    @intro = Intro.new(intro_params)
   #After saving, pass the id of the user associated with the intro model as an argument to return to the user details page.
    # intoro.valid?Not because it has not been validated
    if @intro.save
      redirect_to user_path(@intro.user.id)
    else
      render :new
    end
  end

  def edit
    #Prevents page transitions unless the logged-in user and the editing user match
    unless current_user.id == @intro.user.id
      redirect_to user_path(@intro.user.id)
    end
  end

  def update
   #If you can update like create, pass the argument to return to the user details
    if @intro.update(intro_params)
      redirect_to user_path(@intro.user.id)
    else
      render :edit
    end
  end

  private

  def set_intro
    @intro = Intro.find(params[:id])
  end

  def intro_params
    params.require(:intro).permit(:first_name, :last_name, :website, :profile, :image).merge(user_id: current_user.id)
  end
end

This completes the implementation of the user edit / update function. Finally create the view.

Also, at this time, ** specify the conditions for the link that transitions to the user edit page **.

2-3) Edit views/users/show.html.erb

ruby:users/show.html.erb


<% if user_signed_in? %>
#If the value of User does not exist in the intro table, a new registration link will be displayed.
  <% unless @user.intro.present? %>
#If the logged-in user and the user displayed on My Page are the same, a new registration link will be displayed.
    <% if current_user.id == @user.id %>
       <div class="profile-btn">
         <%= link_to 'Edit profile', new_intro_path, class: "profile-edit-btn" %>
       </div>
    <% end %>
  <% end %>

#If the logged-in user and the user displayed on My Page are the same and the value exists in the intro table, a link to the edit page will be displayed.
  <% if current_user.id == @user.id && @user.intro.present? %>
    <div class="profile-btn">
      <%= link_to 'Edit profile', edit_intro_path(@user.intro.id), class: "profile-edit-btn" %>
    </div>
  <% end %>
<% end %>   

In my case, I could only write like this, but I would appreciate it if you could comment if there is a better description.

It took me a day and a half to get here, so I hope you've seen this article and made some progress.

References

[Rails] To check if there is even one data Model.exists?

Recommended Posts

Implement user edit / update function without using devise
Implement user management functionality using Devise
Implementation of user authentication function using devise (2)
Creating a user authentication function using devise
Implementation of user authentication function using devise (1)
Implementation of user authentication function using devise (3)
Implement partial match search function without using Ransuck
Implement devise edit page
How to update devise user information without a password
Implement category function using ancestory
Edit user information with Devise
Implement user registration function and corporate registration function separately in Rails devise
User evaluation using the like function
[Rails] [Devise] Edit profile without password
How to update user edits in Rails Devise without entering a password
Create authentication function in Rails application using devise
Implement share button in Rails 6 without using Gem
Use [Rails] devise Guest user function (for portfolio)
Tag function using acts-as-taggable-on on Devise My memo
Implement the star five function using the for statement
Implement star rating function using Raty in Rails6
Implement the product category function using ancestry ① (Preparation)
How to implement the breadcrumb function using gretel
Flow to implement image posting function using ActiveStorage
[Note] Summary of rails login function using devise ①
devise user registration
Continued ・ Flow to implement image posting function using ActiveStorage
Introduce devise in Rails to implement user management functionality
Implement test doubles in JUnit without using external libraries
Implement user follow function in Rails (I use Ajax) ②
Implement user follow function in Rails (I use Ajax) ①
Rails learning How to implement search function using ActiveModel
Try to implement tagging function using rails and js
When changing user information using devise Settings on the edit screen when the password is not saved