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 đó:
newsẽ xử lý URL/loginvới phương thứcGET,kết quả trả về trang hiển thị form đăng nhậpcreatesẽ xử lý URL/loginvớ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ếnsessionrồi trả về trang/admin/indexnếu đúng, không thì quay về lại trang/login (GET).destroysẽ xử lý URL/logoutvớ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:

















