Add devise_lastseenable for user last seen tracking.

Adds a timestamp to user model which is touched when user comes back. Statistics active users counts now use these more reliable timestamps. Fixes #4734
This commit is contained in:
Jason Robinson 2014-02-22 23:22:46 +02:00
parent f54931c813
commit 5fe5507128
7 changed files with 43 additions and 19 deletions

View file

@ -15,6 +15,7 @@
## Bug fixes ## Bug fixes
* Improve time agos by updating the plugin [#4280](https://github.com/diaspora/diaspora/issues/4280) * Improve time agos by updating the plugin [#4280](https://github.com/diaspora/diaspora/issues/4280)
* Do not add a space after adding a mention [#4767](https://github.com/diaspora/diaspora/issues/4767) * Do not add a space after adding a mention [#4767](https://github.com/diaspora/diaspora/issues/4767)
* Fix active user statistics by saving a last seen timestamp for users [#4734](https://github.com/diaspora/diaspora/issues/4734)
## Features ## Features
* You can report a single post by clicking the correct icon in the controler section [#4517](https://github.com/diaspora/diaspora/pull/4517) * You can report a single post by clicking the correct icon in the controler section [#4517](https://github.com/diaspora/diaspora/pull/4517)

View file

@ -14,6 +14,7 @@ gem 'json', '1.8.1'
# Authentication # Authentication
gem 'devise', '3.2.2' gem 'devise', '3.2.2'
gem 'devise_lastseenable', '0.0.4'
# Captcha # Captcha

View file

@ -103,6 +103,13 @@ GEM
railties (>= 3.2.6, < 5) railties (>= 3.2.6, < 5)
thread_safe (~> 0.1) thread_safe (~> 0.1)
warden (~> 1.2.3) warden (~> 1.2.3)
devise_lastseenable (0.0.4)
devise
devise
rails (>= 3.0.4)
rails (>= 3.0.4)
warden
warden
diff-lcs (1.2.5) diff-lcs (1.2.5)
eco (1.0.0) eco (1.0.0)
coffee-script coffee-script
@ -460,6 +467,7 @@ DEPENDENCIES
cucumber-rails (= 1.4.0) cucumber-rails (= 1.4.0)
database_cleaner (= 1.2.0) database_cleaner (= 1.2.0)
devise (= 3.2.2) devise (= 3.2.2)
devise_lastseenable (= 0.0.4)
entypo-rails entypo-rails
factory_girl_rails (= 4.3.0) factory_girl_rails (= 4.3.0)
faraday (= 0.8.9) faraday (= 0.8.9)

View file

@ -10,7 +10,7 @@ class User < ActiveRecord::Base
apply_simple_captcha :message => I18n.t('simple_captcha.message.failed'), :add_to_base => true apply_simple_captcha :message => I18n.t('simple_captcha.message.failed'), :add_to_base => true
scope :logged_in_since, lambda { |time| where('last_sign_in_at > ?', time) } scope :logged_in_since, lambda { |time| where('last_seen > ?', time) }
scope :monthly_actives, lambda { |time = Time.now| logged_in_since(time - 1.month) } scope :monthly_actives, lambda { |time = Time.now| logged_in_since(time - 1.month) }
scope :daily_actives, lambda { |time = Time.now| logged_in_since(time - 1.day) } scope :daily_actives, lambda { |time = Time.now| logged_in_since(time - 1.day) }
scope :yearly_actives, lambda { |time = Time.now| logged_in_since(time - 1.year) } scope :yearly_actives, lambda { |time = Time.now| logged_in_since(time - 1.year) }
@ -18,7 +18,7 @@ class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :recoverable, :rememberable, :trackable, :validatable,
:lockable, :lock_strategy => :none, :unlock_strategy => :none :lockable, :lastseenable, :lock_strategy => :none, :unlock_strategy => :none
before_validation :strip_and_downcase_username before_validation :strip_and_downcase_username
before_validation :set_current_language, :on => :create before_validation :set_current_language, :on => :create

View file

@ -0,0 +1,12 @@
class DeviseAddLastseenableUser < ActiveRecord::Migration
def self.up
add_column :users, :last_seen, :datetime
User.find_each do |user|
user.update_column(:last_seen, user.last_sign_in_at)
end
end
def self.down
remove_column :users, :last_seen
end
end

View file

@ -11,7 +11,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20131213171804) do ActiveRecord::Schema.define(:version => 20140222162826) do
create_table "account_deletions", :force => true do |t| create_table "account_deletions", :force => true do |t|
t.string "diaspora_handle" t.string "diaspora_handle"
@ -493,6 +493,7 @@ ActiveRecord::Schema.define(:version => 20131213171804) do
t.integer "auto_follow_back_aspect_id" t.integer "auto_follow_back_aspect_id"
t.text "hidden_shareables" t.text "hidden_shareables"
t.datetime "reset_password_sent_at" t.datetime "reset_password_sent_at"
t.datetime "last_seen"
end end
add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token", :unique => true add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token", :unique => true

View file

@ -48,64 +48,64 @@ describe User do
end end
describe 'yearly_actives' do describe 'yearly_actives' do
it 'returns list which includes users who latest signed in within last year' do it 'returns list which includes users within last year' do
user = FactoryGirl.build(:user) user = FactoryGirl.build(:user)
user.last_sign_in_at = Time.now - 1.month user.last_seen = Time.now - 1.month
user.save user.save
User.yearly_actives.should include user User.yearly_actives.should include user
end end
it 'returns list which does not include users who did not sign in within last year' do it 'returns list which does not include users seen within last year' do
user = FactoryGirl.build(:user) user = FactoryGirl.build(:user)
user.last_sign_in_at = Time.now - 2.year user.last_seen = Time.now - 2.year
user.save user.save
User.yearly_actives.should_not include user User.yearly_actives.should_not include user
end end
end end
describe 'monthly_actives' do describe 'monthly_actives' do
it 'returns list which includes users who latest signed in within last month' do it 'returns list which includes users seen within last month' do
user = FactoryGirl.build(:user) user = FactoryGirl.build(:user)
user.last_sign_in_at = Time.now - 1.day user.last_seen = Time.now - 1.day
user.save user.save
User.monthly_actives.should include user User.monthly_actives.should include user
end end
it 'returns list which does not include users who did not sign in within last month' do it 'returns list which does not include users seen within last month' do
user = FactoryGirl.build(:user) user = FactoryGirl.build(:user)
user.last_sign_in_at = Time.now - 2.month user.last_seen = Time.now - 2.month
user.save user.save
User.monthly_actives.should_not include user User.monthly_actives.should_not include user
end end
end end
describe 'daily_actives' do describe 'daily_actives' do
it 'returns list which includes users who latest signed in within last day' do it 'returns list which includes users seen within last day' do
user = FactoryGirl.build(:user) user = FactoryGirl.build(:user)
user.last_sign_in_at = Time.now - 1.hour user.last_seen = Time.now - 1.hour
user.save user.save
User.daily_actives.should include(user) User.daily_actives.should include(user)
end end
it 'returns list which does not include users who did not sign in within last day' do it 'returns list which does not include users seen within last day' do
user = FactoryGirl.build(:user) user = FactoryGirl.build(:user)
user.last_sign_in_at = Time.now - 2.day user.last_seen = Time.now - 2.day
user.save user.save
User.daily_actives.should_not include(user) User.daily_actives.should_not include(user)
end end
end end
describe 'halfyear_actives' do describe 'halfyear_actives' do
it 'returns list which includes users who latest signed in within half a year' do it 'returns list which includes users seen within half a year' do
user = FactoryGirl.build(:user) user = FactoryGirl.build(:user)
user.last_sign_in_at = Time.now - 4.month user.last_seen = Time.now - 4.month
user.save user.save
User.halfyear_actives.should include user User.halfyear_actives.should include user
end end
it 'returns list which does not include users who did not sign in within the last half a year' do it 'returns list which does not include users seen within the last half a year' do
user = FactoryGirl.build(:user) user = FactoryGirl.build(:user)
user.last_sign_in_at = Time.now - 7.month user.last_seen = Time.now - 7.month
user.save user.save
User.halfyear_actives.should_not include user User.halfyear_actives.should_not include user
end end
@ -1000,6 +1000,7 @@ describe User do
auto_follow_back_aspect_id auto_follow_back_aspect_id
unconfirmed_email unconfirmed_email
confirm_email_token confirm_email_token
last_seen
}.sort }.sort
end end
end end