2011-06-22 31 views
5

Tôi gặp sự cố khi hiểu việc triển khai "Ghi nhớ" trong Hướng dẫn Ruby on Rails của Michael Hartl. Ông tạo ra một mô-đun SessionsHelper với phương pháp để đăng nhập, chứa những điều sau đây:Đường ray - khả năng "nhớ tôi"

module SessionsHelper 

    def sign_in(user) 
     cookies.permanent.signed[:remember_token] = [user.id, user.salt] 
     current_user = user 
    end 

    def current_user=(user) 
     @current_user = user 
    end 

    def current_user 
     return @current_user ||= user_from_remember_token 
    end 

    private 
     def user_from_remember_token 
      #passes array of length two as a parameter -- first slot contains ID, 
      #second contains SALT for encryption 
      User.authenticate_with_salt(*remember_token) 
     end 

     def remember_token 
      #ensures return of a double array in the event that 
      #cookies.signed[:remember_token] is nil. 
      cookies.signed[:remember_token] || [nil,nil] 
     end 

end 

LƯU Ý: Cácauthenticate_with_saltphương pháp trong mô hình tài phát hiện người sử dụng bởi tham số đầu tiên (id) và nếu người dùng là xác định và muối của nó tương đương với tham số thứ hai (muối) sau đó người dùng được trả về, nếu không thì không được trả về.

tôi đang gặp khó khăn tìm hiểu lý do tại sao chúng tôi đi đến độ dài như vậy để kiểm tra nếu người dùng đã được đăng nhập:

Trong trường hợp mà người dùng đang đăng nhập, @current_user đã được xác định theo phương pháp sign_in và do đó || = trong phương thức current_user là vô nghĩa.

Trong trường hợp người dùng chưa đăng nhập, toán tử || = trong phương thức current_user trả về giá trị được trả về theo phương pháp user_from_remember_token, nhưng vì cookie.signed [: remember_token] sẽ là không, User.authenticate_with_salt sẽ được chuyển đối số [nil, nil] và sẽ trả về nil, và do đó, phương thức current_user sẽ trả về nil.

Nói tóm lại, nếu phương pháp current_user đang trở lại @current_user nếu nó được định nghĩa và nil nếu không nó sẽ không được đơn giản hơn nhiều để chỉ cần sử dụng các phương pháp accessor thông thường:

def current_user 
    return @current_user 
end 

cuốn sách Michael Hartl cho biết rằng làm điều này sẽ vô dụng vì trạng thái đăng nhập của người dùng sẽ bị lãng quên. Tại sao điều đó lại xảy ra? Ai đó có thể vui lòng giải thích lý do tại sao chúng tôi không làm điều này và thay vào đó sử dụng phiên bản phức tạp hơn được đăng ở trên?

Trả lời

2

Dòng

return @current_user ||= user_from_remember_token 

là một hình thức khởi tạo lười biếng để tránh khởi tạo biến @current_user cho đến khi nó thực sự là cần thiết. @current_user sẽ không bao giờ được khởi tạo lần đầu tiên chức năng này được gọi, nhưng nó sẽ có giá trị trên mỗi cuộc gọi liên tiếp (giả sử user_from_remember_token trả về một số khác không phải là nil).

Ông có thể viết

def current_user 
    return user_from_remember_token 
end 

Mã này sẽ luôn luôn khởi tạo người dùng hiện tại để bất cứ điều gì nó đọc từ cookie. Điều này sẽ hành xử một cách chính xác, nhưng anh ta có thể muốn tránh lặp đi lặp lại đọc cookie, vì vậy anh ta làm điều đó một lần và lưu trữ nó trong một biến.

Ông không thể làm

def current_user 
    return @current_user 
end 

vì biến @current_user không tồn tại trên yêu cầu trang. Sau khi trang hiển thị và được gửi lại cho máy khách, biến @current_user bị hủy và giá trị của nó bị lãng quên.

Hy vọng điều này sẽ hữu ích. Xem xét việc duy trì trạng thái trong các ứng dụng web để biết thêm thông tin về lý do tại sao cần phải nhảy qua các vòng lặp này.

2

sign_in chỉ được gọi khi bạn thực sự đăng nhập bằng biểu mẫu đăng nhập. Sau đó, bạn phải đặt người dùng hiện tại sử dụng các giá trị cookie cho mỗi yêu cầu.

Vì vậy, khi người dùng đăng nhập và mở trang, lần đầu tiên current_user được gọi là nó sẽ điền biến số @current_user và sử dụng nó cho các cuộc gọi tiếp theo current_user.

+0

Nhưng một khi @current_user được đặt bởi sign_in, có phải nó ở đó không? Giống như tại sao chúng ta không thể sử dụng một biến thể hiện @current_user thay vì một cookie? Sự khác biệt chính giữa chúng là gì? – Kvass

+0

Giống như câu trả lời của Michael Venable cho biết: "@current_user variable không tồn tại trên các yêu cầu trang". Vì vậy, lần đầu tiên bạn đang sử dụng phương thức 'current_user' trong một yêu cầu trang, bạn cần lấy thông tin người dùng từ cookie. – vesan

Các vấn đề liên quan