sufia-models 5.0.0 → 6.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/app/actors/sufia/generic_file/actor.rb +8 -10
  3. data/app/jobs/active_fedora_pid_based_job.rb +2 -3
  4. data/app/jobs/audit_job.rb +46 -32
  5. data/app/jobs/batch_update_job.rb +9 -8
  6. data/app/jobs/import_url_job.rb +2 -2
  7. data/app/models/batch.rb +11 -12
  8. data/app/models/checksum_audit_log.rb +12 -10
  9. data/app/models/concerns/sufia/ability.rb +4 -6
  10. data/app/models/concerns/sufia/collection.rb +4 -5
  11. data/app/models/concerns/sufia/generic_file/batches.rb +29 -0
  12. data/app/models/concerns/sufia/generic_file/characterization.rb +3 -3
  13. data/app/models/concerns/sufia/generic_file/content.rb +13 -0
  14. data/app/models/concerns/sufia/generic_file/derivatives.rb +5 -5
  15. data/app/models/concerns/sufia/generic_file/export.rb +4 -0
  16. data/app/models/concerns/sufia/generic_file/full_text_indexing.rb +2 -2
  17. data/app/models/concerns/sufia/generic_file/indexing.rb +23 -0
  18. data/app/models/concerns/sufia/generic_file/metadata.rb +80 -11
  19. data/app/models/concerns/sufia/generic_file/proxy_deposit.rb +12 -3
  20. data/app/models/concerns/sufia/generic_file/versions.rb +4 -4
  21. data/app/models/concerns/sufia/generic_file/web_form.rb +14 -6
  22. data/app/models/concerns/sufia/generic_file.rb +3 -86
  23. data/app/models/concerns/sufia/model_methods.rb +11 -9
  24. data/app/models/concerns/sufia/user.rb +11 -33
  25. data/app/models/datastreams/file_content_datastream.rb +1 -1
  26. data/app/models/datastreams/fits_datastream.rb +1 -1
  27. data/app/models/file_usage.rb +3 -3
  28. data/app/models/local_authority.rb +2 -2
  29. data/app/models/proxy_deposit_request.rb +1 -1
  30. data/app/services/sufia/generic_file_audit_service.rb +83 -0
  31. data/app/services/sufia/id_service.rb +5 -5
  32. data/app/services/sufia/noid.rb +10 -7
  33. data/app/services/sufia/repository_audit_service.rb +9 -0
  34. data/lib/generators/sufia/models/cached_stats_generator.rb +47 -3
  35. data/lib/generators/sufia/models/install_generator.rb +31 -11
  36. data/lib/generators/sufia/models/proxies_generator.rb +31 -2
  37. data/lib/generators/sufia/models/templates/config/sufia.rb +10 -0
  38. data/lib/generators/sufia/models/upgrade400_generator.rb +33 -2
  39. data/lib/sufia/models/engine.rb +13 -4
  40. data/lib/sufia/models/file_content/versions.rb +9 -11
  41. data/lib/sufia/models/stats/user_stat_importer.rb +5 -9
  42. data/lib/sufia/models/version.rb +1 -1
  43. data/lib/sufia/permissions/writable.rb +34 -16
  44. data/sufia-models.gemspec +4 -2
  45. metadata +54 -33
  46. data/app/models/concerns/sufia/generic_file/audit.rb +0 -116
  47. data/app/models/concerns/sufia/generic_file/reload_on_save.rb +0 -18
  48. data/app/models/concerns/sufia/properties_datastream_behavior.rb +0 -32
  49. data/app/models/datastreams/batch_rdf_datastream.rb +0 -6
  50. data/app/models/datastreams/generic_file_rdf_datastream.rb +0 -69
  51. data/app/models/datastreams/paranoid_rights_datastream.rb +0 -22
  52. data/app/models/datastreams/properties_datastream.rb +0 -4
  53. data/app/models/sufia/orcid_validator.rb +0 -8
  54. data/lib/generators/sufia/models/abstract_migration_generator.rb +0 -30
  55. data/lib/generators/sufia/models/orcid_field_generator.rb +0 -19
  56. data/lib/generators/sufia/models/templates/migrations/add_orcid_to_users.rb +0 -5
  57. data/lib/generators/sufia/models/user_stats_generator.rb +0 -31
