Series Hướng Dẫn Lập Trình Ruby on Rails (Phần 5)
Bài đăng này đã không được cập nhật trong 3 năm
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 name
và password
bây giờ chúng ta sẽ xây dựng chức năng login
sử dụng name
và password
đã đă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
minhduc@minhduc-K42F:~/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 create
và destroy
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