sufia-models 4.2.0 → 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1400794c267e0bde112c7a4668b7ee6e06e9b327
4
- data.tar.gz: 298a15cf5c6e769a2526d81cbb815916d5fe3630
3
+ metadata.gz: c4b6c01683739e17c53f491882eb8c50ead27577
4
+ data.tar.gz: 2b780079c2b52e9f076df2e50e61835bc1f3ab2a
5
5
  SHA512:
6
- metadata.gz: f112d21ca35fef090bbe579b096d758eb17e4c592bc16c40f7f4a2a94c646e9859ce733aadeb9580acacee22495934eed3f764e14701068c2c772fe142a299dc
7
- data.tar.gz: 6b8047750da470d340a0a985a3ffdd722b2a09dc6ecf04da43eed32c18e8b9559abaf3a44152144d83bc12d0dfbe01db16a73eaeb4e69b1c346397bb26ca09c9
6
+ metadata.gz: 8fdfc3fdd81834097e68d9180cd860edb2f9813226532dd6fe06d643dddce743513556fb1a5f1af7e6bae93a662d6438ab0a6ef25d7521569127c4fcb321a489
7
+ data.tar.gz: 3249a331ab148fad1979b43b27fee9bf56ef1299061fde4f4ac0489effb9bee1a4d8357464de85350b2b78996d5f9e584565ffca94da43628b44405f895b3c7a
@@ -17,13 +17,13 @@ module Sufia
17
17
  {ga_start_date: ga_start_date, cached_stats: stats.to_a }
18
18
  end
19
19
 
20
- def combined_stats file_id, start_date, object_method, ga_key
20
+ def combined_stats file_id, start_date, object_method, ga_key, user_id=nil
21
21
  stat_cache_info = cached_stats( file_id, start_date, object_method)
22
22
  stats = stat_cache_info[:cached_stats]
23
23
  if stat_cache_info[:ga_start_date] < Date.today
24
24
  ga_stats = ga_statistics(stat_cache_info[:ga_start_date], file_id)
25
25
  ga_stats.each do |stat|
26
- lstat = self.new file_id:file_id, date: stat[:date], object_method => stat[ga_key]
26
+ lstat = self.new file_id: file_id, date: stat[:date], object_method => stat[ga_key], user_id: user_id
27
27
  lstat.save unless Date.parse(stat[:date]) == Date.today
28
28
  stats << lstat
29
29
  end
@@ -32,4 +32,4 @@ module Sufia
32
32
  end
33
33
 
34
34
  end
35
- end
35
+ end
@@ -18,33 +18,50 @@ module Sufia::User
18
18
  # Users should be followable
19
19
  acts_as_followable
20
20
 
21
- # Setup accessible (or protected) attributes for your model
21
+ # Set up proxy-related relationships
22
22
  has_many :proxy_deposit_requests, foreign_key: 'receiving_user_id'
23
-
24
23
  has_many :deposit_rights_given, foreign_key: 'grantor_id', class_name: 'ProxyDepositRights', dependent: :destroy
25
24
  has_many :can_receive_deposits_from, through: :deposit_rights_given, source: :grantee
26
-
27
25
  has_many :deposit_rights_received, foreign_key: 'grantee_id', class_name: 'ProxyDepositRights', dependent: :destroy
28
26
  has_many :can_make_deposits_for, through: :deposit_rights_received, source: :grantor
29
27
 
28
+ # Validate and normalize ORCIDs
29
+ validates_with OrcidValidator
30
+ after_validation :normalize_orcid
31
+
32
+ # Set up user profile avatars
30
33
  mount_uploader :avatar, AvatarUploader, mount_on: :avatar_file_name
31
34
  validates_with AvatarValidator
35
+
32
36
  has_many :trophies
33
37
  attr_accessor :update_directory
34
38
  end
35
39
 
