Trong phần này chúng ta sẽ tiếp tục xây dựng chức năng đăng nhập user.
Tạo controller
Đầu tiên chúng ta tạo 2 controller mới là sessions
và admin.
C:\Projects\Rails\depot>rails generate controller sessions new create destroy ... C:\Projects\Rails\depot>rails generate controller admin index ...
Controller sessions
sẽ có 3 phương thức là new, create
và destroy.
Trong đó:
new
sẽ xử lý URL/login
với phương thứcGET,
kết quả trả về trang hiển thị form đăng nhậpcreate
sẽ xử lý URL/login
với phương thứcPOST,
trong đó kiểm tra thông tin username và password do người dùng gửi lên có chính xác không, sau đó lưu lại trong biếnsession
rồi trả về trang/admin/index
nếu đúng, không thì quay về lại trang/login (GET).
destroy
sẽ xử lý URL/logout
với phương thứcDELETE
, mục đích là để hủy biến session, tức là chức năng đăng xuất, sau đó trả về trang chủ là'/'.
Controller admin
có một phương thức là index,
xử lý URL /admin/index
(GET),
phương thức này sẽ hiển thị một số câu thông báo đơn giản chứ chưa làm gì nhiều ở đây.
Xử lý quá trình đăng nhập
Chúng ta sửa lại file sessions_controller.rb
trong thư mục app/controllers
như sau:
class SessionsController < ApplicationController def new end def create if user = User.authenticate(params[:name], params[:password]) session[:user_id] = user.id redirect_to admin_url else redirect_to login_url, :alert => "Invalid username/password" end end def destroy session[:user_id] = nil redirect_to '/', :notice => "Logged out" end end
Phương thức new
để hiển thị form, chứ không xử lý gì cả nên chúng ta để không.
Phương thức create
sẽ kiểm tra xem người dùng có đăng nhập đúng không bằng cách gọi phương thức authenticate
trong lớp User
mà chúng ta đã làm trong bài trước. Nếu đúng thì chúng ta tạo một phần tử trong biến session
với key là :user_id
và value là user.id,
sau đó trả về trang 'admin/index'
có trong biến admin_url
. Nếu user đăng nhập sai thì chúng ta trả về lại trang /login,
kèm theo câu thông báo trong biến :alert
.
Phương thức destroy
sẽ xóa phần tử :user_id
trong biến session
, sau đó trả về trang '/'
, với câu thông báo trong biến :notice
.
Tạo form đăng nhập
Như đã nói, form này được phương thức new
trong lớp sessions_controller
hiển thị từ file new.html.erb
trong thư mục app/views/sessions
, chúng ta sửa lại file này như sau:
<div class="depot_form"> <% if flash[:alert] %> <p id="notice"><%= flash[:alert] %></p> <% end %> <% if notice %> <p id="notice"><%= notice %></p> <% end %> <%= form_tag '/login' do %> <fieldset> <legend>Log In</legend> <div> <label for="name">Name:</label> <%= text_field_tag :name, params[:name] %> </div> <div> <label for="password">Password:</label> <%= password_field_tag :password, params[:password] %> </div> <div> <%= submit_tag "Login" %> </div> </fieldset> <% end %> </div>
Chúng ta hiển thị form và câu thông báo từ biến :alert
nếu có (từ người dùng đã đăng nhập sai).
Khác với các phần trước là chúng ta tạo form từ model, tức là model có các trường gì thì chúng ta có thể tạo nhanh form cho model đó với phương thức helper là form_for.
Còn ở đây chúng ta đang tạo form riêng, không có model nào cả, do đó chúng ta dùng phương thức helper là form_tag
,
Phương thức form_tag có phương thức gửi mặc định là POST, URL mặc định là <tên_controller>/<tên_phương_thức>,
tức là form này được tạo trong file new.html.erb
(từ phương thức new
trong controller sessions
) thì mặc định URL gửi đi là /sessions/new
. Nhưng ở đây chúng ta dùng URL riêng là /login
luôn.
Bên trong chúng ta khai báo các trường bằng các phương thức helper khác như text_field_tag
dùng để tạo textbox, password_field_tag
dùng để tạo ô nhập password, submit_tag
tạo nút Submit. Khi sử dụng các phương thức này thì chúng ta phải tự khai báo các
id
và name.
Ngoài ra còn có rất nhiều các phương thức tạo nhanh form khác, bạn có thể xem tại đây.
Tạo trang admin/index
Ở đây trang /admin/index
sẽ chưa làm gì nhiều, chúng ta sẽ tùy chỉnh sau:
<h1>Welcome</h1> Time: <%= Time.now %> <br> There are <%= pluralize(@total_orders, "order") %>. <%= button_to 'Logout', '/logout', :method => :delete %>
Chúng ta cho hiển thị giờ hiện tại (trên máy tính) và tổng số lượng đơn hàng đã được tạo ra. Ở cuối trang là nút bấm dẫn đến URL '/logout'
với phương thức gửi là DELETE
.
Tổng số lượng đơn hàng được lấy từ biến @total_orders,
do đó chúng ta khai báo biến này trong controller như sau:
class AdminController < ApplicationController def index @total_orders = Order.count end end
Routing
Việc cần làm cuối cùng là phải tự tay điều hướng các URL mới vào các controller đã được tạo ở trên, bởi vì chúng ta tạo controller bằng tay chứ không được tạo tự động thông qua model như trước. Chúng ta sửa lại file config/routes.rb
như sau:
Rails.application.routes.draw do get 'admin/index' get 'sessions/new' get 'sessions/create' get 'sessions/destroy' resources :users resources :orders resources :line_items resources :carts get 'store/index' resources :products do get 'who_bought', :on => :member end root :to => 'store#index' get 'admin' => 'admin#index' controller :sessions do get 'login' => :new post 'login' => :create delete 'logout' => :destroy end end
Đối với trang /admin/index
thì chúng ta dùng phương thức get
rồi điều hướng vào phương thức index
trong controller admin.
Đối với các controller có nhiều phương thức xử lý thì chúng ta có thể định nghĩa chúng gộp chung trong khối lệnh controller...do...end.
Trong đó chúng ta cũng sử dụng các phương thức bình thường như get, post, delete,
phương thức gửi đến có thể để theo dạng symbol chứ không cần phải khai báo rõ ra thành chuỗi (như 'sessions#new'
hay 'sessions#create'
…) nữa.
Bây giờ chúng ta có thể trỏ vào trang /login
và đăng nhập được rồi.
Đăng nhập thành công:
Đăng xuất: