Implement login function using session. Understand how to use session (session [: user_id] = 1)
A mechanism for realizing stateful communication.
In normal browser (stateless) communication, every time a page changes, all the information on the previous page is destroyed. In other words, even if you log in on the previous page, the information that you are logged in is not inherited when you move to the next page, so you will be required to log in every time you move. (Very inconvenient)
Therefore, it is necessary to realize stateful communication that can take over the information on the previous page. Specifically, stateful communication can be realized by storing data in a cookie.
Create a login function without using gem "devise"
Ruby 2.6.3 Rails 6.0.3.3 Use gem "bcrypt" (for password encryption)
Terminal
#File creation ~ rails s
mkdir rails
cd rails
rails new rails_login_session
cd rails_login_session
rails s
Create a file to add login function localhost: 3000 and say Yay! You ’re on Rails!
Gemfile and terminal
gem "bcrypt"
bundle install
Start an editor (Atom, VScode, etc.), uncomment the gem "bcrypt" in the Gemfile, and bundle install in the terminal
Terminal
rails g model User email:uniq password:digest
#Make sure the file is generated
rails db:migrate
Creating a User model
Terminal
rails g controller home top
rails g controller users new show
config/routes.rb
Rails.application.routes.draw do
root 'home#top'
resource :user, only: [:new, :create, :show]
end
Creating a home controller and users controller Routing changes
:app/views/users/new.html.erb
<h1>sign up</h1>
<%= form_with model: @user, url: user_path, local: true do |f| %>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %>
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
</div>
<div>
<%= f.submit "sign up" %>
</div>
<% end %>
app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
end
def create
user = User.new(user_params)
if user.save
session[:user_id] = user.id
redirect_to user_path, notice: "you have successfully sign in"
else
render :new
end
end
def show
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
After starting the server with rails s, access localhost: 3000 / user / new and try signing in with an appropriate email address and password. OK if you can confirm that there are no errors
Terminal
rails g controller sessions new
Create sessions controller
config/routes.rb
root 'home#top'
resource :user, only: [:new, :create, :show]
#Add the following 3 lines
get 'login', to: "sessions#new"
post 'login', to: "sessions#create"
delete 'logout', to: "sessions#destroy"
Routing changes
app/controllers/sessions_controller.rb
lass SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to user_path, notice: "you have successfully login"
else
flash.now[:alert] = "Email or Password is invalid"
render :new
end
end
end
create create action
:app/views/sessions/new.html.erb
<h1>Login</h1>
<%= form_with url: login_path, local: true do |f| %>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br>
<%= f.password_field :password %>
</div>
<div>
<%= f.submit "Login" %>
</div>
<%= link_to "Sign up", new_user_path %>
<% end %>
Create view I also added <% = link_to "Login", login_path%> to the line under submit in users / new.html.erb. After confirming that you can log in successfully, display a flash message next.
:app/views/layouts/application.html.erb
<body>
#Add the following two lines and enclose yield in div tag
<%= notice %>
<%= alert %>
<div class="container">
<%= yield %>
</div>
</body>
Now you will see the flash message. I plan to apply css to div class = "conteiner" later, so add a div tag.
app/controllers/sessions_controller.rb
def destroy
session[:user_id] = nil
redirect_to root_path, notice: "you have successfully logout"
end
Added destroy action
:app/views/users/show.html.erb
<h1>Welcome</h1>
<p>you are login</p>
<%= link_to "Logout", logout_path, method: :delete %>
If you have a logout button, you can create a view appropriately Check if you can log out with rails s and see a flash message.
:app/views/home/top.html.erb
<h1>Hello</h1>
<%= link_to "Sign up", new_user_path %>
<%= link_to "Log in", login_path %>
You can now log in and register from the top page.
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
helper_mathod :current_user
def login?
if current_user.nil?
redirect_to login_path, alert: "you have to login"
end
end
def already_login?
unless current_user.nil?
redirect_to user_path, notice: "you are already login"
end
end
def current_user
if session[:user_id]
current_user ||= User.find(session[:user_id])
end
end
end
app/controllers/sessions_controller.rb
#Add above new action
before_action :already_login?, except: :destroy
app/controllers/users_controller.rb
#Add above new action
before_action :already_login?, only: [:new, :create]
before_action :login?, only: :show
It is problematic for a logged-in user to go to the login screen or the new registration screen. On the contrary, there is a problem that a user who is not logged in can enter the user screen. This solved the above two problems.
:app/views/users/show.html.erb
<h1>Welcome</h1>
<p>you are login as "<strong><%= current_user.email %></strong>"</p>
<%= link_to "Logout", logout_path, method: :delete %>
Changed to be able to display the email address of the user logged in to users / show.html.erb
app/assets/stylesheets/application.css
.container{
text-align: center;
}
.field{
margin: 20px 0 20px;
}
input{
width: 400px;
padding: 10px 15px;
font-size: 16px;
border-radius: 3px;
border: 2px solid #ddd;
}
that's all.
Recommended Posts