@@ -1,14 +1,14 @@
1
1
  module Sufia
2
2
  module GenericFile
3
3
  module Versions
4
+ @@count = 0
4
5
  def record_version_committer(user)
5
6
  version = content.latest_version
6
7
  # content datastream not (yet?) present
7
8
  return if version.nil?
8
- VersionCommitter.create(obj_id: version.pid,
9
- datastream_id: version.dsid,
10
- version_id: version.versionID,
11
- committer_login: user.user_key)
9
+ @@count += 1
10
+ # raise "Recording #{@@count} #{version.uri} for #{user.user_key}" if @@count == 3
11
+ VersionCommitter.create(version_id: version.uri, committer_login: user.user_key)
12
12
  end
13
13
 
14
14
  end
@@ -5,19 +5,27 @@ module Sufia
5
5
  include Sufia::GenericFile::AccessibleAttributes
6
6
  included do
7
7
  before_save :remove_blank_assertions
8
+ attr_accessible *(terms_for_display + [:part_of, :permissions_attributes])
8
9
  end
9
10
 
10
11
  def remove_blank_assertions
11
12
  terms_for_editing.each do |key|
12
- self[key] = nil if self[key] == ['']
13
+ if self[key] == ['']
14
+ self[key] = []
15
+ changed_attributes.delete(key) if attribute_was(key) == []
16
+ end
13
17
  end
14
18
  end
15
19
 
16
20
  # override this method if you need to initialize more complex RDF assertions (b-nodes)
17
21
  def initialize_fields
18
- terms_for_editing.each do |key|
22
+ terms_for_editing.select { |key| self[key].blank? }.each do |key|
19
23
  # if value is empty, we create an one element array to loop over for output
20
- self[key] = [''] if self[key].empty?
24
+ if self.class.multiple?(key)
25
+ self[key] = ['']
26
+ else
27
+ self[key] = ''
28
+ end
21
29
  end
22
30
  end
23
31
 
@@ -40,10 +48,10 @@ module Sufia
40
48
 
41
49
  def to_jq_upload
42
50
  return {
43
- "name" => self.title,
44
- "size" => self.file_size,
51
+ "name" => title,
52
+ "size" => file_size,
45
53
  "url" => "/files/#{noid}",
46
- "thumbnail_url" => self.pid,
54
+ "thumbnail_url" => id,
47
55
  "delete_url" => "deleteme", # generic_file_path(id: id),
48
56
  "delete_type" => "DELETE"
49
57
  }
@@ -8,102 +8,19 @@ module Sufia
8
8
  include Sufia::GenericFile::MimeTypes
9
9
  include Sufia::GenericFile::Export
10
10
  include Sufia::GenericFile::Characterization
11
- include Sufia::GenericFile::Audit
12
11
  include Sufia::GenericFile::Permissions
13
12
  include Sufia::GenericFile::WebForm
14
13
  include Sufia::GenericFile::Derivatives
15
14
  include Sufia::GenericFile::Trophies
16
15
  include Sufia::GenericFile::Featured
17
16
  include Sufia::GenericFile::Metadata
17
+ include Sufia::GenericFile::Content
18
18
  include Sufia::GenericFile::Versions
19
19
  include Sufia::GenericFile::VirusCheck
20
- include Sufia::GenericFile::ReloadOnSave
21
20
  include Sufia::GenericFile::FullTextIndexing
22
21
  include Sufia::GenericFile::ProxyDeposit
23
22
  include Hydra::Collections::Collectible
