This time, I will explain how to implement the user's My Page and then make it possible to edit the profile.
・ Devise has been installed ・ Implemented new user registration/login function by devise
Ruby 2.6.5 Rails 6.0.0 MySQL 5.6.50
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.
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.
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.
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 **.
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.
[Rails] To check if there is even one data Model.exists?
Recommended Posts