12/08/2018, 15:40

Sample app thần thánh với Sessions và Cookies trong Ruby on Rails - Phần 2

Chào các bạn, tiếp tục series bài viết về Sessions và Cookies, trong bài viết này mình sẽ tiếp nối bài viết "Sample app thần thánh với Sessions và Cookies trong Ruby on Rails - Phần 1" Logging in Trường hợp thông tin đăng nhập là hợp lệ # Include Session helper module vào bên trong ...

Chào các bạn, tiếp tục series bài viết về Sessions và Cookies, trong bài viết này mình sẽ tiếp nối bài viết "Sample app thần thánh với Sessions và Cookies trong Ruby on Rails - Phần 1"

Logging in

  • Trường hợp thông tin đăng nhập là hợp lệ
# Include Session helper module vào bên trong ApplicationController
# Trong app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  include SessionsHelper
end
  • log_in method Chúng ta có thể xử lý session như là 1 hash và gán nó như sau:
session[:user_id] = user.id

Điều này sẽ "đặt" một cookie tạm thời (cookie temporary) trên trình duyệt của người dùng chứa mã người dùng (user_id) đã được mã hóa (encrypted), cho phép có thể lấy id trên những trang tiếp theo sử dụng session[:user_id]. cookie temporary này sẽ hết hạn ngay khi trình duyệt bị đóng. Định nghĩa 1 method được gọi là log_in trong SessionsHelper để sử dụng kỹ thuật login trong 1 vài nơi khác:

# Trong app/helpers/sessions_helper.rb
module SessionsHelper

  # log_in method
  def log_in user
    session[:user_id] = user.id
  end
end

Với log_in method được định nghĩa, chúng ta sẵn sàng hoàn thành create action của session bằng việc logging user vào và chuyển hướng tới trang thông tin người dùng (User's profile)

# Trong app/controllers/sessions_controller.rb
class SessionsController < ApplicationController

  def new
  end

  def create
    user = User.find_by email: params[:session][:email].downcase
    
    if user && user.authenticate(params[:session][:password])
      log_in user
      redirect_to user
    else
      flash.now[:danger] = "Invalid email/password combination"
      render :new
    end
  end

  def destroy
  end
end

Current user

Sau khi tạo ra 1 temporary session để lưu lại user_id, chúng ta sẽ lấy nó để sử dụng ở các trang tiếp theo, chúng ta sẽ thực hiện bằng cách xác định một method là current_user để tìm kiếm user trong database tương ứng với session id

  • Để tìm kiếm user hiện tại, sử dụng find method:
User.find session[:user_id]

find method sẽ sinh ra 1 ngoại lệ nếu user_id này không tồn tại, để xử lý trường hợp này, sử dụng find_by method thay vì, nó sẽ trả về nil khi không tìm thấy user:

User.find_by id: session[:user_id]
  • current_user method được định nghĩa như sau:
# Trong app/helpers/sessions_helper.rb
module SessionsHelper
...
  # Trả về user hiện tại đã loggin (nếu tồn tại).
  def current_user
    @current_user ||= User.find_by(id: session[:user_id])
  end
end

logged_in? method

  • Kiểm tra user đã loggin hay chưa:
# Trong app/helpers/sessions_helper.rb
module SessionsHelper
...
  def current_user
    @current_user ||= User.find_by(id: session[:user_id])
  end
  
  # Trả về true nếu user logged in, và false nếu không
  def logged_in?
    current_user.present?
  end
end
  • Custom view
# app/views/layouts/_header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%= link_to "sample app", root_path, id: "logo" %>
    <nav>
      <ul class="nav navbar-nav navbar-right">
        <li><%= link_to "Home", root_path %></li>
        <li><%= link_to "Help", help_path %></li>
        <% if logged_in? %>
          <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
              Account <strong class="caret"></strong>
            </a>
            <ul class="dropdown-menu">
              <li><%= link_to "Profile", current_user %></li>
              <li class="divider"></li>
              <li>
                <%= link_to "Log out", logout_path, method: :delete %>
              </li>
            </ul>
          </li>
        <% else %>
          <li><%= link_to "Log in", login_path %></li>
        <% end %>
      </ul>
    </nav>
  </div>
</header>
  • Custom trong UsersController Khi user được tạo sẽ loggin và chuyển hướng tới trang User's profile
# Trong app/controllers/users_controller.rb
class UsersController < ApplicationController
...
  def create
    @user = User.new user_params
    
    if @user.save
      log_in @user
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render :new
    end
  end

  private

  def user_params
    params.require(:user).permit :name, :email, :password,
      :password_confirmation
  end
end

Logging out

  • Xóa user_id từ session, sử dụng delete method
session.delete :user_id
  • Định nghĩa 1 method: log_out trong SessionHelper
# Trong app/helpers/sessions_helper.rb
module SessionsHelper
...
  # log_out method
  def log_out
    session.delete :user_id
    @current_user = nil
  end
end

Và sử dụng trong app/controllers/sessionscontroller.rb

  def destroy
    log_out
    redirect_to root_url
  end

Bài viết này đã kết thúc demo về "Basic login" Ở bài viết sau, mình sẽ giới thiệu đến các kỹ thuật "Advance login"

Cảm ơn các bạn đã theo dõi bài viết này! Link tài liệu tham khảo: https://www.railstutorial.org/book/basic_login

0