24
-
25
- included do
26
- belongs_to :batch, property: :is_part_of
27
-
28
- around_save :retry_warming
29
-
30
- attr_accessible *(terms_for_display + [:part_of, :permissions])
31
- end
32
-
33
- def persistent_url
34
- "#{Sufia.config.persistent_hostpath}#{noid}"
35
- end
36
-
37
- def retry_warming
38
- save_tries = 0
39
- conflict_tries = 0
40
- begin
41
- yield
42
- rescue RSolr::Error::Http => error
43
- save_tries += 1
44
- logger.warn "Retry Solr caught RSOLR error on #{self.pid}: #{error.inspect}"
45
- # fail for good if the tries is greater than 3
46
- raise if save_tries >=3
47
- sleep 0.01
48
- retry
49
- rescue ActiveResource::ResourceConflict => error
50
- conflict_tries += 1
51
- logger.warn "Retry caught Active Resource Conflict #{self.pid}: #{error.inspect}"
52
- raise if conflict_tries >=10
53
- sleep 0.01
54
- retry
55
- rescue => error
56
- if error.to_s.downcase.include? "conflict"
57
- conflict_tries += 1
58
- logger.warn "Retry caught Active Resource Conflict #{self.pid}: #{error.inspect}"
59
- raise if conflict_tries >=10
60
- sleep 0.01
61
- retry
62
- else
63
- raise
64
- end
65
- end
66
- end
67
-
68
- # Get the files with a sibling relationship (belongs_to :batch)
69
- # The batch id is minted when visiting the upload screen and attached
70
- # to each file when it is done uploading. The Batch object is not created
71
- # until all objects are done uploading and the user is redirected to
72
- # BatchController#edit. Therefore, we must handle the case where
73
- # self.batch_id is set but self.batch returns nil.
74
- def related_files
75
- return [] if batch.nil?
76
- batch.generic_files.reject { |sibling| sibling.id == id }
77
- end
78
-
79
- # Unstemmed, searchable, stored
80
- def self.noid_indexer
81
- @noid_indexer ||= Solrizer::Descriptor.new(:text, :indexed, :stored)
82
- end
83
-
84
- def to_solr(solr_doc={}, opts={})
85
- super(solr_doc, opts).tap do |solr_doc|
86
- solr_doc[Solrizer.solr_name('label')] = self.label
87
- solr_doc[Solrizer.solr_name('noid', Sufia::GenericFile.noid_indexer)] = noid
88
- solr_doc[Solrizer.solr_name('file_format')] = file_format
89
- solr_doc[Solrizer.solr_name('file_format', :facetable)] = file_format
90
- solr_doc['all_text_timv'] = full_text.content
91
- solr_doc = index_collection_pids(solr_doc)
92
- end
93
- end
94
-
95
- def label=(new_label)
96
- @inner_object.label = new_label
97
- if self.title.empty?
98
- self.title = [new_label].compact
99
- end
100
- end
101
-
102
- # Is this file in the middle of being processed by a batch?
103
- def processing?
104
- return false if self.batch.blank?
105
- return false if !self.batch.methods.include? :status
106
- return (!self.batch.status.empty?) && (self.batch.status.count == 1) && (self.batch.status[0] == "processing")
107
- end
23
+ include Sufia::GenericFile::Batches
24
+ include Sufia::GenericFile::Indexing
108
25
  end
109
26
  end
@@ -8,23 +8,25 @@ module Sufia
8
8
 
9
9
  # OVERRIDE to support Hydra::Datastream::Properties which does not
10
10
  # respond to :depositor_values but :depositor
11
- # Adds metadata about the depositor to the asset
12
- # Most important behavior: if the asset has a rightsMetadata datastream, this method will add +depositor_id+ to its individual edit permissions.
13
-
11
+ # Adds metadata about the depositor to the asset and ads +depositor_id+ to
12
+ # its individual edit permissions.
14
13
  def apply_depositor_metadata(depositor)
15
- rights_ds = self.datastreams["rightsMetadata"]
16
- prop_ds = self.datastreams["properties"]
17
14
  depositor_id = depositor.respond_to?(:user_key) ? depositor.user_key : depositor
18
15
 
19
- rights_ds.update_indexed_attributes([:edit_access, :person]=>depositor_id) unless rights_ds.nil?
20
- prop_ds.depositor = depositor_id unless prop_ds.nil?
16
+ self.edit_users += [depositor_id]
17
+ self.depositor = depositor_id
21
18
 
22
19
  return true
23
20
  end
24
21
 
25
22
  def to_s
26
- return Array(title).join(" | ") if title.present?
27
- label || "No Title"
23
+ if title.present?
24
+ Array(title).join(" | ")
25
+ elsif label.present?
26
+ Array(label).join(" | ")
27
+ else
28
+ "No Title"
29
+ end
28
30
  end
29
31
 
30
32
  end
@@ -18,55 +18,33 @@ module Sufia::User
18
18
  # Users should be followable
