worthwhile-models 0.1.0
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.
- checksums.yaml +7 -0
- data/app/models/concerns/curation_concern/collection_model.rb +62 -0
- data/app/models/concerns/curation_concern/curatable.rb +77 -0
- data/app/models/concerns/curation_concern/has_representative.rb +14 -0
- data/app/models/concerns/curation_concern/human_readable_type.rb +23 -0
- data/app/models/concerns/curation_concern/with_basic_metadata.rb +49 -0
- data/app/models/concerns/curation_concern/with_editors.rb +44 -0
- data/app/models/concerns/curation_concern/with_generic_files.rb +23 -0
- data/app/models/concerns/curation_concern/with_linked_resources.rb +21 -0
- data/app/models/concerns/curation_concern/work.rb +24 -0
- data/app/models/concerns/worthwhile/ability.rb +34 -0
- data/app/models/concerns/worthwhile/generic_file/versioned_content.rb +18 -0
- data/app/models/concerns/worthwhile/generic_file_base.rb +64 -0
- data/app/models/concerns/worthwhile/solr_document_behavior.rb +140 -0
- data/app/models/generic_work.rb +5 -0
- data/app/models/worthwhile/classify_concern.rb +47 -0
- data/app/models/worthwhile/content_version.rb +23 -0
- data/app/models/worthwhile/contributor_agreement.rb +23 -0
- data/app/models/worthwhile/generic_file.rb +5 -0
- data/app/models/worthwhile/linked_resource.rb +41 -0
- data/app/models/worthwhile/quick_classification_query.rb +31 -0
- data/lib/worthwhile/models.rb +7 -0
- data/lib/worthwhile/models/engine.rb +11 -0
- data/lib/worthwhile/models/version.rb +5 -0
- data/worthwhile-models.gemspec +29 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9e40a4356445e489fdd44804236d674d99cd7f29
|
4
|
+
data.tar.gz: 426954c2064b078d0a811069528a96642cb4fdfb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dd3b23367115d00157ecd7c21b38c8dc0a279f328f4a7d1fe5bfbca99b08518c8512c43056a689b4f8a4d343d6c0db0b302e505e33298052a3b5bdc63b8f358f
|
7
|
+
data.tar.gz: c36133602cc143df28212470c1c0d43588703c2cc9d3840e4525de1f05170ea9c27dc80597f147038aeef302fd2abb3ad5f1832f0c1a54c20aea7194cb63462f
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module CurationConcern
|
2
|
+
module CollectionModel
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
include Hydra::AccessControls::Permissions
|
6
|
+
include Hydra::AccessControls::WithAccessRight
|
7
|
+
include Sufia::Noid
|
8
|
+
include CurationConcern::HumanReadableType
|
9
|
+
include Hydra::Collection
|
10
|
+
include Hydra::Collections::Collectible
|
11
|
+
include CurationConcern::HasRepresentative
|
12
|
+
|
13
|
+
def add_member(collectible)
|
14
|
+
if can_add_to_members?(collectible)
|
15
|
+
collectible.collections << self
|
16
|
+
collectible.save
|
17
|
+
self.members << collectible
|
18
|
+
self.save
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
self.title.present? ? title : "No Title"
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_solr(solr_doc={}, opts={})
|
27
|
+
super.tap do |solr_doc|
|
28
|
+
Solrizer.set_field(solr_doc, 'generic_type', human_readable_type, :facetable)
|
29
|
+
solr_doc[Solrizer.solr_name('noid', Sufia::GenericFile.noid_indexer)] = noid
|
30
|
+
index_collection_pids(solr_doc)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def can_be_member_of_collection?(collection)
|
35
|
+
collection == self ? false : true
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# ------------------------------------------------
|
40
|
+
# overriding method from active-fedora:
|
41
|
+
# lib/active_fedora/semantic_node.rb
|
42
|
+
#
|
43
|
+
# The purpose of this override is to ensure that
|
44
|
+
# a collection cannot contain itself.
|
45
|
+
#
|
46
|
+
# TODO: After active-fedora 7.0 is released, this
|
47
|
+
# logic can be moved into a before_add callback.
|
48
|
+
# ------------------------------------------------
|
49
|
+
def add_relationship(predicate, target, literal=false)
|
50
|
+
return if self == target
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def can_add_to_members?(collectible)
|
56
|
+
collectible.can_be_member_of_collection?(self)
|
57
|
+
rescue NoMethodError
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Replaces Curate's CurationConcern::Model
|
2
|
+
module CurationConcern::Curatable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
include ::CurationConcern::HumanReadableType
|
7
|
+
include Sufia::Noid
|
8
|
+
include Sufia::ModelMethods
|
9
|
+
include Hydra::Collections::Collectible
|
10
|
+
include Solrizer::Common
|
11
|
+
include ::CurationConcern::HasRepresentative
|
12
|
+
|
13
|
+
# Modules in Curate's CurationConcern::Model that we _might_ pull in later
|
14
|
+
# include Curate::ActiveModelAdaptor
|
15
|
+
|
16
|
+
has_metadata 'properties', type: Worthwhile::PropertiesDatastream
|
17
|
+
has_attributes :relative_path, :depositor, :owner, datastream: :properties, multiple: false
|
18
|
+
class_attribute :human_readable_short_description
|
19
|
+
attr_accessor :files
|
20
|
+
end
|
21
|
+
|
22
|
+
def as_json(options)
|
23
|
+
{ pid: pid, title: title, model: self.class.to_s, curation_concern_type: human_readable_type }
|
24
|
+
end
|
25
|
+
|
26
|
+
def as_rdf_object
|
27
|
+
RDF::URI.new(internal_uri)
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_solr(solr_doc={}, opts={})
|
31
|
+
super.tap do |solr_doc|
|
32
|
+
index_collection_pids(solr_doc)
|
33
|
+
solr_doc[Solrizer.solr_name('noid', Sufia::GenericFile.noid_indexer)] = noid
|
34
|
+
add_derived_date_created(solr_doc)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
title.join(', ')
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a string identifying the path associated with the object. ActionPack uses this to find a suitable partial to represent the object.
|
43
|
+
def to_partial_path
|
44
|
+
"curation_concern/#{super}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def can_be_member_of_collection?(collection)
|
48
|
+
collection == self ? false : true
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
# A searchable date field that is derived from the (text) field date_created
|
54
|
+
def add_derived_date_created(solr_doc)
|
55
|
+
if self.respond_to?(:date_created)
|
56
|
+
self.class.create_and_insert_terms('date_created_derived', derived_dates, [:dateable], solr_doc)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def derived_dates
|
61
|
+
dates = Array(date_created)
|
62
|
+
dates.map { |date| Curate::DateFormatter.parse(date.to_s).to_s }
|
63
|
+
end
|
64
|
+
|
65
|
+
def index_collection_pids(solr_doc)
|
66
|
+
solr_doc[Solrizer.solr_name(:collection, :facetable)] ||= []
|
67
|
+
solr_doc[Solrizer.solr_name(:collection)] ||= []
|
68
|
+
self.collection_ids.each do |collection_id|
|
69
|
+
collection_obj = ActiveFedora::Base.load_instance_from_solr(collection_id)
|
70
|
+
if collection_obj.is_a?(Collection)
|
71
|
+
solr_doc[Solrizer.solr_name(:collection, :facetable)] << collection_id
|
72
|
+
solr_doc[Solrizer.solr_name(:collection)] << collection_id
|
73
|
+
end
|
74
|
+
end
|
75
|
+
solr_doc
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module CurationConcern::HasRepresentative
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
has_attributes :representative, datastream: :properties, multiple: false
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_solr(solr_doc={}, opts={})
|
9
|
+
super.tap do |solr_doc|
|
10
|
+
solr_doc[Solrizer.solr_name('representative', :stored_searchable)] = representative
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module CurationConcern
|
2
|
+
module HumanReadableType
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :human_readable_short_description, :human_readable_type
|
7
|
+
self.human_readable_type = name.demodulize.titleize
|
8
|
+
end
|
9
|
+
|
10
|
+
def human_readable_type
|
11
|
+
self.class.human_readable_type
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_solr(solr_doc={}, opts={})
|
15
|
+
super(solr_doc, opts)
|
16
|
+
solr_doc[Solrizer.solr_name('human_readable_type',:facetable)] = human_readable_type
|
17
|
+
solr_doc[Solrizer.solr_name('human_readable_type', :stored_searchable)] = human_readable_type
|
18
|
+
return solr_doc
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Basic metadata for all Works
|
2
|
+
# Required fields:
|
3
|
+
# dc:title
|
4
|
+
# dc:rights
|
5
|
+
#
|
6
|
+
# Optional fields:
|
7
|
+
# dc:contributor
|
8
|
+
# dc:coverage
|
9
|
+
# dc:creator
|
10
|
+
# dc:date
|
11
|
+
# dc:description
|
12
|
+
# dc:format
|
13
|
+
# dc:identifier
|
14
|
+
# dc:language
|
15
|
+
# dc:publisher
|
16
|
+
# dc:relation
|
17
|
+
# dc:source
|
18
|
+
# dc:subject
|
19
|
+
# dc:type
|
20
|
+
module CurationConcern::WithBasicMetadata
|
21
|
+
extend ActiveSupport::Concern
|
22
|
+
|
23
|
+
included do
|
24
|
+
has_metadata "descMetadata", type: ::GenericWorkMetadata
|
25
|
+
# Validations that apply to all types of Work AND Collections
|
26
|
+
validates_presence_of :title, message: 'Your work must have a title.'
|
27
|
+
|
28
|
+
|
29
|
+
# Single-value fields
|
30
|
+
has_attributes :created, :date_modified, :date_uploaded, datastream: :descMetadata, multiple: false
|
31
|
+
|
32
|
+
# Multi-value fields
|
33
|
+
has_attributes :contributor, :creator, :coverage, :date, :description, :content_format, :identifier,
|
34
|
+
:language, :publisher, :relation, :rights, :source, :subject, :title, :type,
|
35
|
+
datastream: :descMetadata, multiple: true
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# TODO created and date_uploaded?
|
40
|
+
# TODO created and date_created
|
41
|
+
# has_attributes :date_uploaded, :date_modified, :title, :description,
|
42
|
+
# datastream: :descMetadata, multiple: false
|
43
|
+
#
|
44
|
+
# has_attributes :related_url, :based_near, :part_of, :creator, :contributor,
|
45
|
+
# :tag, :rights, :publisher, :date_created, :subject, :resource_type,
|
46
|
+
# :identifier, :language,
|
47
|
+
# datastream: :descMetadata, multiple: true
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module CurationConcern
|
2
|
+
module WithEditors
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def add_editor_group(group_name)
|
6
|
+
self.edit_groups += [group]
|
7
|
+
end
|
8
|
+
|
9
|
+
# @param groups [Array<String>] a list of group names to add
|
10
|
+
def add_editor_groups(groups)
|
11
|
+
groups.each { |g| add_editor_group(g) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def remove_editor_group(group)
|
15
|
+
self.edit_groups -= [group]
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param groups [Array<String>] a list of users to remove
|
19
|
+
def remove_editor_groups(groups)
|
20
|
+
groups.each { |g| remove_editor_group(g) }
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param user [String] the user account you want to grant edit access to.
|
24
|
+
def add_editor(user)
|
25
|
+
self.edit_users += [user]
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param users [Array<String>] a list of users to add
|
29
|
+
def add_editors(users)
|
30
|
+
users.each { |u| add_editor(u) }
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param user [String] the user account you want to revoke edit access for.
|
34
|
+
def remove_editor(user)
|
35
|
+
self.edit_users -= [user]
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param users [Array<String>] a list of users to remove
|
39
|
+
def remove_editors(users)
|
40
|
+
users.each { |u| remove_editor(u) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copied from Curate
|
2
|
+
module CurationConcern
|
3
|
+
module WithGenericFiles
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
has_many :generic_files, property: :is_part_of, class_name: "Worthwhile::GenericFile"
|
8
|
+
before_destroy :before_destroy_cleanup_generic_files
|
9
|
+
end
|
10
|
+
|
11
|
+
def before_destroy_cleanup_generic_files
|
12
|
+
generic_files.each(&:destroy)
|
13
|
+
end
|
14
|
+
|
15
|
+
def copy_visibility_to_files
|
16
|
+
generic_files.each do |gf|
|
17
|
+
gf.visibility = visibility
|
18
|
+
gf.save!
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CurationConcern
|
2
|
+
module WithLinkedResources
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
|
7
|
+
# attribute :linked_resource_urls, multiple: true
|
8
|
+
attr_accessor :linked_resource_urls
|
9
|
+
|
10
|
+
has_many :linked_resources, property: :is_part_of, class_name:"Worthwhile::LinkedResource"
|
11
|
+
|
12
|
+
after_destroy :after_destroy_cleanup_linked_resources
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_destroy_cleanup_linked_resources
|
16
|
+
linked_resources.each(&:destroy)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module CurationConcern::Work
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
include ::CurationConcern::Curatable
|
4
|
+
include ::CurationConcern::WithGenericFiles
|
5
|
+
include Hydra::AccessControls::Embargoable
|
6
|
+
include ::CurationConcern::WithEditors
|
7
|
+
include CurationConcern::WithLinkedResources
|
8
|
+
|
9
|
+
# Modules in Curate's CurationConcern::Work that we _might_ pull in later
|
10
|
+
# include Curate::ActiveModelAdaptor
|
11
|
+
# include CurationConcern::WithLinkedContributors
|
12
|
+
# include CurationConcern::WithRelatedWorks
|
13
|
+
|
14
|
+
included do
|
15
|
+
has_metadata "properties", type: Worthwhile::PropertiesDatastream
|
16
|
+
has_attributes :depositor, :representative, datastream: :properties, multiple: false
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_solr(solr_doc={}, opts={})
|
20
|
+
super(solr_doc, opts)
|
21
|
+
Solrizer.set_field(solr_doc, 'generic_type', 'Work', :facetable)
|
22
|
+
return solr_doc
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Worthwhile
|
2
|
+
module Ability
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
self.ability_logic += [:worthwhile_permissions]
|
6
|
+
end
|
7
|
+
|
8
|
+
def worthwhile_permissions
|
9
|
+
|
10
|
+
unless current_user.new_record?
|
11
|
+
can :create, Worthwhile::ClassifyConcern
|
12
|
+
can :create, [Worthwhile::GenericFile, Worthwhile::LinkedResource]
|
13
|
+
end
|
14
|
+
|
15
|
+
if user_groups.include? 'admin'
|
16
|
+
can [:discover, :show, :read, :edit, :update, :destroy], :all
|
17
|
+
end
|
18
|
+
|
19
|
+
can :collect, :all
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
# Add this to your ability_logic if you want all logged in users to be able to submit content
|
24
|
+
def everyone_can_create_curation_concerns
|
25
|
+
unless current_user.new_record?
|
26
|
+
can :create, [Worthwhile.configuration.curation_concerns]
|
27
|
+
can :create, Collection
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Worthwhile
|
2
|
+
class GenericFile
|
3
|
+
module VersionedContent
|
4
|
+
def versions
|
5
|
+
return [] unless persisted?
|
6
|
+
@versions ||= content.versions.collect {|version| Worthwhile::ContentVersion.new(content, version)}
|
7
|
+
end
|
8
|
+
|
9
|
+
def latest_version
|
10
|
+
versions.first || Worthwhile::ContentVersion::Null.new(content)
|
11
|
+
end
|
12
|
+
|
13
|
+
def current_version_id
|
14
|
+
latest_version.version_id
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Worthwhile
|
2
|
+
module GenericFileBase
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include Hydra::AccessControls::Embargoable
|
5
|
+
include Sufia::ModelMethods
|
6
|
+
include Sufia::Noid
|
7
|
+
include Sufia::GenericFile::MimeTypes
|
8
|
+
include Sufia::GenericFile::Characterization
|
9
|
+
include Sufia::GenericFile::Audit
|
10
|
+
include Sufia::GenericFile::WebForm
|
11
|
+
include Sufia::GenericFile::Derivatives
|
12
|
+
include Sufia::GenericFile::Metadata
|
13
|
+
include Sufia::GenericFile::Versions
|
14
|
+
include Sufia::Permissions::Readable
|
15
|
+
include Worthwhile::GenericFile::VersionedContent
|
16
|
+
|
17
|
+
included do
|
18
|
+
belongs_to :batch, property: :is_part_of, class_name: 'ActiveFedora::Base'
|
19
|
+
|
20
|
+
before_destroy :remove_representative_relationship
|
21
|
+
|
22
|
+
attr_accessor :file
|
23
|
+
|
24
|
+
# make filename single-value (Sufia::GenericFile::Characterization makes it multivalue)
|
25
|
+
# has_attributes :filename, datastream: :characterization, multiple: false
|
26
|
+
def filename
|
27
|
+
content.label
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def human_readable_type
|
32
|
+
self.class.to_s.demodulize.titleize
|
33
|
+
end
|
34
|
+
|
35
|
+
def representative
|
36
|
+
to_param
|
37
|
+
end
|
38
|
+
|
39
|
+
def copy_permissions_from(obj)
|
40
|
+
self.datastreams['rightsMetadata'].ng_xml = obj.datastreams['rightsMetadata'].ng_xml
|
41
|
+
end
|
42
|
+
|
43
|
+
def update_parent_representative_if_empty(obj)
|
44
|
+
return unless obj.representative.blank?
|
45
|
+
obj.representative = self.pid
|
46
|
+
obj.save
|
47
|
+
end
|
48
|
+
|
49
|
+
def remove_representative_relationship
|
50
|
+
return unless ActiveFedora::Base.exists?(batch)
|
51
|
+
return unless batch.representative == self.pid
|
52
|
+
batch.representative = nil
|
53
|
+
batch.save
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_solr(solr_doc = {})
|
57
|
+
super.tap do |solr_doc|
|
58
|
+
# Enables Riiif to not have to recalculate this each time.
|
59
|
+
solr_doc['height_isi'] = Integer(height.first) if height.present?
|
60
|
+
solr_doc['width_isi'] = Integer(width.first) if width.present?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# This was moved out of sufia-models and into sufia/app/models.
|
2
|
+
# Copied the file in here to retain the functionality until/unless the file gets moved back into sufia-models.
|
3
|
+
# -*- encoding : utf-8 -*-
|
4
|
+
module Worthwhile
|
5
|
+
module SolrDocumentBehavior
|
6
|
+
def title_or_label
|
7
|
+
title || label
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Give our SolrDocument an ActiveModel::Naming appropriate route_key
|
12
|
+
def route_key
|
13
|
+
get(Solrizer.solr_name('has_model', :symbol)).split(':').last.downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_param
|
17
|
+
noid || id
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
title_or_label
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Offer the source (ActiveFedora-based) model to Rails for some of the
|
26
|
+
# Rails methods (e.g. link_to).
|
27
|
+
# @example
|
28
|
+
# link_to '...', SolrDocument(:id => 'bXXXXXX5').new => <a href="/dams_object/bXXXXXX5">...</a>
|
29
|
+
def to_model
|
30
|
+
m = ActiveFedora::Base.load_instance_from_solr(id, self)
|
31
|
+
m.class == ActiveFedora::Base ? self : m
|
32
|
+
end
|
33
|
+
|
34
|
+
def collection?
|
35
|
+
hydra_model == 'Collection'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Method to return the ActiveFedora model
|
39
|
+
def hydra_model
|
40
|
+
self[Solrizer.solr_name('active_fedora_model', Solrizer::Descriptor.new(:string, :stored, :indexed))]
|
41
|
+
end
|
42
|
+
|
43
|
+
def noid
|
44
|
+
self[Solrizer.solr_name('noid', Sufia::GenericFile.noid_indexer)]
|
45
|
+
end
|
46
|
+
|
47
|
+
def human_readable_type
|
48
|
+
Array(self[Solrizer.solr_name('human_readable_type', :stored_searchable)]).first
|
49
|
+
end
|
50
|
+
|
51
|
+
def representative
|
52
|
+
Array(self[Solrizer.solr_name('representative', :stored_searchable)]).first
|
53
|
+
end
|
54
|
+
|
55
|
+
def date_uploaded
|
56
|
+
field = self[Solrizer.solr_name("desc_metadata__date_uploaded", :stored_sortable, type: :date)]
|
57
|
+
return unless field.present?
|
58
|
+
begin
|
59
|
+
Date.parse(field).to_formatted_s(:standard)
|
60
|
+
rescue
|
61
|
+
Rails.logger.info "Unable to parse date: #{field.first.inspect} for #{self['id']}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def depositor(default = '')
|
66
|
+
val = Array(self[Solrizer.solr_name("depositor")]).first
|
67
|
+
val.present? ? val : default
|
68
|
+
end
|
69
|
+
|
70
|
+
def title
|
71
|
+
Array(self[Solrizer.solr_name('desc_metadata__title')]).first
|
72
|
+
end
|
73
|
+
|
74
|
+
def description
|
75
|
+
Array(self[Solrizer.solr_name('desc_metadata__description')]).first
|
76
|
+
end
|
77
|
+
|
78
|
+
def label
|
79
|
+
Array(self[Solrizer.solr_name('label')]).first
|
80
|
+
end
|
81
|
+
|
82
|
+
def file_format
|
83
|
+
Array(self[Solrizer.solr_name('file_format')]).first
|
84
|
+
end
|
85
|
+
|
86
|
+
def creator
|
87
|
+
Array(self[Solrizer.solr_name("desc_metadata__creator")]).first
|
88
|
+
end
|
89
|
+
|
90
|
+
def tags
|
91
|
+
Array(self[Solrizer.solr_name("desc_metadata__tag")])
|
92
|
+
end
|
93
|
+
|
94
|
+
def resource_type
|
95
|
+
Array(self[Solrizer.solr_name("desc_metadata__resource_type")])
|
96
|
+
end
|
97
|
+
|
98
|
+
def mime_type
|
99
|
+
Array(self[Solrizer.solr_name("mime_type")]).first
|
100
|
+
end
|
101
|
+
|
102
|
+
def read_groups
|
103
|
+
Array(self[::Ability.read_group_field])
|
104
|
+
end
|
105
|
+
|
106
|
+
def edit_groups
|
107
|
+
Array(self[::Ability.edit_group_field])
|
108
|
+
end
|
109
|
+
|
110
|
+
def edit_people
|
111
|
+
Array(self[::Ability.edit_user_field])
|
112
|
+
end
|
113
|
+
|
114
|
+
def public?
|
115
|
+
read_groups.include?('public')
|
116
|
+
end
|
117
|
+
|
118
|
+
def registered?
|
119
|
+
read_groups.include?('registered')
|
120
|
+
end
|
121
|
+
|
122
|
+
def pdf?
|
123
|
+
['application/pdf'].include? self.mime_type
|
124
|
+
end
|
125
|
+
|
126
|
+
def image?
|
127
|
+
['image/png','image/jpeg', 'image/jpg', 'image/jp2', 'image/bmp', 'image/gif', 'image/tiff'].include? self.mime_type
|
128
|
+
end
|
129
|
+
|
130
|
+
def video?
|
131
|
+
['video/mpeg', 'video/mp4', 'video/webm', 'video/x-msvideo', 'video/avi', 'video/quicktime', 'application/mxf'].include? self.mime_type
|
132
|
+
end
|
133
|
+
|
134
|
+
def audio?
|
135
|
+
# audio/x-wave is the mime type that fits 0.6.0 returns for a wav file.
|
136
|
+
# audio/mpeg is the mime type that fits 0.6.0 returns for an mp3 file.
|
137
|
+
['audio/mp3', 'audio/mpeg', 'audio/x-wave', 'audio/x-wav', 'audio/ogg'].include? self.mime_type
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'active_attr'
|
2
|
+
module Worthwhile
|
3
|
+
class ClassifyConcern
|
4
|
+
include ActiveAttr::Model
|
5
|
+
attribute :curation_concern_type
|
6
|
+
|
7
|
+
validates(
|
8
|
+
:curation_concern_type,
|
9
|
+
presence: true,
|
10
|
+
inclusion: { in: lambda { |record| record.registered_curation_concern_types } }
|
11
|
+
)
|
12
|
+
|
13
|
+
def all_curation_concern_classes
|
14
|
+
registered_curation_concern_types.sort.map { |c| self.class.to_class(c) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def registered_curation_concern_types
|
18
|
+
Worthwhile.configuration.registered_curation_concern_types
|
19
|
+
end
|
20
|
+
|
21
|
+
def possible_curation_concern_types
|
22
|
+
registered_curation_concern_types.collect do |concern|
|
23
|
+
[self.class.to_class(concern).human_readable_type, concern]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def curation_concern_class
|
28
|
+
if possible_curation_concern_types.detect{|name, class_name|
|
29
|
+
class_name == curation_concern_type
|
30
|
+
}
|
31
|
+
self.class.to_class(curation_concern_type)
|
32
|
+
else
|
33
|
+
raise RuntimeError, "Invalid :curation_concern_type"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.to_class(type)
|
38
|
+
# TODO we may want to allow a different (or nil) namespace
|
39
|
+
type.camelize.constantize
|
40
|
+
# begin
|
41
|
+
# "::#{type.camelize}".constantize
|
42
|
+
# rescue NameError
|
43
|
+
# "Worthwhile::#{type}".constantize
|
44
|
+
# end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Worthwhile
|
2
|
+
class ContentVersion
|
3
|
+
class Null
|
4
|
+
def initialize(content)
|
5
|
+
end
|
6
|
+
def created_on; 'unknown'; end
|
7
|
+
def committer_name; 'unknown'; end
|
8
|
+
def formatted_created_on(*args); 'unknown'; end
|
9
|
+
def version_id; 'unknown'; end
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :version_id, :created_on, :committer_name
|
13
|
+
def initialize(content, version_structure)
|
14
|
+
@created_on = version_structure.dsCreateDate
|
15
|
+
@version_id = version_structure.versionID
|
16
|
+
@committer_name = content.version_committer(version_structure)
|
17
|
+
end
|
18
|
+
|
19
|
+
def formatted_created_on(format = :long_ordinal )
|
20
|
+
created_on.localtime.to_formatted_s(format)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Worthwhile
|
2
|
+
class ContributorAgreement
|
3
|
+
attr_reader :curation_concern, :user
|
4
|
+
def initialize(curation_concern, user, params)
|
5
|
+
@curation_concern = curation_concern
|
6
|
+
@user = user
|
7
|
+
@param_value = params[param_key.to_sym] || params[param_key.to_s]
|
8
|
+
end
|
9
|
+
|
10
|
+
def acceptance_value
|
11
|
+
'accept'
|
12
|
+
end
|
13
|
+
|
14
|
+
def param_key
|
15
|
+
:accept_contributor_agreement
|
16
|
+
end
|
17
|
+
attr_reader :param_value
|
18
|
+
|
19
|
+
def is_being_accepted?
|
20
|
+
param_value == acceptance_value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Worthwhile
|
2
|
+
class LinkedResource < ActiveFedora::Base
|
3
|
+
include ::CurationConcern::Work
|
4
|
+
|
5
|
+
has_file_datastream "content", control_group: 'E'
|
6
|
+
has_metadata "descMetadata", type: GenericFileRdfDatastream
|
7
|
+
|
8
|
+
belongs_to :batch, property: :is_part_of, class_name: 'ActiveFedora::Base'
|
9
|
+
|
10
|
+
validates :url, presence: true
|
11
|
+
|
12
|
+
self.human_readable_short_description = "An arbitrary URL reference."
|
13
|
+
include ActionView::Helpers::SanitizeHelper
|
14
|
+
|
15
|
+
has_attributes :date_uploaded, :date_modified, :title, :description, datastream: :descMetadata, multiple: false
|
16
|
+
|
17
|
+
# Creator is multiple to match Sufia::GenericFile#creator
|
18
|
+
has_attributes :creator, datastream: :descMetadata, multiple: true
|
19
|
+
|
20
|
+
def url=(url)
|
21
|
+
u = URI::Parser.new.parse(url)
|
22
|
+
return unless [URI::HTTP, URI::HTTPS, URI::FTP].include?(u.class)
|
23
|
+
content.dsLocation = u.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def url
|
27
|
+
content.dsLocation
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
url
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_solr(solr_doc={}, opts={})
|
35
|
+
super
|
36
|
+
Solrizer.set_field(solr_doc, 'url', url, :stored_searchable)
|
37
|
+
solr_doc
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Worthwhile
|
2
|
+
class QuickClassificationQuery
|
3
|
+
|
4
|
+
def self.each_for_context(*args, &block)
|
5
|
+
new(*args).all.each(&block)
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :user
|
9
|
+
|
10
|
+
def initialize(user, options = {})
|
11
|
+
@user = user
|
12
|
+
@concern_name_normalizer = options.fetch(:concern_name_normalizer, ClassifyConcern.method(:to_class))
|
13
|
+
@registered_curation_concern_names = options.fetch(:registered_curation_concern_names, Worthwhile.configuration.registered_curation_concern_types)
|
14
|
+
end
|
15
|
+
|
16
|
+
def all
|
17
|
+
ActiveFedora::Base.logger.debug "User is #{user}"
|
18
|
+
ActiveFedora::Base.logger.debug "try is #{normalized_curation_concern_names.first}"
|
19
|
+
ActiveFedora::Base.logger.debug "can is #{user.can?(:create, normalized_curation_concern_names.first)}"
|
20
|
+
normalized_curation_concern_names.select {|klass| user.can?(:create, klass)}
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :concern_name_normalizer, :registered_curation_concern_names
|
26
|
+
|
27
|
+
def normalized_curation_concern_names
|
28
|
+
registered_curation_concern_names.collect{|name| concern_name_normalizer.call(name) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
version = File.read(File.expand_path("../../WORTHWHILE_VERSION", __FILE__)).strip
|
3
|
+
|
4
|
+
lib = File.expand_path('../lib', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "worthwhile-models"
|
9
|
+
spec.version = version
|
10
|
+
spec.authors = ["Justin Coyne"]
|
11
|
+
spec.email = ["justin@curationexperts.com"]
|
12
|
+
spec.summary = %q{Simple institutional repository models for Hydra}
|
13
|
+
spec.description = %q{An extensible repository data-model with works and and many attached files}
|
14
|
+
spec.homepage = ""
|
15
|
+
spec.license = "APACHE2"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency 'hydra-head', '~> 7.2.2'
|
23
|
+
spec.add_dependency "active_attr"
|
24
|
+
spec.add_dependency 'sufia-models', '~> 4.0.0'
|
25
|
+
spec.add_dependency 'hydra-collections', '~> 2.0.5'
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: worthwhile-models
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Coyne
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hydra-head
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 7.2.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 7.2.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: active_attr
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sufia-models
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 4.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 4.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hydra-collections
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.0.5
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.0.5
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.6'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.6'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: An extensible repository data-model with works and and many attached
|
98
|
+
files
|
99
|
+
email:
|
100
|
+
- justin@curationexperts.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- app/models/concerns/curation_concern/collection_model.rb
|
106
|
+
- app/models/concerns/curation_concern/curatable.rb
|
107
|
+
- app/models/concerns/curation_concern/has_representative.rb
|
108
|
+
- app/models/concerns/curation_concern/human_readable_type.rb
|
109
|
+
- app/models/concerns/curation_concern/with_basic_metadata.rb
|
110
|
+
- app/models/concerns/curation_concern/with_editors.rb
|
111
|
+
- app/models/concerns/curation_concern/with_generic_files.rb
|
112
|
+
- app/models/concerns/curation_concern/with_linked_resources.rb
|
113
|
+
- app/models/concerns/curation_concern/work.rb
|
114
|
+
- app/models/concerns/worthwhile/ability.rb
|
115
|
+
- app/models/concerns/worthwhile/generic_file/versioned_content.rb
|
116
|
+
- app/models/concerns/worthwhile/generic_file_base.rb
|
117
|
+
- app/models/concerns/worthwhile/solr_document_behavior.rb
|
118
|
+
- app/models/generic_work.rb
|
119
|
+
- app/models/worthwhile/classify_concern.rb
|
120
|
+
- app/models/worthwhile/content_version.rb
|
121
|
+
- app/models/worthwhile/contributor_agreement.rb
|
122
|
+
- app/models/worthwhile/generic_file.rb
|
123
|
+
- app/models/worthwhile/linked_resource.rb
|
124
|
+
- app/models/worthwhile/quick_classification_query.rb
|
125
|
+
- lib/worthwhile/models.rb
|
126
|
+
- lib/worthwhile/models/engine.rb
|
127
|
+
- lib/worthwhile/models/version.rb
|
128
|
+
- worthwhile-models.gemspec
|
129
|
+
homepage: ''
|
130
|
+
licenses:
|
131
|
+
- APACHE2
|
132
|
+
metadata: {}
|
133
|
+
post_install_message:
|
134
|
+
rdoc_options: []
|
135
|
+
require_paths:
|
136
|
+
- lib
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 2.2.2
|
150
|
+
signing_key:
|
151
|
+
specification_version: 4
|
152
|
+
summary: Simple institutional repository models for Hydra
|
153
|
+
test_files: []
|