40
+ # Coerce the ORCID into URL format
41
+ def normalize_orcid
42
+ # Skip normalization if:
43
+ # 1. validation has already flagged the ORCID as invalid
44
+ # 2. the orcid field is blank
45
+ # 3. the orcid is already in its normalized form
46
+ return if self.errors[:orcid].first.present? || self.orcid.blank? || self.orcid.starts_with?('http://orcid.org/')
47
+ bare_orcid = /\d{4}-\d{4}-\d{4}-\d{4}/.match(self.orcid).string
48
+ self.orcid = "http://orcid.org/#{bare_orcid}"
49
+ end
50
+
36
51
  # Format the json for select2 which requires just an id and a field called text.
37
52
  # If we need an alternate format we should probably look at a json template gem
38
53
  def as_json(opts = nil)
39
- {id: user_key, text: display_name ? "#{display_name} (#{user_key})" : user_key}
54
+ { id: user_key, text: display_name ? "#{display_name} (#{user_key})" : user_key }
40
55
  end
41
56
 
42
57
  def email_address
43
- return self.email
58
+ self.email
44
59
  end
45
60
 
46
61
  def name
47
- return self.display_name.titleize || self.user_key rescue self.user_key
62
+ self.display_name.titleize || raise
63
+ rescue
64
+ self.user_key
48
65
  end
49
66
 
50
67
  # Redefine this for more intuitive keys in Redis
@@ -61,7 +78,7 @@ module Sufia::User
61
78
 
62
79
  # method needed for messaging
63
80
  def mailboxer_email(obj=nil)
64
- return nil
81
+ nil
65
82
  end
66
83
 
67
84
  # The basic groups method, override or will fallback to Sufia::Ldap::User
@@ -85,7 +102,9 @@ module Sufia::User
85
102
  [:email, :login, :display_name, :address, :admin_area,
86
103
  :department, :title, :office, :chat_id, :website, :affiliation,
87
104
  :telephone, :avatar, :group_list, :groups_last_update, :facebook_handle,
88
- :twitter_handle, :googleplus_handle, :linkedin_handle, :remove_avatar]
105
+ :twitter_handle, :googleplus_handle, :linkedin_handle, :remove_avatar,
106
+ :orcid
107
+ ]
89
108
  end
90
109
 
91
110
  def current
@@ -119,7 +138,5 @@ module Sufia::User
119
138
  def from_url_component(component)
120
139
  User.find_by_user_key(component.gsub(/-dot-/, '.'))
121
140
  end
122
-
123
141
  end
124
-
125
142
  end
@@ -0,0 +1,15 @@
1
+ module Sufia::UserUsageStats
2
+
3
+ def stats
4
+ @stats ||= UserStat.where(user_id: id).order(date: :asc)
5
+ end
6
+
7
+ def total_file_views
8
+ stats.reduce(0) { |total, stat| total + stat.file_views }
9
+ end
10
+
11
+ def total_file_downloads
12
+ stats.reduce(0) { |total, stat| total + stat.file_downloads }
13
+ end
14
+
15
+ end
@@ -5,8 +5,8 @@ class FileDownloadStat < ActiveRecord::Base
5
5
  [ self.class.convert_date(date), downloads ]
6
6
  end
7
7
 
8
- def self.statistics file_id, start_date
9
- combined_stats file_id, start_date, :downloads, :totalEvents
8
+ def self.statistics file_id, start_date, user_id=nil
9
+ combined_stats file_id, start_date, :downloads, :totalEvents, user_id
10
10
  end
11
11
 
12
12
  # Sufia::Download is sent to Sufia::Analytics.profile as #sufia__download
@@ -3,13 +3,17 @@ class FileUsage
3
3
  attr_accessor :id, :created, :path, :downloads, :pageviews
4
4
 
5
5
  def initialize id
6
+ file = ::GenericFile.find(id)
7
+ user = User.where(email: file.depositor).first
8
+ user_id = user ? user.id : nil
9
+
6
10
  self.id = id
7
11
  self.path = Sufia::Engine.routes.url_helpers.generic_file_path(Sufia::Noid.noidify(id))
8
12
  earliest = Sufia.config.analytic_start_date