19
19
  acts_as_followable
20
20
 
21
- # Set up proxy-related relationships
21
+ # Setup accessible (or protected) attributes for your model
22
22
  has_many :proxy_deposit_requests, foreign_key: 'receiving_user_id'
23
+
23
24
  has_many :deposit_rights_given, foreign_key: 'grantor_id', class_name: 'ProxyDepositRights', dependent: :destroy
24
25
  has_many :can_receive_deposits_from, through: :deposit_rights_given, source: :grantee
26
+
25
27
  has_many :deposit_rights_received, foreign_key: 'grantee_id', class_name: 'ProxyDepositRights', dependent: :destroy
26
28
  has_many :can_make_deposits_for, through: :deposit_rights_received, source: :grantor
27
29
 
28
- # Validate and normalize ORCIDs
29
- validates_with OrcidValidator
30
- after_validation :normalize_orcid
31
-
32
- # Set up user profile avatars
33
30
  mount_uploader :avatar, AvatarUploader, mount_on: :avatar_file_name
34
31
  validates_with AvatarValidator
35
-
36
32
  has_many :trophies
37
33
  attr_accessor :update_directory
38
34
  end
39
35
 
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
-
51
36
  # Format the json for select2 which requires just an id and a field called text.
52
37
  # If we need an alternate format we should probably look at a json template gem
53
38
  def as_json(opts = nil)
54
- { id: user_key, text: display_name ? "#{display_name} (#{user_key})" : user_key }
55
- end
56
-
57
- # Populate user instance with attributes from remote system (e.g., LDAP)
58
- # There is no default implementation -- override this in your application
59
- def populate_attributes
39
+ {id: user_key, text: display_name ? "#{display_name} (#{user_key})" : user_key}
60
40
  end
61
41
 
62
42
  def email_address
63
- self.email
43
+ return self.email
64
44
  end
65
45
 
66
46
  def name
67
- self.display_name.titleize || raise
68
- rescue
69
- self.user_key
47
+ return self.display_name.titleize || self.user_key rescue self.user_key
70
48
  end
71
49
 
72
50
  # Redefine this for more intuitive keys in Redis
@@ -77,13 +55,13 @@ module Sufia::User
77
55
 
78
56
  def trophy_files
79
57
  trophies.map do |t|
80
- ::GenericFile.load_instance_from_solr(Sufia::Noid.namespaceize(t.generic_file_id))
58
+ ::GenericFile.load_instance_from_solr(t.generic_file_id)
81
59
  end
82
60
  end
83
61
 
84
62
  # method needed for messaging
85
63
  def mailboxer_email(obj=nil)
86
- nil
64
+ return nil
87
65
  end
88
66
 
89
67
  # The basic groups method, override or will fallback to Sufia::Ldap::User
@@ -107,9 +85,7 @@ module Sufia::User
107
85
  [:email, :login, :display_name, :address, :admin_area,
108
86
  :department, :title, :office, :chat_id, :website, :affiliation,
109
87
  :telephone, :avatar, :group_list, :groups_last_update, :facebook_handle,
110
- :twitter_handle, :googleplus_handle, :linkedin_handle, :remove_avatar,
111
- :orcid
112
- ]
88
+ :twitter_handle, :googleplus_handle, :linkedin_handle, :remove_avatar]
113
89
  end
114
90
 
115
91
  def current
@@ -143,5 +119,7 @@ module Sufia::User
143
119
  def from_url_component(component)
144
120
  User.find_by_user_key(component.gsub(/-dot-/, '.'))
145
121
  end
122
+
146
123
  end
124
+
147
125
  end
@@ -1,4 +1,4 @@
1
- class FileContentDatastream < ActiveFedora::Datastream
1
+ class FileContentDatastream < ActiveFedora::File
2
2
  include Hydra::Derivatives::ExtractMetadata
3
3
  include Sufia::FileContent::Versions
4
4
  end
@@ -1,7 +1,7 @@
1
1
  class FitsDatastream < ActiveFedora::OmDatastream
2
2
  include OM::XML::Document
3
3
 
4
- def prefix
4
+ def prefix(_)
5
5
  ""
6
6
  end
7
7
 
