Series Hướng Dẫn Lập Trình Ruby on Rails (Phần 5)

Chào các bạn, hôm nay mình sẽ tiếp tục phần 5 của Series Hướng dẫn lập trình Ruby on Rails nhé. Ở phần trước chúng ta đã thực hiện project login_app hoàn thành bước đăng ký User, như vậy là trong db của chúng ta đã lưu thông tin User với namepassword bây giờ chúng ta sẽ xây dựng chức năng login sử dụng namepassword đã đăng ký để tiến hành đăng nhập nhé.

Để tạo một chức năng trên Web application sử dụng Ruby on Rails ta cần thực hiện các bước :

  • Tạo Model để lưu trữ dữ liệu, xử lý logic
  • Tạo Controller để thực hiện điều hướng, nhận dữ liệu từ Client.
  • Viết code phần View
  • Cấu hình file routes.rb để đảm bảo request từ Client sẽ gọi đúng Controller. Đây là các bước cơ bản để thực hiện code một chức năng cho Web Application, không chỉ đối với Ruby on Rails mà các bạn có thể áp dụng cho bất kỳ Framework nào khác nhé 😃

Để thực hiện chức năng Login ta sẽ đi lần lượt các bước trên nhé.

  • Đâu tiên tạo Model : vì đối với chức năng login ta sẽ sử dụng lại Model User nên không cần tạo thêm Model nữa nhé
  • Tạo Controller : Chúng ta sẽ tạo một controller có tên là Sessions để thực hiện chức năng Login rails g controller Session new
[email protected]:~/login_app$ rails g controller Sessions new
Running via Spring preloader in process 4603
Expected string default value for '--jbuilder'; got true (boolean)
Expected string default value for '--helper'; got true (boolean)
Expected string default value for '--assets'; got true (boolean)
      create  app/controllers/sessions_controller.rb
       route  get 'sessions/new'
      invoke  erb
      create    app/views/sessions
      create    app/views/sessions/new.html.erb
      invoke  test_unit
      create    test/controllers/sessions_controller_test.rb
      invoke  helper
      create    app/helpers/sessions_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/sessions.coffee
      invoke    scss
      create      app/assets/stylesheets/sessions.scss

Sau khi chạy lệnh trên action new và View app/views/sessions/new.html.erb sẽ được sinh ra cho chúng ta Chúng ta sẽ sử dụng View app/views/sessions/new.html.erb để làm page thực hiện Login nhé Thêm 2 action create : thực hiện việc login - lưu thông tin user vào session và action destroy : thực hiện việc logout - xóa thông tin user khỏi session

SessionsController của chúng ta sẽ thế này

class SessionsController < ApplicationController
  def new
  end

  def create
  end

  def destroy
  end
end
  • Tiếp theo chúng ta sẽ cấu hình file routes.rb để Client có thể request chức năng login/logout nhé Sau khi tạo controller trên thì mở file routes.rb ta sẽ có như bên dưới
Rails.application.routes.draw do
  get 'sessions/new'

  resources :users
end

resources :users là phần cấu hình mà ta đã thêm từ Phần 4 get 'sessions/new' là phần mà Rails đã tự thêm cho chúng ta sau khi chúng ta thực hiện lệnh rails g controller Session new Bật rails server lên và truy cập thử vào http://localhost:3000/sessions/new nhé Như vậy là ta đã có thể truy cập đến trang để thực hiện việc login mà không cần phải làm gì thêm, Rails rất tuyệt đúng không nào :v Có một điều lưu ý nhỏ ở đây là nhìn vào url http://localhost:3000/sessions/new phần sessions/new có vẻ khá là tối nghĩa và không thân thiện người dùng cho lắm đúng không nhỉ, ta sẽ thay phần sessions/new thành login để url của ta nhìn dễ hiểu và thân thiện người dùng hơn. Ta chỉnh trong file routes.rb như sau get "login" => "sessions#new" Truy cập vào http://localhost:3000/login và nó vẫn là trang session/new.html.erb cũ tuy nhiên url nhìn đã rất dễ hiểu hơn đúng không nào 😄 Tiếp theo ta thêm cấu hình path cho 2 action createdestroy

Rails.application.routes.draw do
  get     "login"    => "sessions#new"
  post    "login"    => "sessions#create"
  delete  "logout"   => "sessions#destroy"

  resources :users