9
- self.created = DateTime.parse(::GenericFile.find(id).create_date)
13
+ self.created = DateTime.parse(file.create_date)
10
14
  self.created = earliest > created ? earliest : created unless earliest.blank?
11
- self.downloads = FileDownloadStat.to_flots FileDownloadStat.statistics(id, created)
12
- self.pageviews = FileViewStat.to_flots FileViewStat.statistics(id, created)
15
+ self.downloads = FileDownloadStat.to_flots FileDownloadStat.statistics(id, created, user_id)
16
+ self.pageviews = FileViewStat.to_flots FileViewStat.statistics(id, created, user_id)
13
17
  end
14
18
 
15
19
  def total_downloads
@@ -5,8 +5,8 @@ class FileViewStat < ActiveRecord::Base
5
5
  [ self.class.convert_date(date), views ]
6
6
  end
7
7
 
8
- def self.statistics file_id, start_date
9
- combined_stats file_id, start_date, :views, :pageviews
8
+ def self.statistics file_id, start_date, user_id=nil
9
+ combined_stats file_id, start_date, :views, :pageviews, user_id
10
10
  end
11
11
 
12
12
  # Sufia::Download is sent to Sufia::Analytics.profile as #sufia__download
@@ -0,0 +1,8 @@
1
+ module Sufia
2
+ class OrcidValidator < ActiveModel::Validator
3
+ def validate(record)
4
+ return if record.orcid.blank?
5
+ record.errors.add(:orcid, 'must be a string of 19 characters, e.g., "0000-0000-0000-0000"') unless /\d{4}-\d{4}-\d{4}-\d{4}/.match(record.orcid)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,2 @@
1
+ class UserStat < ActiveRecord::Base
2
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'rails/generators'
3
+ require 'rails/generators/migration'
4
+
5
+ class Sufia::Models::AbstractMigrationGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ # Implement the required interface for Rails::Generators::Migration.
9
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
10
+ def self.next_migration_number(path)
11
+ if @prev_migration_nr
12
+ @prev_migration_nr += 1
13
+ else
14
+ if last_migration = Dir[File.join(path, '*.rb')].sort.last
15
+ @prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
16
+ else
17
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
18
+ end
19
+ end
20
+ @prev_migration_nr.to_s
21
+ end
22
+
23
+ protected
24
+
25
+ def better_migration_template(file)
26
+ migration_template "migrations/#{file}", "db/migrate/#{file}"
27
+ rescue Rails::Generators::Error => e
28
+ say_status("warning", e.message, :yellow)
29
+ end
30
+ end
@@ -1,30 +1,12 @@
1
- # -*- encoding : utf-8 -*-
2
- require 'rails/generators'
3
- require 'rails/generators/migration'
4
-
5
- class Sufia::Models::CachedStatsGenerator < Rails::Generators::Base
6
- include Rails::Generators::Migration
1
+ require_relative 'abstract_migration_generator'
7
2
 
3
+ class Sufia::Models::CachedStatsGenerator < Sufia::Models::AbstractMigrationGenerator
8
4
  source_root File.expand_path('../templates', __FILE__)
9
5
 
10
6
  desc """
11
7
  This generator adds the ability to cache usage stats to your application:
12
8
  1. Creates several database migrations if they do not exist in /db/migrate
13
9
  """
14
- # Implement the required interface for Rails::Generators::Migration.
15
- # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
16
- def self.next_migration_number(path)
17
- if @prev_migration_nr
18
- @prev_migration_nr += 1
19
- else
20
- if last_migration = Dir[File.join(path, '*.rb')].sort.last
21
- @prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
22
- else
23
- @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
24
- end
25
- end
26
- @prev_migration_nr.to_s
27
- end
28
10
 
29
11
  def banner
30
12
  say_status("warning", "ADDING STATS CACHING-RELATED SUFIA MODELS", :yellow)
@@ -32,7 +14,6 @@ This generator adds the ability to cache usage stats to your application:
32
14
 
33
15
  # Setup the database migrations