@@ -10,7 +10,7 @@ class FileUsage
10
10
  self.id = id
11
11
  self.path = Sufia::Engine.routes.url_helpers.generic_file_path(Sufia::Noid.noidify(id))
12
12
  earliest = Sufia.config.analytic_start_date
13
- self.created = DateTime.parse(file.create_date)
13
+ self.created = ::GenericFile.find(id).create_date
14
14
  self.created = earliest > created ? earliest : created unless earliest.blank?
15
15
  self.downloads = FileDownloadStat.to_flots FileDownloadStat.statistics(id, created, user_id)
16
16
  self.pageviews = FileViewStat.to_flots FileViewStat.statistics(id, created, user_id)
@@ -23,8 +23,8 @@ class FileUsage
23
23
  def total_pageviews
24
24
  self.pageviews.reduce(0) { |total, result| total + result[1].to_i }
25
25
  end
26
-
27
- # Package data for visualization using JQuery Flot
26
+
27
+ # Package data for visualization using JQuery Flot
28
28
  def to_flot
29
29
  [
30
30
  { label: "Pageviews", data: pageviews },
@@ -9,10 +9,10 @@ class LocalAuthority < ActiveRecord::Base
9
9
  return unless self.where(name: name).empty?
10
10
  authority = self.create(name: name)
11
11
  format = opts.fetch(:format, :ntriples)
12
- predicate = opts.fetch(:predicate, RDF::SKOS.prefLabel)
12
+ predicate = opts.fetch(:predicate, ::RDF::SKOS.prefLabel)
13
13
  entries = []
14
14
  sources.each do |uri|
15
- RDF::Reader.open(uri, format: format) do |reader|
15
+ ::RDF::Reader.open(uri, format: format) do |reader|
16
16
  reader.each_statement do |statement|
17
17
  if statement.predicate == predicate
18
18
  entries << LocalAuthorityEntry.new(local_authority: authority,
@@ -78,7 +78,7 @@ class ProxyDepositRequest < ActiveRecord::Base
78
78
 
79
79
  def title
80
80
  return 'file not found' if deleted_file?
81
- query = ActiveFedora::SolrService.construct_query_for_pids([pid])
81
+ query = ActiveFedora::SolrQueryBuilder.construct_query_for_ids([pid])
82
82
  solr_response = ActiveFedora::SolrService.query(query, raw: true)
83
83
  SolrDocument.new(solr_response['response']['docs'].first, solr_response).title
84
84
  end
@@ -0,0 +1,83 @@
1
+ module Sufia
2
+ class GenericFileAuditService
3
+ attr_reader :generic_file
4
+ def initialize(file)
5
+ @generic_file = file
6
+ end
7
+
8
+ NO_RUNS = 999
9
+
10
+ # provides a human readable version of the audit status
11
+ def human_readable_audit_status
12
+ stat = audit_stat
13
+ case stat
14
+ when 0
15
+ 'failing'
16
+ when 1
17
+ 'passing'
18
+ else
19
+ stat
20
+ end
21
+ end
22
+
23
+ # TODO: Run audits on all attached files. We're only auditing "content" at tht moment
24
+ # Pushes an AuditJob for each version of content if it hasn't been audited recently
25
+ # Returns the set of most recent audit status for each version of the content file
26
+ def audit
27
+ audit_content([])
28
+ end
29
+
30
+
31
+ private
32
+ def audit_content(log)
33
+ if generic_file.content.has_versions?
34
+ audit_file_versions("content", log)
35
+ else
36
+ log << audit_file("content", generic_file.content.uri)
37
+ end
38
+ end
39
+
40
+ def audit_file_versions file, log
41
+ generic_file.attached_files[file].versions.all.each do |version|
42
+ log << audit_file(file, version.uri, version.label)
43
+ end
44
+ log
45
+ end
46
+
47
+ def audit_stat
48
+ audit_results = audit.collect { |result| result["pass"] }
49
+
50
+ # check how many non runs we had
51
+ non_runs = audit_results.reduce(0) { |sum, value| value == NO_RUNS ? sum += 1 : sum }
52
+ if non_runs == 0
53
+ audit_results.reduce(true) { |sum, value| sum && value }
54
+ elsif non_runs < audit_results.length
55
+ result = audit_results.reduce(true) { |sum, value| value == NO_RUNS ? sum : sum && value }
56
+ "Some audits have not been run, but the ones run were #{result ? 'passing' : 'failing'}."
57
+ else
58
+ 'Audits have not yet been run on this file.'
59
+ end
60
+ end
61
+
62
+ def audit_file(file, uri, label = nil)
63
+ latest_audit = ChecksumAuditLog.logs_for(generic_file.id, file).first
64
+ return latest_audit unless needs_audit?(latest_audit)
65
+ Sufia.queue.push(AuditJob.new(generic_file.id, file, uri))
66
+ latest_audit || ChecksumAuditLog.new(pass: NO_RUNS, pid: generic_file.id, dsid: file, version: label)
67
+ end
68
+
69
+ def needs_audit?(latest_audit)
70
+ return true unless latest_audit
71
+ unless latest_audit.updated_at
72
+ logger.warn "***AUDIT*** problem with audit log! Latest Audit is not nil, but updated_at is not set #{latest_audit}"
73
+ return true
74
+ end
75
+ days_since_last_audit(latest_audit) >= Sufia.config.max_days_between_audits
76
+ end
77
+
78
+ def days_since_last_audit(latest_audit)
79
+ (DateTime.now - latest_audit.updated_at.to_date).to_i
80
+ end
81
+
82
+ end
83
+ end
@@ -9,11 +9,11 @@ module Sufia
9
9
 
10
10
  @minter = ::Noid::Minter.new(template: noid_template)
11
11
  @pid = $$
12
- @namespace = Sufia.config.id_namespace
12
+ #@namespace = Sufia.config.id_namespace
13
13
  @semaphore = Mutex.new
14
14
  def self.valid?(identifier)
15
15
  # remove the fedora namespace since it's not part of the noid
16
- noid = identifier.split(":").last
16
+ noid = identifier#.split(":").last
17
17
  return @minter.valid? noid
18
18
  end
19
19
  def self.mint
@@ -28,20 +28,20 @@ module Sufia
28
28
  protected
29
29
 
30
30
  def self.next_id
31
- pid = ''
31
+ id = ''
32
32
  File.open(Sufia.config.minter_statefile, File::RDWR|File::CREAT, 0644) do |f|
33
33
  f.flock(File::LOCK_EX)
34
34
  yaml = YAML::load(f.read)
35
35
  yaml = {template: noid_template} unless yaml
36
36
  minter = ::Noid::Minter.new(yaml)
37
- pid = "#{@namespace}:#{minter.mint}"
37
+ id = minter.mint
38
38
  f.rewind
39
39
  yaml = YAML::dump(minter.dump)
40
40
  f.write yaml
41
41
  f.flush
42
42
  f.truncate(f.pos)
43
43
  end
44
- return pid
44
+ id
45
45
  end
46
46
  end
47
47
  end
@@ -2,16 +2,14 @@ module Sufia
2
2
  module Noid
3
3
  extend ActiveSupport::Concern
4
4
 
5
- module ClassMethods
6
- ## This overrides the default behavior, which is to ask Fedora for a pid
7
- # @see ActiveFedora::Sharding.assign_pid
8
- def assign_pid(_)
9
- Sufia::IdService.mint
10
- end
5
+ ## This overrides the default behavior, which is to ask Fedora for a pid
6
+ # @see ActiveFedora::Sharding.assign_pid
7
+ def assign_pid
8
+ Sufia::IdService.mint
11
9
  end
12
10
 
13
11
  def noid
14
- Noid.noidify(self.pid)
12
+ Noid.noidify(id)
15
13
  end
16
14
 
17
15
  # Redefine this for more intuitive keys in Redis
@@ -24,6 +22,11 @@ module Sufia
24
22
  String(identifier).split(":").last
25
23
  end
26
24
 
25
+ # Create a pairtree like path for the given identifier
26
+ def treeify(identifier)
27
+ (identifier.scan(/..?/).first(4) + [identifier]).join('/')
28
+ end
29
+
27
30
  def namespaceize(identifier)
28
31
  return identifier if identifier.include?(':')
29
32
  "#{namespace}:#{identifier}"
@@ -0,0 +1,9 @@
1
+ module Sufia
2
+ class RepositoryAuditService
3
+ def self.audit_everything
4
+ ::GenericFile.find_each do |gf|
5
+ gf.audit
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,12 +1,32 @@
1
- require_relative 'abstract_migration_generator'
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
2
7
 
3
- class Sufia::Models::CachedStatsGenerator < Sufia::Models::AbstractMigrationGenerator
4
8
  source_root File.expand_path('../templates', __FILE__)
9
+ argument :model_name, type: :string , default: "user"
5
10
 
6
11
  desc """
7
12
  This generator adds the ability to cache usage stats to your application:
8
13
  1. Creates several database migrations if they do not exist in /db/migrate
14
+ 2. Adds stats methods to the user model
9
15
  """
16
+ # Implement the required interface for Rails::Generators::Migration.
17
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
18
+ def self.next_migration_number(path)
19
+ if @prev_migration_nr
20
+ @prev_migration_nr += 1
21
+ else
22
+ if last_migration = Dir[File.join(path, '*.rb')].sort.last
23
+ @prev_migration_nr = last_migration.sub(File.join(path, '/'), '').to_i + 1
24
+ else
25
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
26
+ end
27
+ end
28
+ @prev_migration_nr.to_s
29
+ end
10
30
 
11
31
  def banner
12
32
  say_status("warning", "ADDING STATS CACHING-RELATED SUFIA MODELS", :yellow)
@@ -14,11 +34,35 @@ This generator adds the ability to cache usage stats to your application:
14
34
 
15
35
  # Setup the database migrations
16
36
  def copy_migrations
37
+ # Can't get this any more DRY, because we need this order.
17
38
  [
18
39
  'create_file_view_stats.rb',
19
- 'create_file_download_stats.rb'
40
+ 'create_file_download_stats.rb',
41
+ 'create_user_stats.rb'
20
42
  ].each do |file|
21
43
  better_migration_template file
22
44
  end
23
45
  end
46
+
47
+ def add_stats_mixin_to_user_model
48
+ file_path = "app/models/#{model_name.underscore}.rb"
49
+
50
+ if File.exists?(file_path)
51
+ inject_into_file file_path, after: /include Sufia\:\:User.*$/ do
52
+ "\n include Sufia::UserUsageStats"
53
+ end
54
+ else
55
+ puts " \e[31mFailure\e[0m Sufia requires a user object. This generators 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 client"
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def better_migration_template(file)
62
+ begin
63
+ migration_template "migrations/#{file}", "db/migrate/#{file}"
64
+ rescue Rails::Generators::Error => e
65
+ say_status("warning", e.message, :yellow)
66
+ end
67
+ end
24
68
  end
@@ -1,7 +1,12 @@
1
- require_relative 'abstract_migration_generator'
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
2
7
 
3
- class Sufia::Models::InstallGenerator < Sufia::Models::AbstractMigrationGenerator
4
8
  source_root File.expand_path('../templates', __FILE__)
9
+
5
10
  argument :model_name, type: :string , default: "user"
6
11
  desc """
7
12
  This generator makes the following changes to your application:
@@ -14,15 +19,30 @@ This generator makes the following changes to your application:
14
19
  7. Runs full-text generator
15
20
  8. Runs proxies generator
16
21
  9. Runs cached stats generator
17
- 10. Runs ORCID field generator
18
- 11. Runs user stats generator
19
22
  """
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
+
20
39
  def banner
21
40
  say_status("warning", "GENERATING SUFIA MODELS", :yellow)
22
41
  end
23
42
 
24
43
  # Setup the database migrations
25
44
  def copy_migrations
45
+ # Can't get this any more DRY, because we need this order.
26
46
  [
27
47
  "acts_as_follower_migration.rb",
28
48
  "add_social_to_users.rb",
@@ -94,13 +114,13 @@ This generator makes the following changes to your application:
94
114
  generate 'sufia:models:cached_stats'
95
115
  end
96
116
 
97
- # Adds orcid field to user model
98
- def orcid_field
99
- generate 'sufia:models:orcid_field'
100
- end
117
+ private
101
118
 
102
- # Adds user stats-related migration & methods
103
- def user_stats
104
- generate 'sufia:models:user_stats'
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
105
125
  end
106
126
  end