end

Như vậy là đã xong phần cấu hình file routes.rb

Tiếp theo chũng ta sẽ viết code cho phần view trang login nhé app/views/sessions/new.html.erb

<div class="container">
  <div class="row">
    <h1 class="title">Login</h1>
  </div>
  <div class="row">
    <div class="col-lg-offset-3 col-lg-6">
      <%= form_for :session, url: login_path do |f| %>
        <div class="form-group">
          <%= f.label :name %>
          <%= f.text_field :name, placeholder: "Enter your name", class: "form-control" %>
        </div>
        <div class="form-group">
          <%= f.label :password %>
          <%= f.password_field :password, placeholder: "Enter your password",
            class: "form-control" %>
        </div>
        <div class="text-center">
          <%= f.submit "Login", class: "btn btn-info col-lg-12" %>
        </div>
        <div class="text-right">
          <%= link_to "Register", new_user_path %>
        </div>
      <% end %>
    </div>
  </div>
</div>

thêm chút css cho cái title Login app/assets/stylesheets/sessions.scss

.title {
  font-size: 70px;
  text-align: center;
  font-weight: bold;
  color: #BDBDBD;
}

Mình sẽ giải thích tại sao lại sử dụng <%= form_for :sesson, url: login_path do |f| %> mà không phải là <%= form_for @user do |f| %> như mình đã dùng đã lần trước, nguyên nhân ở đây là SessionsController không có Model và việc tạo Model cho nó cũng không cần thiết vì chúng ta đã có Model User chứa thông tin User cần thiết rồi, do đó ở đây chúng ta chỉ cần truyền thông dữ liệu đơn thuần lên SessionsController chứ không cần tạo mới bất cứ đối tượng nào nên chỉ cần như này là đủ <%= form_for :sesson, url: login_path do |f| %> chi tiết về sử dụng FormHelper và các thẻ Helper khác mình đã đề cập ở phần 4 các bạn xem lại nhé.

Giờ chúng ta sẽ có trang login như này : Nhìn có vẻ tạm tạm, giờ chúng ta sẽ viết code cho action create

  def create
    user = User.find_by name: params[:session][:name].downcase
    if user && user.authenticate(params[:session][:password])
      #TODO save user infor into session
    else
      flash[:danger] = "Invalid email/password combination"
      render :new
    end
  end

user.authenciate params[:session][:password] đây là hàm được cung cấp bởi has_secure_password, nó sẽ trả về false nếu tham số password cung cấp là sai. app/helpers/sessions_helper.rb tạo thêm phương thức thực hiện chức năng login

module SessionsHelper

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

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  include SessionsHelper
end

app/views/users/show.html.erb

<div class="container">
  <div class="row">
    <div class="col-lg-offset-3 col-lg-6">
      <div class="text-left">
        <label><%= @user.name %></label>
      </div>
      <%= link_to "Logout", logout_path, method: :delete %> 
    </div>
  </div>
</div>

app/controllers/users_controller.rb add thêm

  def show
    @user = User.find_by id: params[:id]
  end

app/controllers/sessions_controller.rb sẽ như này

class SessionsController < ApplicationController
  def new
  end

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

  def destroy
  end
end

OK mọi thứ đã xong bây giờ chúng ta sẽ đăng ký thử một tài khoản rồi sau đó login nhé 😄 Bật rails server vào http://localhost:3000/users/new Như vậy là chúng ta đã login thành công, bây giờ chúng ta sẽ viết code cho phần logout nhé app/helpers/sessions_helper.rb ta add thêm hàm log_out

  def log_out
    session.delete :user_id
  end

app/controllers/sessions_controller.rb

  def destroy
    log_out
    flash[:success] = "You are logged out"
    redirect_to login_path
  end

Kết quả

Như vậy là mình đã hướng dẫn các bạn xong phần login/logout tuy nhiên vẫn còn một vài điểm chưa hoàn thiện đó là khi user đã tiến hành login thì lần tiếp theo sẽ không cần Login lại nữa. Phần tới mình sẽ tiếp tục hướng dẫn các bạn phần này và sẽ mở rộng thêm một số chức năng cho login_app này nữa, hẹn các bạn kì tiếp nhé 😃


All Rights Reserved