Rails – Session

3.7/5 - (48 votes)

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.

5 1 vote
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

8 Comments
Inline Feedbacks
View all comments
Anh
Anh
7 năm trước

cậu ơi, rails session trong safari của ios bị lỗi, cứ tắt tab đi vào lại là phải login mới nhận current_user, có cách nào để làm unlimited cookies k nhỉ.

Anh
Anh
7 năm trước
Reply to  Phở Code

uh, cho tớ hỏi thêm là, giờ tớ muốn tạo 1 phòng chat có attribute là password, để truy cập vào thì phải gõ mật khẩu, tớ bắt chước session như trong login user mà k được, cậu nhìn qua giúp t phát Routes get ‘rooms/:id/pass’, to: ‘rooms#pass’, as: :pass post ‘rooms/:id/pass’, to: ‘rooms#pass_login’ Controller def pass end def pass_login room = Room.find_by(email: params[:session][:email]) if room && User.find_by(name: params[:session][:name]) log_in_room_has_password(room) redirect_to room_path else flash[:danger] = ‘Invalid email/name combination’ # Not quite right! render ‘index’ end end Helper def log_in_room_has_password(room) session[:room_id] = room.id end def logged_room_in? !current_room_has_password.nil? end private def current_room_has_password… Đọc thêm »

Near
Near
7 năm trước

mình không hiểu chỗ Cart.find, method find được định nghĩa ở đâu vậy, trong class Cart mình tìm ko có.

Near
Near
7 năm trước
Reply to  Phở Code

làm sao để xem các phương thức của ActiveRecord vây ad