34
16
  def copy_migrations
35
- # Can't get this any more DRY, because we need this order.
36
17
  [
37
18
  'create_file_view_stats.rb',
38
19
  'create_file_download_stats.rb'
@@ -40,14 +21,4 @@ This generator adds the ability to cache usage stats to your application:
40
21
  better_migration_template file
41
22
  end
42
23
  end
43
-
44
- private
45
-
46
- def better_migration_template(file)
47
- begin
48
- migration_template "migrations/#{file}", "db/migrate/#{file}"
49
- rescue Rails::Generators::Error => e
50
- say_status("warning", e.message, :yellow)
51
- end
52
- end
53
24
  end
@@ -1,12 +1,7 @@
1
- # -*- encoding : utf-8 -*-
2
- require 'rails/generators'
3
- require 'rails/generators/migration'
4
-
5
- class Sufia::Models::InstallGenerator < Rails::Generators::Base
6
- include Rails::Generators::Migration
1
+ require_relative 'abstract_migration_generator'
7
2
 
3
+ class Sufia::Models::InstallGenerator < Sufia::Models::AbstractMigrationGenerator
8
4
  source_root File.expand_path('../templates', __FILE__)
9
-
10
5
  argument :model_name, type: :string , default: "user"
11
6
  desc """
12
7
  This generator makes the following changes to your application:
@@ -19,30 +14,15 @@ This generator makes the following changes to your application:
19
14
  7. Runs full-text generator
20
15
  8. Runs proxies generator
21
16
  9. Runs cached stats generator
17
+ 10. Runs ORCID field generator
18
+ 11. Runs user stats generator
22
19
  """
23
-
24
- # Implement the required interface for Rails::Generators::Migration.
25
- # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
26
- def self.next_migration_number(path)
27
- if @prev_migration_nr
28
- @prev_migration_nr += 1
29
- else
30
- if last_migration = Dir[File.join(path, '*.rb')].sort.last
31
- @prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
32
- else
33
- @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
34
- end
35
- end
36
- @prev_migration_nr.to_s
37
- end
38
-
39
20
  def banner
40
21
  say_status("warning", "GENERATING SUFIA MODELS", :yellow)
41
22
  end
42
23
 
43
24
  # Setup the database migrations
44
25
  def copy_migrations
45
- # Can't get this any more DRY, because we need this order.
46
26
  [
47
27
  "acts_as_follower_migration.rb",
48
28
  "add_social_to_users.rb",
@@ -114,13 +94,13 @@ This generator makes the following changes to your application:
114
94
  generate 'sufia:models:cached_stats'
115
95
  end
116
96
 
117
- private
97
+ # Adds orcid field to user model
98
+ def orcid_field
99
+ generate 'sufia:models:orcid_field'
100
+ end
118
101
 
119
- def better_migration_template(file)
120
- begin
121
- migration_template "migrations/#{file}", "db/migrate/#{file}"
122
- rescue Rails::Generators::Error => e
123
- say_status("warning", e.message, :yellow)
124
- end
102
+ # Adds user stats-related migration & methods
103
+ def user_stats
104
+ generate 'sufia:models:user_stats'
125
105
  end
126
106
  end
@@ -0,0 +1,19 @@
1
+ require_relative 'abstract_migration_generator'
2
+
3
+ class Sufia::Models::OrcidFieldGenerator < Sufia::Models::AbstractMigrationGenerator
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ desc """
7
+ This generator adds a field to hold users' ORCIDs to your application:
8
+ 1. Creates a database migration if they do not exist in /db/migrate
9
+ """
10
+
11
+ def banner
12
+ say_status("warning", "ADDING ORCID FIELD TO USER MODEL", :yellow)
13
+ end
14
+
15
+ # Setup the database migration
16
+ def copy_migrations
17
+ better_migration_template 'add_orcid_to_users.rb'
18
+ end
19
+ end
@@ -1,30 +1,12 @@
1
- # -*- encoding : utf-8 -*-
2
- require 'rails/generators'
3
- require 'rails/generators/migration'
4
-
5
- class Sufia::Models::ProxiesGenerator < Rails::Generators::Base
6
- include Rails::Generators::Migration
1
+ require_relative 'abstract_migration_generator'
7
2
 
3
+ class Sufia::Models::ProxiesGenerator < Sufia::Models::AbstractMigrationGenerator
8
4
  source_root File.expand_path('../templates', __FILE__)
9
5
 
10
6
  desc """
11
7
  This generator adds proxies and transfers to your application:
12
8
  1. Creates several database migrations if they do not exist in /db/migrate
13
9
  """
14
- # Implement the required interface for Rails::Generators::Migration.
15
- # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
16
- def self.next_migration_number(path)
17
- if @prev_migration_nr
18
- @prev_migration_nr += 1
19
- else
20
- if last_migration = Dir[File.join(path, '*.rb')].sort.last
21
- @prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
22
- else
23
- @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
24
- end
25
- end
26
- @prev_migration_nr.to_s
27
- end
28
10
 
29
11
  def banner
30
12
  say_status("warning", "ADDING PROXY/TRANSFER-RELATED SUFIA MODELS", :yellow)
@@ -32,7 +14,6 @@ This generator adds proxies and transfers to your application:
32
14
 
33
15
  # Setup the database migrations
34
16
  def copy_migrations
35
- # Can't get this any more DRY, because we need this order.
36
17
  [
37
18
  'create_proxy_deposit_rights.rb',
38
19
  'create_proxy_deposit_requests.rb'
@@ -40,14 +21,4 @@ This generator adds proxies and transfers to your application:
40
21
  better_migration_template file
41
22
  end
42
23
  end
43
-
44
- private
45
-
46
- def better_migration_template(file)
47
- begin
48
- migration_template "migrations/#{file}", "db/migrate/#{file}"
49
- rescue Rails::Generators::Error => e
50
- say_status("warning", e.message, :yellow)
51
- end
52
- end
53
24
  end
@@ -93,6 +93,9 @@ Sufia.config do |config|
93
93
  # Specify a Google Analytics tracking ID to gather usage statistics
94
94
  # config.google_analytics_id = 'UA-99999999-1'
95
95
 
96
+ # Specify a date you wish to start collecting Google Analytic statistics for.
97
+ # config.analytic_start_date = DateTime.new(2014,9,10)
98
+
96
99
  # Where to store tempfiles, leave blank for the system temp directory (e.g. /tmp)
97
100
  # config.temp_file_base = '/home/developer1'
98
101
 
@@ -108,11 +111,6 @@ Sufia.config do |config|
108
111
  # Specify how many seconds back from the current time that we should show by default of the user's activity on the user's dashboard
109
112
  # config.activity_to_show_default_seconds_since_now = 24*60*60
110
113
 
111
- # Specify a date you wish to start collecting Google Analytic statistics for.
112
- # Leaving it blank will set the start date to when ever the file was uploaded by
113
- # NOTE: if you have always sent analytics to GA for downloads and page views leave this commented out
114
- # config.analytic_start_date = DateTime.new(2014,9,10)
115
-
116
114
  # If browse-everything has been configured, load the configs. Otherwise, set to nil.
117
115
  begin
118
116
  if defined? BrowseEverything
@@ -0,0 +1,5 @@
1
+ class AddOrcidToUsers < ActiveRecord::Migration
2
+ def change
3
+ add_column :users, :orcid, :string
4
+ end
5
+ end
@@ -0,0 +1,19 @@
1
+ class CreateUserStats < ActiveRecord::Migration
2
+ def change
3
+ create_table :user_stats do |t|
4
+ t.integer :user_id
5
+ t.datetime :date
6
+ t.integer :file_views
7
+ t.integer :file_downloads
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_column :file_view_stats, :user_id, :integer
13
+ add_column :file_download_stats, :user_id, :integer
14
+
15
+ add_index :user_stats, :user_id
16
+ add_index :file_view_stats, :user_id
17
+ add_index :file_download_stats, :user_id
18
+ end
19
+ end
@@ -1,13 +1,8 @@
1
- # -*- encoding : utf-8 -*-
2
- require 'rails/generators'
3
- require 'rails/generators/migration'
4
-
5
- class Sufia::Models::Upgrade400Generator < Rails::Generators::Base
6
- include Rails::Generators::Migration
1
+ require_relative 'abstract_migration_generator'
7
2
 
3
+ class Sufia::Models::Upgrade400Generator < Sufia::Models::AbstractMigrationGenerator
8
4
  source_root File.expand_path('../templates', __FILE__)
9
5
 
10
- argument :model_name, type: :string , default: "user"
11
6
  desc """
12
7
  This generator for upgrading sufia-models from 3.7.2 to 4.0 makes the following changes to your application:
13
8
  1. Creates several database migrations if they do not exist in /db/migrate
@@ -16,28 +11,12 @@ This generator for upgrading sufia-models from 3.7.2 to 4.0 makes the following
16
11
  4. Runs full-text generator
17
12
  """
18
13
 
19
- # Implement the required interface for Rails::Generators::Migration.
20
- # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
21
- def self.next_migration_number(path)
22
- if @prev_migration_nr
23
- @prev_migration_nr += 1
24
- else
25
- if last_migration = Dir[File.join(path, '*.rb')].sort.last
26
- @prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
27
- else
28
- @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
29
- end
30
- end
31
- @prev_migration_nr.to_s
32
- end
33
-
34
14
  def banner
35
15
  say_status("warning", "UPGRADING SUFIA MODELS", :yellow)
36
16
  end
37
17
 
38
18
  # Setup the database migrations
39
19
  def copy_migrations
40
- # Can't get this any more DRY, because we need this order.
41
20
  [
42
21
  'create_tinymce_assets.rb',
43
22
  'create_content_blocks.rb',
@@ -72,14 +51,4 @@ This generator for upgrading sufia-models from 3.7.2 to 4.0 makes the following
72
51
  def full_text_indexing
73
52
  generate "sufia:models:fulltext"
74
53
  end
75
-
76
- private
77
-
78
- def better_migration_template(file)
79
- begin
80
- migration_template "migrations/#{file}", "db/migrate/#{file}"
81
- rescue Rails::Generators::Error => e
82
- say_status("warning", e.message, :yellow)
83
- end
84
- end
85
54
  end
@@ -0,0 +1,31 @@
1
+ require_relative 'abstract_migration_generator'
2
+
3
+ class Sufia::Models::UserStatsGenerator < Sufia::Models::AbstractMigrationGenerator
4
+ source_root File.expand_path('../templates', __FILE__)
5
+ argument :model_name, type: :string , default: "user"
6
+
7
+ desc """
8
+ This generator adds usage stats methods to the user model in your application:
9
+ """
10
+
11
+ def banner
12
+ say_status("warning", "ADDING USER STATS-RELATED ABILITIES TO SUFIA MODELS", :yellow)
13
+ end
14
+
15
+ # Setup the database migrations
16
+ def copy_migrations
17
+ better_migration_template 'create_user_stats.rb'
18
+ end
19
+
20
+ def add_stats_mixin_to_user_model
21
+ file_path = "app/models/#{model_name.underscore}.rb"
22
+
23
+ if File.exists?(file_path)
24
+ inject_into_file file_path, after: /include Sufia\:\:User.*$/ do
25
+ "\n include Sufia::UserUsageStats"
26
+ end
27
+ else
28
+ puts " \e[31mFailure\e[0m Sufia requires a user object. This generator assumes that the model is defined in the file #{file_path}, which does not exist. If you used a different name, please re-run the generator and provide that name as an argument. Such as \b rails g sufia:models:user_stats client"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,85 @@
1
+ module Sufia
2
+ class UserStatImporter
3
+
4
+ def initialize(options={})
5
+ @verbose = options[:verbose]
6
+ @logging = options[:logging]
7
+ end
8
+
9
+ def import
10
+ log_message('Begin import of User stats.')
11
+ ::User.find_each do |user|
12
+ start_date = date_since_last_cache(user)
13
+
14
+ stats = {}
15
+ files_for_user(user).each do |file|
16
+ view_stats = FileViewStat.statistics(file.id, start_date, user.id)
17
+ stats = tally_results(view_stats, :views, stats)
18
+
19
+ dl_stats = FileDownloadStat.statistics(file.id, start_date, user.id)
20
+ stats = tally_results(dl_stats, :downloads, stats)
21
+ end
22
+
23
+ create_or_update_user_stats(stats, user)
24
+ end
25
+ log_message('User stats import complete.')
26
+ end
27
+
28
+
29
+ private
30
+
31
+ def date_since_last_cache(user)
32
+ last_cached_stat = UserStat.where(user_id: user.id).order(date: :asc).last
33
+
34
+ if last_cached_stat
35
+ last_cached_stat.date + 1.day
36
+ else
37
+ Sufia.config.analytic_start_date
38
+ end
39
+ end
40
+
41
+ def files_for_user(user)
42
+ ::GenericFile.where(Solrizer.solr_name('depositor', :symbol) => user.user_key)
43
+ end
44
+
45
+ # For each date, add the view and download counts for this
46
+ # file to the view & download sub-totals for that day.
47
+ # The resulting hash will look something like this:
48
+ # {"2014-11-30 00:00:00 UTC" => {:views=>2, :downloads=>5},
49
+ # "2014-12-01 00:00:00 UTC" => {:views=>4, :downloads=>4}}
50
+ def tally_results(file_stats, stat_name, total_stats)
51
+ file_stats.each do |stats|
52
+ # Exclude the stats from today since it will only be a partial day's worth of data
53
+ break if stats.date == Date.today
54
+
55
+ date_key = stats.date.to_s
56
+ old_count = total_stats[date_key] ? total_stats[date_key].fetch(stat_name) { 0 } : 0
57
+ new_count = old_count + stats.method(stat_name).call
58
+
59
+ old_values = total_stats[date_key] || {}
60
+ total_stats.store(date_key, old_values)
61
+ total_stats[date_key].store(stat_name, new_count)
62
+ end
63
+ total_stats
64
+ end
65
+
66
+ def create_or_update_user_stats(stats, user)
67
+ stats.each do |date_string, data|
68
+ date = Time.zone.parse(date_string)
69
+
70
+ user_stat = UserStat.where(user_id: user.id).where(date: date).first
71
+ user_stat ||= UserStat.new(user_id: user.id, date: date)
72
+
73
+ user_stat.file_views = data[:views] || 0
74
+ user_stat.file_downloads = data[:downloads] || 0
75
+ user_stat.save!
76
+ end
77
+ end
78
+
79
+ def log_message(message)
80
+ puts message if @verbose
81
+ Rails.logger.info "#{self.class}: #{message}" if @logging
82
+ end
83
+
84
+ end
85
+ end
@@ -1,5 +1,5 @@
1
1
  module Sufia
2
2
  module Models
3
- VERSION = "4.2.0"
3
+ VERSION = "4.3.1"
4
4
  end
5
5
  end
@@ -0,0 +1,12 @@
1
+ namespace :sufia do
2
+ namespace :stats do
3
+
4
+ desc "Cache file view & download stats for all users"
5
+ task :user_stats => :environment do
6
+ require 'sufia/models/stats/user_stat_importer'
7
+ importer = Sufia::UserStatImporter.new(verbose: true, logging: true)
8
+ importer.import
9
+ end
10
+
11
+ end
12
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sufia-models
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Friesen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-25 00:00:00.000000000 Z
11
+ date: 2014-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -320,6 +320,7 @@ files:
320
320
  - app/models/concerns/sufia/model_methods.rb
321
321
  - app/models/concerns/sufia/properties_datastream_behavior.rb
322
322
  - app/models/concerns/sufia/user.rb
323
+ - app/models/concerns/sufia/user_usage_stats.rb
323
324
  - app/models/datastreams/batch_rdf_datastream.rb
324
325
  - app/models/datastreams/file_content_datastream.rb
325
326
  - app/models/datastreams/fits_datastream.rb
@@ -344,16 +345,20 @@ files:
344
345
  - app/models/sufia/avatar_uploader.rb
345
346
  - app/models/sufia/avatar_validator.rb
346
347
  - app/models/sufia/download.rb
348
+ - app/models/sufia/orcid_validator.rb
347
349
  - app/models/sufia/pageview.rb
348
350
  - app/models/trophy.rb
351
+ - app/models/user_stat.rb
349
352
  - app/models/version_committer.rb
350
353
  - app/services/sufia/analytics.rb
351
354
  - app/services/sufia/id_service.rb
352
355
  - app/services/sufia/noid.rb
353
356
  - config/locales/sufia.en.yml
357
+ - lib/generators/sufia/models/abstract_migration_generator.rb
354
358
  - lib/generators/sufia/models/cached_stats_generator.rb
355
359
  - lib/generators/sufia/models/fulltext_generator.rb
356
360
  - lib/generators/sufia/models/install_generator.rb
361
+ - lib/generators/sufia/models/orcid_field_generator.rb
357
362
  - lib/generators/sufia/models/proxies_generator.rb
358
363
  - lib/generators/sufia/models/templates/config/analytics.yml
359
364
  - lib/generators/sufia/models/templates/config/clamav.rb
@@ -372,6 +377,7 @@ files:
372
377
  - lib/generators/sufia/models/templates/migrations/add_groups_to_users.rb
373
378
  - lib/generators/sufia/models/templates/migrations/add_ldap_attrs_to_user.rb
374
379
  - lib/generators/sufia/models/templates/migrations/add_linkedin_to_users.rb
380
+ - lib/generators/sufia/models/templates/migrations/add_orcid_to_users.rb
375
381
  - lib/generators/sufia/models/templates/migrations/add_social_to_users.rb
376
382
  - lib/generators/sufia/models/templates/migrations/create_checksum_audit_logs.rb
377
383
  - lib/generators/sufia/models/templates/migrations/create_content_blocks.rb
@@ -384,9 +390,11 @@ files:
384
390
  - lib/generators/sufia/models/templates/migrations/create_single_use_links.rb
385
391
  - lib/generators/sufia/models/templates/migrations/create_tinymce_assets.rb
386
392
  - lib/generators/sufia/models/templates/migrations/create_trophies.rb
393
+ - lib/generators/sufia/models/templates/migrations/create_user_stats.rb
387
394
  - lib/generators/sufia/models/templates/migrations/create_version_committers.rb
388
395
  - lib/generators/sufia/models/upgrade400_generator.rb
389
396
  - lib/generators/sufia/models/usagestats_generator.rb
397
+ - lib/generators/sufia/models/user_stats_generator.rb
390
398
  - lib/sufia/messages.rb
391
399
  - lib/sufia/models.rb
392
400
  - lib/sufia/models/active_fedora/redis.rb
@@ -395,6 +403,7 @@ files:
395
403
  - lib/sufia/models/file_content.rb
396
404
  - lib/sufia/models/file_content/versions.rb
397
405
  - lib/sufia/models/resque.rb
406
+ - lib/sufia/models/stats/user_stat_importer.rb
398
407
  - lib/sufia/models/user_local_directory_behavior.rb
399
408
  - lib/sufia/models/utils.rb
400
409
  - lib/sufia/models/version.rb
@@ -403,6 +412,7 @@ files:
403
412
  - lib/sufia/permissions/readable.rb
404
413
  - lib/sufia/permissions/writable.rb
405
414
  - lib/tasks/resque.rake
415
+ - lib/tasks/stats_tasks.rake
406
416
  - lib/tasks/sufia-models_tasks.rake
407
417
  - sufia-models.gemspec
408
418
  homepage: https://github.com/projecthydra/sufia