2012-01-09 9 views
8

Tôi đang sử dụng Devise và dựa trên last_sign_in_at của mô hình người dùng để tìm hiểu xem khách hàng của tôi có không trả lại trong vòng X ngày hay không. Tuy nhiên, gần đây tôi đã phát hiện ra rằng last_sign_in_at chỉ được cập nhật khi sự kiện đăng nhập biểu mẫu thực tế xảy ra, trái ngược với thời điểm người dùng đăng nhập tự động do có thể nhớ được.Thiết lập: phương tiện có thể nhớ được rằng last_sign_in_at không được cập nhật theo dõi

Nếu muốn đảm bảo rằng last_sign_in_at được cập nhật mỗi lần người dùng đăng nhập (phiên trình duyệt mới), bất kể họ sử dụng biểu mẫu để đăng nhập hay tự động đăng nhập bằng cookie có thể nhớ được, tôi sẽ làm điều này theo cách tương thích với Devise?

Trả lời

5

Móc có thể theo dõi được từ móc Warden's after_set_user - những gì bạn có thể làm để dễ dàng khắc phục điều này được đặt trước_filter để gọi sign_in.

Điều này có thể được tối ưu hóa, nhưng thử nghiệm để xem nếu sử dụng

before_filter proc{ sign_in(current_user, :force => true) } 

cập nhật các dấu thời gian last_signed_in_at.

+1

khi nào thì before_filter được gọi? Tôi hy vọng không phải trên mỗi yêu cầu, và chỉ trên trước khi xác thực cho lần đầu tiên phiên họp đó? Ngoài ra, câu hỏi ngu ngốc, nhưng nơi nào tôi thêm before_filter? Tôi đã thử thêm nó vào mô hình người dùng Devise và tôi đã nhận được phương thức undefined before_filter. –

+0

Điều đó sẽ được chạy trên mỗi yêu cầu - đó chỉ là một bước gỡ lỗi nhanh/bẩn để xem liệu điều đó có giải quyết được trước khi thực hiện một giải pháp tốt hơn hay không. Bạn có thể thêm nó vào bất kỳ bộ điều khiển nào, ApplicationController nếu bạn muốn nó toàn cục. – RobH

+3

Hi Rob, đây là những gì tôi đã đi cho đến cuối mà a) kiểm tra rằng người dùng đã đăng nhập trước khi buộc một sign_in, và b) đảm bảo rằng phương thức sign_in (buộc) chỉ được thực thi một lần mỗi phiên.(xin lỗi; thay vì ngắt dòng, nhận xét không cho phép ngắt dòng) 'before_filter proc {if user_signed_in? && phiên [: logged_signin]; sign_in (current_user,: force => true); phiên [: logged_signin] = true; end} ' –

13

Lấy giải pháp Matthew, tôi nghĩ rằng mã nên được như sau (chú ý không-nhà điều hành trước khi phiên [: logged_signin]):

before_filter :update_last_sign_in_at 

protected 

def update_last_sign_in_at 
    if user_signed_in? && !session[:logged_signin] 
    sign_in(current_user, :force => true) 
    session[:logged_signin] = true 
    end 
end 
+0

Đây có phải là giải pháp tốt nhất chưa? –

+0

OK. Bạn đang sử dụng thông số cookie tùy chỉnh để kiểm tra xem đây có phải là phiên mới hoặc phiên hiện tại hay không. Cảm ơn cho tip, điều này cảm thấy giống như một cách tiếp cận sạch hơn nhiều trong trường hợp của tôi vì nó có nghĩa là tôi không phải đào sâu vào ruột của Devise. –

-1

AFAIK bạn cũng có thể sử dụng update_tracked_fields! vào đó current_user mô hình.

+0

'update_tracked_fields!' Nhận yêu cầu làm tham số. Kể từ khi ra đời cũng theo dõi IP. Chỉ cần làm điều này trong bộ điều khiển, 'current_user.update_tracked_fields! (Yêu cầu)'. –

2

Devise: rememberable means that last_sign_in_at is not updated by trackable

Mở rộng trên các giải pháp trước đó, vấn đề với họ sẽ là nếu người dùng đăng nhập bình thường, họ sẽ "đăng nhập hai lần". Điều này sẽ đặt last_sign_in_at thành cùng một giá trị (hoặc gần như giống nhau) là current_sign_in_at. Trên trang web của tôi, tôi sử dụng last_sign_in_at để cho người dùng biết điều gì đã xảy ra kể từ lần cuối họ ghé thăm trang web và vì vậy tôi cần nó có phần chính xác. Ngoài ra, nó ghi lại số lần đăng nhập +1.

Ngoài ra, có những người (như bản thân tôi), người rời khỏi cửa sổ trình duyệt mở cửa trong nhiều ngày mà không đóng cửa sổ (và do đó không bao giờ xóa cờ phiên). Đối với mục đích số liệu v.v., nó có thể hữu ích nếu hành vi của người dùng đôi khi làm mới thời gian current_sign_in_at.

Các biến thể dưới đây sẽ khắc phục những điều này.

class ApplicationController < ActionController::Base 
    before_filter :update_sign_in_at_periodically 
    UPDATE_LOGIN_PERIOD = 10.hours 

    protected 

    def update_sign_in_at_periodically 
    if !session[:last_login_update_at] or session[:last_login_update_at] < UPDATE_LOGIN_PERIOD.ago 
     session[:last_login_update_at] = Time.now 
     sign_in(current_user, :force => true) if user_signed_in? 
    end 
    end 
end 

Tuy nhiên, khi tôi cố gắng trên, sử dụng lập mưu 3.2.4, tôi có được một đăng nhập mới khi nó tự động đăng nhập bằng cookie (login-count +1 và current_sign_in_at được thiết lập). Vì vậy, tôi còn lại chỉ với vấn đề muốn theo dõi để cập nhật định kỳ ngay cả đối với người dùng giữ phiên mở.

class ApplicationController < ActionController::Base 
    before_filter :update_sign_in_at_periodically 
    UPDATE_LOGIN_PERIOD = 10.hours 

    protected 

    def update_sign_in_at_periodically 
    # use session cookie to avoid hammering the database 
    if !session[:last_login_update_at] or session[:last_login_update_at] < UPDATE_LOGIN_PERIOD.ago 
     session[:last_login_update_at] = Time.now 
     if user_signed_in? and current_user.current_sign_in_at < 1.minute.ago # prevents double logins 
     sign_in(current_user, :force => true) 
     end 
    end 
    end 
end