質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

1477閲覧

Railsでログイン、ログアウト時間を取得

on_off_on

総合スコア18

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

1クリップ

投稿2018/08/06 05:26

userテーブルを持つRailsアプリのユーザーひとりひとりと紐づける形で、毎日ログイン時間とログアウト時間を記録したい(一週間ごとくらいで消滅してもいい)んですが、どのような方法が適切なのか、そもそもどういったやりかたで取得したらいいのかがあまりつかめません。。。

ちなみにDeviseは使っていなくて、Sorceryというgemを使っています。

そしてFacebookでオンラインの人の横に緑の丸が出るみたいな感じで、ログイン状態の表示もしたいです。

それらを実現する方法として、

ログインテーブルみたいなのを作り、
・ユーザーID(userテーブルにあるもの。これで紐付けを行う。)
・IPアドレス(今回の件とは関係ないので気にしないでください。)
・ログイン時間
・ログアウト時間
・ログイン状態(enumで管理? 1:login 2:logout)
ログインが成功した時点でログインテーブルに1を入れて「1の時にオンラインであることを表示」という処理にする。

で、やろうと思っているんですが、

・これで適切なのかがわからないのと、
・ログイン、ログアウト時間の取得方法がわからない
・ログイン状態に関しては他にいいやり方はありそうか

というのが主な質問です。

その他指摘があればお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ログイン状態を履歴から取るのは良くないと思います、2つに分けるべきでしょう

  1. 最新の情報を取得するために無駄な処理が必要
  2. ログアウトせずブラウザを閉じた場合の対処が必要です、またそれはログ情報には不要

■1. ログイン状態に関して

gem sorceryには活動具合を記録してくれるモジュールがあるのでそれを適用するのはどうでしょう

https://github.com/Sorcery/sorcery/wiki/Activity-logging

ただし上のwikiにある current_users はgemでやることではないと既に削除されています

旧実装のソースと思わしき場所: lib/sorcery/adapters/mongoid_adapter.rb#L96

ログアウトしてないときは最終アクセス時刻からセッションタイムアウトの時間が過ぎるまでをログイン扱いにするなどの工夫をしているみたいですね
実際にどのような判定にするかは作るもの次第だと思いますが参考にどうぞ

■2. ログに関して

上記モジュールで各種の保存処理が増えています
https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/controller/submodules/activity_logging.rb

そのモジュールのタイミングに追記するような形で拡張するのはどうでしょう?

ruby

1class ApplicationController < ActionController::Base 2 protected 3 def register_login_time_to_db(user, credentials) 4 super(user, credentials) 5 user.login_logs.create(login_at: user.last_login_at) 6 end 7 8 # ログインせずに閉じるとここが動かないので、ログで未ログアウトとして残る 9 def register_logout_time_to_db 10 super 11 user.login_logs 12 .find_by(login_at: user.last_login_at) 13 .update(logout_at: user.last_logout_at) 14 end 15end

また「一週間ごとくらいで消滅してもいい」というより別途バッチ処理等で意図して古いのは消すべきでしょう
ログ情報をDBに貯め続けるのはあまり良い仕組みではありません

投稿2018/08/06 06:27

Ighrs

総合スコア656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

on_off_on

2018/08/07 06:38 編集

丁寧に回答していただきありがとうございます。 一度試してみます。 ところで credentialsの正体がわからないです。。 すみません、 credential_regexメソッドなどを読み込んで見ても、他の読み込まれてるモジュールを辿って見ても credentialが一体どこからきてるのかさっぱりわからず... 調べてみても今回の実装とは関係ないような気がして....。
Ighrs

2018/08/08 00:40

関係ありませんが関数を上書きして super で本来の処理に流すためには同じ引数である必要があります、ただそれだけの物であって本筋ではないので気にしなくて良いですよ
on_off_on

2018/08/08 00:45

おお、ありがとうございます!
on_off_on

2018/08/10 00:37 編集

たびたびすみません。。 user.login_logsのlogin_logsはログを残す用のテーブルだと思うんですが、その前ついてるuserとはなんのことでしょうか...? undefined local variable or method `user'となってしまいます。。。 user_logsテーブルを作ったので少し変えてますが、 ------------------------------------------------------------------------ class ApplicationController < ActionController::Base protect_from_forgery with: :exception protected def register_login_time_to_db(user, credentials) super(user, credentials) user.user_logs.create(login_at: user.last_login_at) end # ログインせずに閉じるとここが動かないので、ログで未ログアウトとして残る def register_logout_time_to_db super user.user_logs .find_by(login_at: user.last_login_at) .update(logout_at: user.last_logout_at) end end -------------------------------------------------------------------- また、いただいた案とは別に、こんな感じで書いてみましたが、 undefined method `user_logs’ for nil:NilClass となってしまいました -------------------------------------------------------------------------------- class SessionsController < ApplicationController def new end def create user = login(params[:username], params[:password]) if user #TODO: ここに処理を書く @user_log = @user.user_logs.create(user_id: @user.id, login_at: @user.last_login_at) redirect_back_or_to user_path(user) else render :new end end def destroy logout #TODO: ここに処理を書く @user_log = @user.user_logs.create(user_id: @user.id,logout_at: @user.last_logout_at) redirect_to root_path end end ----------------------------------------------------------------------------- こんな感じになりました。
Ighrs

2018/08/10 02:43

userとlogin_logs を has_many で繋げていると繋がる値である user_id を省略して書けますよ LoginLog.create(user_id: user.id, logind_at: ***) もしくは user.login_logs.create(login_at: ***) のどちらかですね、userから繋げた場合に user_id を指定する必要はありません なので has_many で繋げないなら普通にLoginLogクラスの関数を使えば大丈夫です
on_off_on

2018/08/10 05:55 編集

ありがとうございます。 この場合  has_manyで繋げて教えていただいたようにやると You have incorrectly defined user_class or have forgotten to define it in intitializer file というエラーが出ます。 https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/controller.rb ここの160行目以降に関係している感じですが、まったく対処法がわからないです...... ---------------------------------------------------------------------- class SessionsController < ApplicationController def new end def create user = login(params[:username], params[:password]) if user #TODO: ここに処理を書く user.user_logs.create(login_at: last_login_at) redirect_back_or_to user_path(user) else render :new end end def destroy logout #TODO: ここに処理を書く user.user_logs.create(logout_at: last_logout_at) redirect_to root_path end end ---------------------------------------------------------------------- もしよろしければ回答かヒントをいただけると助かります。 インデントなくてみづらいですね。。すみません。。
guest

0

ruby

1require "date" 2DateTime.now

でその時点での日時を取得できます。

投稿2018/08/06 05:31

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

on_off_on

2018/08/06 06:36

前の質問に引き続き回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問