Daily Archives: 19/11/2016

Rails – Session

Session là được hiểu 1 phiên làm việc trong đó người sử dụng giao tiếp với 1 ứng dụng. Session bắt đầu khi người sử dụng truy cập vào ứng dụng lần đầu tiên, và kết thúc khi người sử dụng thoát khỏi ứng dụng.

Khi người dùng xem các sản phẩm trên một website bán hàng, có thể họ sẽ muốn mua nó, do đó chúng ta sẽ xây dựng tính năng giỏ hàng để lưu trữ các sản phẩm mà khách hàng muốn mua trong session.

Chúng ta sẽ định nghĩa một model cart (giỏ hàng), mỗi khi có người dùng nào truy cập vào website thì chúng ta sẽ tạo một đối tượng cart rồi lưu vào CSDL. Khi người dùng thoát trang web, sau đó quay lại thì chúng ta sẽ kiểm tra trong session của họ có id của cart nào hay không, nếu có thì lấy ra hiển thị, không thì lại tạo mới như ban đầu.

Đầu tiên chúng ta tạo model như sau:

C:\Projects\Rails\depot>rails generate scaffold cart
...

Chúng ta không định nghĩa cột nào ở đây cả vì sau này chúng ta sẽ liên kết với các model khác là đủ.

Tiếp theo chúng ta chạy lệnh rake db:migrate để Rails tạo bảng carts trong CSDL:

C:\Projects\Rails\depot>rake db:migrate
== 20161119034946 CreateCarts: migrating ==============================================
-- create_table(:carts)
   -> 0.0182s
== 20161119034946 CreateCarts: migrated (0.0194s)======================================

Nếu bạn còn nhớ thì Rails sẽ tự động tạo 3 trường là id,  created_atupdated_at:

C:\Projects\Rails\depot\db>sqlite3 development.sqlite3
> pragma table_info(carts);
0|id|INTEGER|1|1
1|created_at|datetime|1|0
2|updated_at|datetime|1|0

Tất cả các lớp controller do Rails tạo ra đều được kế thừa từ lớp ApplicationController (trong file app/controllers/application_controller.rb), lớp này cũng là một lớp do Rails tự tạo ra và được kế thừa từ lớp ActionController::Base, trong mỗi lớp controller bất kỳ có một đối tượng toàn cục có tên là session thuộc lớp ActionDispatch::Request::Session, đây là một lớp lưu trữ dữ liệu theo dạng từ điển, tức là cứ mỗi phần tử trong này sẽ bao gồm một cặp <khóa>-<giá trị>.

Bây giờ chúng ta sửa lại file application_controller.rb như sau:

class ApplicationController < ActionController::Base
    # Prevent CSRF attacks by raising an exception.
    # For APIs, you may want to use :null_session instead.
    protect_from_forgery with: :exception
 
    private
    
    def current_cart
        Cart.find(session[:cart_id])
    rescue ActiveRecord::RecordNotFound
        cart = Cart.create
        session[:cart_id] = cart.id
        cart
    end
end

Ở đây chúng ta định nghĩa một phương thức có tên current_cart dùng để lấy thuộc tính id của đối tượng Cart trong đối tượng session của người dùng khi người dùng truy cập vào website. Chúng ta chỉ định phương thức này có phạm vi truy xuất là private.

Đầu tiên chúng ta tìm xem trong CSDL có giỏ hàng nào có id giống với phần tử có khóa là :cart_id trong session hay không bằng phương thức Cart.find(), nếu không có thì phương thức này sẽ giải phóng một exception là ActiveRecord::RecordNotFound, chúng ta bắt lỗi này và thực hiện tạo một đối tượng Cart mới, sau đó tạo một phần tử trong đối tượng session với khóa là :cart_id và giá trị là id mới vừa được tạo (thuộc tính idcart.id).

Ngoài các lớp controller thì một khu vực khác cũng có thể đọc/ghi dữ liệu với đối tượng session là View, chúng ta sẽ xử lý session với View trong các bài sau.