Now that we've finished Chapter 8 of the Rails tutorial, I'll post about Session as an output.
The protocol that underpins the Internet, HTTP
, is stateless
. Since there is literally no "state", each HTTP request
does not inherit the information of the previous request.
It is easy to understand by looking at the following example.
"Stateful example" Customer: Hello Clerk: Welcome. Welcome to XX Burger Customer: I'd like a hamburger set Clerk: What would you like to have on the side menu? Customer: With potatoes Clerk: What would you like to drink? Customer: With ginger ale Clerk: How about making a drink L size for +50 yen? Customer: M is fine Clerk: Are you sure you want to do that? Customer: Yes Clerk: I'm clever
"Stateless example" Customer: Hello Clerk: Welcome. Welcome to XX Burger Customer: I'd like a hamburger set Clerk: What would you like to have on the side menu? Customer: Please give me a hamburger set with potatoes Clerk: What would you like to drink? Customer: Please give me a hamburger set with potatoes and ginger ale Clerk: How about making a drink L size for +50 yen? Customer: Please give me a hamburger set with potatoes and ginger ale (M) Clerk: Are you sure you want to do that? Customer: I'd like a hamburger set with potatoes and ginger ale (M). that's all Clerk: I'm clever
In the stateful
example, the clerk (server) remembers the order status of the customer (client) (inheriting the previous information). This is called the application state or session state.
On the other hand, you can see that stateless
does not remember the order status (it does not carry over the previous information). You may be in trouble if you are stateless
. That is when you use features such as login authentication
and shopping cart
. If you forget the previous communication, you need to perform processing such as "login authentication" and "every time you want more products, put everything back in the basket, including the products you put in the past".
session
is a function to remember that you are" logged in "so that you do not have to log in again even if you change pages after logging in. In other words, it is a mechanism for realizing stateful communication.
We'll skip creating the controller and routing, and start by creating the login form.
The biggest difference between a session form and a user registration form is that there is no Session model for sessions, so there is no equivalent to an instance variable like @user. Therefore, the information you have to pass to the form_with helper
when creating a new session form is slightly different.
form_with(model: @user, local: true)
Rails automatically determines that "the action of the form is a POST to the URL / users" just by writing as above, but in the case of a session, the scope of the resource (here, the session) and its corresponding You need to specify the URL specifically.
form_with(url: login_path, scope: :session, local: true)
Note that scope:: session
=> form data goes into: session.
Next, the content entered in the login form is received by the create action of the session controller, and the user is found in the database and verified.
sessions_controller.rb
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
#Redirect to user information page after user login
else
#Create an error message
render 'new'
end
end
user = User.find_by(email: params[:session][:email].downcase)
(1) Receive the email address entered in the login form with params, retrieve the user information from the database with find_by, and use the downcase method
to ensure a match when a valid email address is entered.
if user && user.authenticate(params[:session][:password])
(2) Check if user is nil and authenticate with authenticate method
.
session[:user_id] = user.id
When you execute the above code, you can save it in the browser with the session method and access the browser like a variable.
#Log in as the passed user
def log_in(user)
session[:user_id] = user.id
end
If you're logged in, use current_user
to return information about that user. Also, use the if statement
to reduce the number of database queries.
#Returns the currently logged in user (if any)
def current_user
if session[:user_id]
@current_user ||= User.find_by(id: session[:user_id])
end
end
Then change the layout depending on whether the user is logged in or not. For that, we need a method that returns the logical value of whether we are logged in or not, so we will implement it.
The state in which the user is logged in means that "the user id exists in session", that is, the state where current_user
is not nil
.
#Returns true if the user is logged in, false otherwise
def logged_in?
!current_user.nil?
end
Change the layout as follows using the logged_in?
method that returns a logical value.
<% if logged_in? %>
#Links for logged-in users
<% else %>
#Links for users who are not logged in
<% end %>
To log out, remove the user ID from the session.
#Log out the current user
def log_out
session.delete(:user_id)
@current_user = nil
end
Recommended Posts