私は自分のコードにいくつかの変更を加えることになりました。私はそれが何をするかを説明し、私が終わったとき、私はなってしまったものを紹介します:これらは私が行った変更されている
class SessionTimeoutController < ApplicationController
# These are what prevent check_time_until_logout and
# reset_user_clock from resetting users' Timeoutable
# Devise "timers"
prepend_before_action :skip_timeout, only: [:check_time_until_logout, :has_user_timed_out]
def skip_timeout
request.env["devise.skip_trackable"] = true
end
skip_before_filter :authenticate_user!, only: [:has_user_timed_out]
def check_time_until_logout
@time_left = Devise.timeout_in - (Time.now - user_session["last_request_at"]).round
end
def has_user_timed_out
@has_timed_out = (!current_user) or (current_user.timedout? (user_session["last_request_at"]))
end
def reset_user_clock
# Receiving an arbitrary request from a client automatically
# resets the Devise Timeoutable timer.
head :ok
end
end
:
env["devise.skip_trackable"]
を使用してこれがコードです
prepend_before_action :skip_timeout, only: [:check_time_until_logout, :has_user_timed_out]
def skip_timeout
request.env["devise.skip_trackable"] = true
end
これを:それはそれは不活動によるアウトをユーザーにログインする前に待機する時間をリセットするから工夫を防止しますコードは、ユーザーが最後に活動したときに追跡するために保存する値を更新するかどうかを決定するために、Deviseが内部的に使用するハッシュ値を変更します。具体的には、これは我々が(link)と相互に作用している工夫コードです:
Warden::Manager.after_set_user do |record, warden, options|
scope = options[:scope]
env = warden.request.env
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
last_request_at = warden.session(scope)['last_request_at']
if record.timedout?(last_request_at) && !env['devise.skip_timeout']
warden.logout(scope)
if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
record.reset_authentication_token!
end
throw :warden, :scope => scope, :message => :timeout
end
unless env['devise.skip_trackable']
warden.session(scope)['last_request_at'] = Time.now.utc
end
end
end
(このコードはRailsは、クライアントからの要求を処理するたびに実行されることに注意してください。)
近くこれらの行
unless env['devise.skip_trackable']
warden.session(scope)['last_request_at'] = Time.now.utc
end
これは、ユーザーが非アクティブなためにログアウトするまでカウントダウンを「リセット」するコードです。 env['devise.skip_trackable']
がtrue
でない場合にのみ実行されるため、Deviseがユーザーの要求を処理する前にその値を変更する必要があります。
これを行うには、何かをする前にenv['devise.skip_trackable']
の値を変更するようにRailsに指示します。ここでも、私の最終的なコードから:この点以上の
prepend_before_action :skip_timeout, only: [:check_time_until_logout, :has_user_timed_out]
def skip_timeout
request.env["devise.skip_trackable"] = true
end
すべてが、私は私の質問に答えるために変更するために必要なものです。しかし、私が望むようにコードを動作させるために必要ないくつかの変更がありましたので、ここでもそれらを説明します。私の質問の私のコードは、カップル、他の問題を抱えているようTimeoutable
正しく
を使用して
私は、Timeoutable
モジュールに関するドキュメントを読み違えます。
まず、私のcheck_time_until_logout
メソッドは常に同じ値を返します。これは私が持っていたアクションの誤ったバージョンです:
def check_time_until_logout
@time_left = current_user.timeout_in
end
私は、ユーザーが自動的にログアウトされるまでTimeoutable#timeout_in
は時間の量を返すだろうと思いました。代わりに、ユーザーをログアウトする前にDeviseが待機するように構成されている時間を返します。ユーザーがどれくらい長く自分を去ったかを計算する必要があります。
これを計算するには、ユーザーが最後にDeviseが認識したアクティビティがいつあったかを知る必要があります。このコードは、我々は上記の見工夫ソースから、ユーザーが最後にアクティブだったときに決定されます。私たちはwarden.session(scope)
によって返されたオブジェクトへのハンドルを取得する必要があり
last_request_at = warden.session(scope)['last_request_at']
。これは、ハンドルcurrent_user
とuser_signed_in?
のように、Deviseが私たちに提供するuser_session
ハッシュのようなものです。
user_session
ハッシュを使用し、自分自身を残り時間を算出する、check_time_until_logout
方法は私もTimeoutable#timedout?
のドキュメントを読み違え
def check_time_until_logout
@time_left = Devise.timeout_in - (Time.now - user_session["last_request_at"]).round
end
なります。ユーザーが最後にアクティブだった時間に渡すときにユーザーがタイムアウトしたかどうかを確認するために、は現在時刻を渡すときにではありません。私たちが作る必要がある変更は簡単です:私はこれらの3つの変更を行ったら、私のコントローラは、私はそれを期待する方法を務めた
def has_user_timed_out
@has_timed_out = (!current_user) or (current_user.timedout? (user_session["last_request_at"]))
end
:代わりにTime.now
に渡すので、私たちはuser_session
ハッシュの時間に渡す必要があります。
良い答え、コードサンプルありがとう!レール4.2.6でこのコードを使用し、3.5.6を考案しましたが、修正するためにいくつかのエラーがありました。 'NoMethodError Exception:未定義のメソッド' - @ ''は、@time_left = Devise.timeout_in - (Time.now - user_session [" last_request_at "])のroundを' @time_left = Devise.timeout_in - (Time。 to_i' – Cameron
'@has_timed_out =(!current_user)または(current_user.timedout?)という行を変更すると、' ArgumentError Exception:ActiveSupport :: TimeWithZoneとのFixnumの比較に失敗しました 'というエラーが修正されました。 – Cameron
クライアントにアラートメッセージを送信する方法(user_session ["last_request_at"])) '' @has_timed_out =(!current_user)または(current_user.timedout?(Time.at(user_session ["last_request_at"])))前にタイムアウトを工夫しますか? –