hydra-pcdm 0.9.0 → 0.10.0

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: 006a56a41489a68705b5f0ba39cb71adaebcd93a
4
- data.tar.gz: 9bf9ac83b49048e144b2a595ad0a38ae16507936
3
+ metadata.gz: 61bc1a9816b4822a33c073ecbab19f6eb74dda9a
4
+ data.tar.gz: 4d8f2cd6f00ea740ab855418319764e579abcd7f
5
5
  SHA512:
6
- metadata.gz: 45a1c0c840a1262986f00485d2eed19e0032c84dffabf0fa5ce51f7dcadd1e2dc0db5e02c748a4192c3e8fb541f1ca56d236726ddc2e0c02630421423d8a1b8d
7
- data.tar.gz: 02969cb30e666ea14ced04268404702aea51fbee3f346957677d142e6bb907a685b1fcfac745c9017f7613cac55988171d7316b6ac88b7269fd5341babfa9b5b
6
+ metadata.gz: dfbe03462ec7d064c1d92f8305838bdc73dee0a50f621656c0bc24529f97f1cae00e0a1f87b84026cac04ee255f4f1c3175b6761aa37d610735646de6eb9afee
7
+ data.tar.gz: b8c13606f893bfef6d26bfb70514230be9170fa1165b97ac8480330535dd19946276d893e8bba4d45cd20193328504deb962374df9df5a3fb16e6913b1bb775c
@@ -8,6 +8,9 @@ AllCops:
8
8
  Metrics/LineLength:
9
9
  Enabled: false
10
10
 
11
+ Metrics/AbcSize:
12
+ Max: 17
13
+
11
14
  Style/CollectionMethods:
12
15
  PreferredMethods:
13
16
  collect: 'map'
@@ -36,3 +39,19 @@ RSpec/FilePath:
36
39
 
37
40
  RSpec/InstanceVariable:
38
41
  Enabled: false
42
+
43
+ RSpec/NamedSubject:
44
+ Enabled: false
45
+
46
+ RSpec/MultipleExpectations:
47
+ Exclude:
48
+ - spec/hydra/pcdm/collection_indexer_spec.rb
49
+ - spec/hydra/pcdm/pcdm_indexer_spec.rb
50
+ - spec/hydra/pcdm/models/*
51
+
52
+ RSpec/ExampleLength:
53
+ Exclude:
54
+ - spec/hydra/pcdm/models/*
55
+
56
+ RSpec/NestedGroups:
57
+ Enabled: false
@@ -8,11 +8,10 @@ env:
8
8
  jdk:
9
9
  - oraclejdk8
10
10
  rvm:
11
- - 2.2.5
12
- - 2.3.1
13
- - jruby-head
11
+ - 2.2.7
12
+ - 2.3.4
13
+ - 2.4.1
14
+ - jruby-9.1.8.0
14
15
  matrix:
15
16
  allow_failures:
16
- - rvm: jruby-head
17
- jdk:
18
- - oraclejdk8
17
+ - rvm: jruby-9.1.8.0
@@ -3,6 +3,13 @@
3
3
  We want your help to make Project Hydra great.
4
4
  There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
5
5
 
6
+ ## Code of Conduct
7
+
8
+ The Hydra community is dedicated to providing a welcoming and positive experience for all its
9
+ members, whether they are at a formal gathering, in a social setting, or taking part in activities
10
+ online. Please see our [Code of Conduct](https://wiki.duraspace.org/display/hydra/Code+of+Conduct)
11
+ for more information.
12
+
6
13
  ## Hydra Project Intellectual Property Licensing and Ownership
7
14
 
8
15
  All code contributors must have an Individual Contributor License Agreement (iCLA) on file with the Hydra Project Steering Group.
@@ -16,8 +23,10 @@ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the pr
16
23
 
17
24
  * Reporting Issues
18
25
  * Making Changes
26
+ * Documenting Code
27
+ * Committing Changes
19
28
  * Submitting Changes
20
- * Merging Changes
29
+ * Reviewing and Merging Changes
21
30
 
22
31
  ### Reporting Issues
23
32
 
@@ -38,8 +47,28 @@ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the pr
38
47
  * Then checkout the new branch with `git checkout fix/master/my_contribution`.
39
48
  * Please avoid working directly on the `master` branch.
40
49
  * You may find the [hub suite of commands](https://github.com/defunkt/hub) helpful
50
+ * Make sure you have added sufficient tests and documentation for your changes.
51
+ * Test functionality with RSpec; est features / UI with Capybara.
52
+ * Run _all_ the tests to assure nothing else was accidentally broken.
53
+
54
+ ### Documenting Code
55
+
56
+ * All new public methods, modules, and classes should include inline documentation in [YARD](http://yardoc.org/).
57
+ * Documentation should seek to answer the question "why does this code exist?"
58
+ * Document private / protected methods as desired.
59
+ * If you are working in a file with no prior documentation, do try to document as you gain understanding of the code.
60
+ * If you don't know exactly what a bit of code does, it is extra likely that it needs to be documented. Take a stab at it and ask for feedback in your pull request. You can use the 'blame' button on GitHub to identify the original developer of the code and @mention them in your comment.
61
+ * This work greatly increases the usability of the code base and supports the on-ramping of new committers.
62
+ * We will all be understanding of one another's time constraints in this area.
63
+ * YARD examples:
64
+ * [Hydra::Works::RemoveGenericFile](https://github.com/projecthydra-labs/hydra-works/blob/master/lib/hydra/works/services/generic_work/remove_generic_file.rb)
65
+ * [ActiveTriples::LocalName::Minter](https://github.com/ActiveTriples/active_triples-local_name/blob/master/lib/active_triples/local_name/minter.rb)
66
+ * [Getting started with YARD](http://www.rubydoc.info/gems/yard/file/docs/GettingStarted.md)
67
+
68
+ ### Committing changes
69
+
41
70
  * Make commits of logical units.
42
- * Your commit should include a high level description of your work in HISTORY.textile
71
+ * Your commit should include a high level description of your work in HISTORY.textile
43
72
  * Check for unnecessary whitespace with `git diff --check` before committing.
44
73
  * Make sure your commit messages are [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
45
74
  * If you created an issue, you can close it by including "Closes #issue" in your commit message. See [Github's blog post for more details](https://github.com/blog/1386-closing-issues-via-commit-messages)
@@ -60,7 +89,9 @@ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the pr
60
89
 
61
90
  class PostsController
62
91
  def index
63
- respond_with Post.limit(10)
92
+ respond_to do |wants|
93
+ wants.html { render 'index' }
94
+ end
64
95
  end
65
96
  end
66
97
 
@@ -72,10 +103,6 @@ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the pr
72
103
  long to fit in 72 characters
73
104
  ```
74
105
 
75
- * Make sure you have added the necessary tests for your changes.
76
- * Run _all_ the tests to assure nothing else was accidentally broken.
77
- * When you are ready to submit a pull request
78
-
79
106
  ### Submitting Changes
80
107
 
81
108
  * Read the article ["Using Pull Requests"](https://help.github.com/articles/using-pull-requests) on GitHub.
@@ -84,28 +111,45 @@ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the pr
84
111
  * `git pull --rebase`
85
112
  * `git checkout <your-branch>`
86
113
  * `git rebase master`
87
- * It is likely a good idea to run your tests again.
114
+ * It is a good idea to run your tests again.
88
115
  * If you've made more than one commit take a moment to consider whether squashing commits together would help improve their logical grouping.
89
116
  * [Detailed Walkthrough of One Pull Request per Commit](http://ndlib.github.io/practices/one-commit-per-pull-request/)
90
- * `git rebase --interactive HEAD~<number-of-commits>` ([See Github help](https://help.github.com/articles/interactive-rebase))
91
- * To determine the number of commits on your branch: `git log master..<your-branch> --oneline | wc -l`
117
+ * `git rebase --interactive master` ([See Github help](https://help.github.com/articles/interactive-rebase))
92
118
  * Squashing your branch's changes into one commit is "good form" and helps the person merging your request to see everything that is going on.
93
119
  * Push your changes to a topic branch in your fork of the repository.
94
120
  * Submit a pull request from your fork to the project.
95
121
 
96
- ### Merging Changes
122
+ ### Reviewing and Merging Changes
123
+
124
+ We adopted [Github's Pull Request Review](https://help.github.com/articles/about-pull-request-reviews/) for our repositories.
125
+ Common checks that may occur in our repositories:
126
+
127
+ 1. Travis CI - where our automated tests are running
128
+ 2. Hound CI - where we check for style violations
129
+ 3. Approval Required - Github enforces at least one person approve a pull request. Also, all reviewers that have chimed in must approve.
130
+ 4. CodeClimate - is our code remaining healthy (at least according to static code analysis)
131
+
132
+ If one or more of the required checks failed (or are incomplete), the code should not be merged (and the UI will not allow it). If all of the checks have passed, then anyone on the project (including the pull request submitter) may merge the code.
133
+
134
+ *Example: Carolyn submits a pull request, Justin reviews the pull request and approves. However, Justin is still waiting on other checks (Travis CI is usually the culprit), so he does not merge the pull request. Eventually, all of the checks pass. At this point, Carolyn or anyone else may merge the pull request.*
135
+
136
+ #### Things to Consider When Reviewing
137
+
138
+ First, the person contributing the code is putting themselves out there. Be mindful of what you say in a review.
139
+
140
+ * Ask clarifying questions
141
+ * State your understanding and expectations
142
+ * Provide example code or alternate solutions, and explain why
143
+
144
+ This is your chance for a mentoring moment of another developer. Take time to give an honest and thorough review of what has changed. Things to consider:
97
145
 
98
- * It is considered "poor from" to merge your own request.
99
- * Please take the time to review the changes and get a sense of what is being changed. Things to consider:
100
146
  * Does the commit message explain what is going on?
101
- * Does the code changes have tests? _Not all changes need new tests, some changes are refactorings_
147
+ * Does the code changes have tests? _Not all changes need new tests, some changes are refactors_
148
+ * Do new or changed methods, modules, and classes have documentation?
102
149
  * Does the commit contain more than it should? Are two separate concerns being addressed in one commit?
103
- * Did the Travis tests complete successfully?
104
- * If you are uncertain, bring other contributors into the conversation by creating a comment that includes their @username.
105
- * If you like the pull request, but want others to chime in, create a +1 comment and tag a user.
150
+ * Does the description of the new/changed specs match your understanding of what the spec is doing?
106
151
 
107
- ## New Developers
108
- A great way to get new developers involved and to learn the process is to have them go through the Hierarchy of Promises and create a pull request to improve it.
152
+ If you are uncertain, bring other contributors into the conversation by assigning them as a reviewer.
109
153
 
110
154
  # Additional Resources
111
155
 
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  group :development, :test do
4
- gem 'rubocop', '~> 0.37.0', require: false
5
- gem 'rubocop-rspec', '~> 1.3.1', require: false
4
+ gem 'rubocop', '~> 0.46.0', require: false
5
+ gem 'rubocop-rspec', '~> 1.9.1', require: false
6
6
  gem 'pry' unless ENV['CI']
7
7
  gem 'pry-byebug' unless ENV['CI']
8
8
  end
data/README.md CHANGED
@@ -16,7 +16,7 @@ Add these lines to your application's Gemfile:
16
16
 
17
17
  ```ruby
18
18
  gem 'active-fedora', '~> 9.3'
19
- gem 'hydra-pcdm', '~> 0.4'
19
+ gem 'hydra-pcdm', '~> 0.9'
20
20
  ```
21
21
 
22
22
  And then execute:
@@ -1,4 +1,12 @@
1
1
  module Hydra::PCDM
2
+ ##
3
+ # A generic implementation of `PCDM::Collection`.
4
+ #
5
+ # @example creating a generic collection
6
+ # my_collection = Collection.create
7
+ #
8
+ # my_collection.pcdm_collection? # => true
9
+ #
2
10
  class Collection < ActiveFedora::Base
3
11
  include Hydra::PCDM::CollectionBehavior
4
12
  end
@@ -1,12 +1,13 @@
1
1
  module Hydra::PCDM
2
- # behavior:
2
+ ##
3
+ # Implements behavior for PCDM collections.
4
+ #
5
+ # The behavior is summarized as:
3
6
  # 1) Hydra::PCDM::Collection can aggregate (pcdm:hasMember) Hydra::PCDM::Collection (no infinite loop, e.g., A -> B -> C -> A)
4
7
  # 2) Hydra::PCDM::Collection can aggregate (pcdm:hasMember) Hydra::PCDM::Object
5
8
  # 3) Hydra::PCDM::Collection can aggregate (ore:aggregates) Hydra::PCDM::Object (Object related to the Collection)
6
-
7
9
  # 4) Hydra::PCDM::Collection can NOT aggregate non-PCDM object
8
10
  # 5) Hydra::PCDM::Collection can NOT contain (pcdm:hasFile) Hydra::PCDM::File
9
-
10
11
  # 6) Hydra::PCDM::Collection can have descriptive metadata
11
12
  # 7) Hydra::PCDM::Collection can have access metadata
12
13
  #
@@ -18,36 +19,54 @@ module Hydra::PCDM
18
19
  include ::Hydra::PCDM::PcdmBehavior
19
20
  end
20
21
 
22
+ ##
23
+ # @see ActiveSupport::Concern
21
24
  module ClassMethods
25
+ ##
26
+ # @return [Class] the indexer class
22
27
  def indexer
23
28
  Hydra::PCDM::CollectionIndexer
24
29
  end
25
30
 
31
+ ##
32
+ # @return [Class] the validator class
26
33
  def type_validator
27
34
  Validators::PCDMCollectionValidator
28
35
  end
29
36
  end
30
37
 
38
+ ##
39
+ # @return [Enumerable<PCDM::CollectionBehavior>]
31
40
  def collections
32
41
  members.select(&:pcdm_collection?)
33
42
  end
34
43
 
44
+ ##
45
+ # @return [Enumerable<String>]
35
46
  def collection_ids
36
47
  members.select(&:pcdm_collection?).map(&:id)
37
48
  end
38
49
 
50
+ ##
51
+ # @return [Enumerable<PCDM::CollectionBehavior>]
39
52
  def ordered_collections
40
53
  ordered_members.to_a.select(&:pcdm_collection?)
41
54
  end
42
55
 
56
+ ##
57
+ # @return [Enumerable<String>]
43
58
  def ordered_collection_ids
44
59
  ordered_collections.map(&:id)
45
60
  end
46
61
 
62
+ ##
63
+ # @return [Boolean] whether this instance is a PCDM Object.
47
64
  def pcdm_object?
48
65
  false
49
66
  end
50
67
 
68
+ ##
69
+ # @return [Boolean] whether this instance is a PCDM Collection.
51
70
  def pcdm_collection?
52
71
  true
53
72
  end
@@ -1,5 +1,8 @@
1
1
  module Hydra::PCDM
2
- # behavior:
2
+ ##
3
+ # Implements behavior for PCDM objects.
4
+ #
5
+ # The behavior is summarized as:
3
6
  # 1) Hydra::PCDM::Object can aggregate (pcdm:hasMember) Hydra::PCDM::Object
4
7
  # 2) Hydra::PCDM::Object can aggregate (ore:aggregates) Hydra::PCDM::Object (Object related to the Object)
5
8
  # 3) Hydra::PCDM::Object can contain (pcdm:hasFile) Hydra::PCDM::File
@@ -8,6 +11,31 @@ module Hydra::PCDM
8
11
  # 6) Hydra::PCDM::Object can NOT aggregate non-PCDM object
9
12
  # 7) Hydra::PCDM::Object can have descriptive metadata
10
13
  # 8) Hydra::PCDM::Object can have access metadata
14
+ #
15
+ # @example defining an object class and creating an object
16
+ # class Book < ActiveFedora::Base
17
+ # include Hydra::PCDM::ObjectBehavior
18
+ # end
19
+ #
20
+ # my_book = Book.create
21
+ # # #<Book id: "71/3f/07/e0/713f07e0-9d5c-493a-bdb9-7fbfe2160028", head: [], tail: []>
22
+ #
23
+ # my_book.pcdm_object? # => true
24
+ # my_book.pcdm_collection? # => false
25
+ #
26
+ # @example adding a members to an object
27
+ # class Page < ActiveFedora::Base
28
+ # include Hydra::PCDM::ObjectBehavior
29
+ # end
30
+ #
31
+ # my_book = Book.create
32
+ # a_page = Page.create
33
+ #
34
+ # my_book.members << a_page
35
+ # my_book.members # => [a_page]
36
+ #
37
+ # @see PcdmBehavior for details about the base behavior required by
38
+ # this module.
11
39
  module ObjectBehavior
12
40
  extend ActiveSupport::Concern
13
41
 
@@ -15,48 +43,54 @@ module Hydra::PCDM
15
43
  type Vocab::PCDMTerms.Object
16
44
  include ::Hydra::PCDM::PcdmBehavior
17
45
 
46
+ ##
47
+ # @macro [new] directly_contains
48
+ # @!method $1
49
+ # @return [ActiveFedora::Associations::ContainerProxy]
18
50
  directly_contains :files, has_member_relation: Vocab::PCDMTerms.hasFile,
19
51
  class_name: 'Hydra::PCDM::File'
20
-
21
- indirectly_contains :member_of_collections,
22
- has_member_relation: Vocab::PCDMTerms.memberOf,
23
- inserted_content_relation: RDF::Vocab::ORE.proxyFor,
24
- class_name: 'ActiveFedora::Base',
25
- through: 'ActiveFedora::Aggregation::Proxy',
26
- foreign_key: :target,
27
- type_validator: Validators::PCDMCollectionValidator
28
52
  end
29
53
 
54
+ ##
55
+ # @see ActiveSupport::Concern
30
56
  module ClassMethods
57
+ ##
58
+ # @return [Class] the indexer class
31
59
  def indexer
32
60
  Hydra::PCDM::ObjectIndexer
33
61
  end
34
62
 
63
+ ##
64
+ # @return [Class] the validator class
35
65
  def type_validator
36
66
  Validators::PCDMObjectValidator
37
67
  end
38
68
  end
39
69
 
70
+ ##
40
71
  # @return [Boolean] whether this instance is a PCDM Object.
41
72
  def pcdm_object?
42
73
  true
43
74
  end
44
75
 
76
+ ##
45
77
  # @return [Boolean] whether this instance is a PCDM Collection.
46
78
  def pcdm_collection?
47
79
  false
48
80
  end
49
81
 
82
+ ##
83
+ # @return [Enumerable<Hydra::PCDM::ObjectBehavior>]
50
84
  def in_objects
51
85
  member_of.select(&:pcdm_object?).to_a
52
86
  end
53
87
 
54
- def member_of_collection_ids
55
- member_of_collections.map(&:id)
56
- end
57
-
58
- # Returns directly contained files that have the requested RDF Type
88
+ ##
89
+ # Gives directly contained files that have the requested RDF Type
90
+ #
59
91
  # @param [RDF::URI] uri for the desired Type
92
+ # @return [Enumerable<ActiveFedora::File>]
93
+ #
60
94
  # @example
61
95
  # filter_files_by_type(::RDF::URI("http://pcdm.org/ExtractedText"))
62
96
  def filter_files_by_type(uri)
@@ -65,8 +99,12 @@ module Hydra::PCDM
65
99
  end
66
100
  end
67
101
 
102
+ ##
68
103
  # Finds or Initializes directly contained file with the requested RDF Type
104
+ #
69
105
  # @param [RDF::URI] uri for the desired Type
106
+ # @return [ActiveFedora::File]
107
+ #
70
108
  # @example
71
109
  # file_of_type(::RDF::URI("http://pcdm.org/ExtractedText"))
72
110
  def file_of_type(uri)
@@ -1,19 +1,66 @@
1
1
  module Hydra::PCDM
2
+ ##
3
+ # Implements behavior for PCDM objects. This behavior is intended for use with
4
+ # another concern completing the set of defined behavior for a PCDM class
5
+ # (e.g. `PCDM::ObjectBehavior` or `PCDM::CollectionBehavior`).
6
+ #
7
+ # A class mixing in this behavior needs to implement {.type_validator},
8
+ # returning a validator class.
9
+ #
10
+ # @example Defining a minimal PCDM-like thing
11
+ # class MyAbomination < ActiveFedora::Base
12
+ # def type_validator
13
+ # Hydra::PCDM::Validators::PCDMValidator
14
+ # end
15
+ #
16
+ # include Hydra::PCDM::PcdmBehavior
17
+ # end
18
+ #
19
+ # abom = MyAbomination.create
20
+ #
21
+ # @see ActiveFedora::Base
22
+ # @see Hydra::PCDM::Validators
2
23
  module PcdmBehavior
3
24
  extend ActiveSupport::Concern
25
+
4
26
  included do
27
+ ##
28
+ # @macro [new] ordered_aggregation
29
+ # @!method $1
30
+ # @return [ActiveFedora::Associations::ContainerProxy]
5
31
  ordered_aggregation :members,
6
32
  has_member_relation: Vocab::PCDMTerms.hasMember,
7
33
  class_name: 'ActiveFedora::Base',
8
34
  type_validator: type_validator,
9
35
  through: :list_source
36
+
37
+ ##
38
+ # @macro [new] indirectly_contains
39
+ # @!method $1
40
+ # @return [ActiveFedora::Associations::ContainerProxy]
10
41
  indirectly_contains :related_objects, has_member_relation: RDF::Vocab::ORE.aggregates,
11
42
  inserted_content_relation: RDF::Vocab::ORE.proxyFor, class_name: 'ActiveFedora::Base',
12
43
  through: 'ActiveFedora::Aggregation::Proxy', foreign_key: :target,
13
44
  type_validator: Validators::PCDMObjectValidator
45
+
46
+ ##
47
+ # @macro [new] indirectly_contains
48
+ # @!method $1
49
+ # @return [ActiveFedora::Associations::ContainerProxy]
50
+ indirectly_contains :member_of_collections,
51
+ has_member_relation: Vocab::PCDMTerms.memberOf,
52
+ inserted_content_relation: RDF::Vocab::ORE.proxyFor,
53
+ class_name: 'ActiveFedora::Base',
54
+ through: 'ActiveFedora::Aggregation::Proxy',
55
+ foreign_key: :target,
56
+ type_validator: Validators::PCDMCollectionValidator
14
57
  end
15
58
 
59
+ ##
60
+ # @see ActiveSupport::Concern
16
61
  module ClassMethods
62
+ ##
63
+ # @return [#validate!] a validator object
17
64
  def type_validator
18
65
  @type_validator ||= Validators::CompositeValidator.new(
19
66
  super,
@@ -23,39 +70,71 @@ module Hydra::PCDM
23
70
  end
24
71
  end
25
72
 
73
+ ##
74
+ # @return [Enumerable<ActiveFedora::Base>]
26
75
  def member_of
27
76
  return [] if id.nil?
28
77
  ActiveFedora::Base.where(Config.indexing_member_ids_key => id)
29
78
  end
30
79
 
80
+ ##
81
+ # @return [Enumerable<String>] an ordered list of member ids
31
82
  def ordered_member_ids
32
83
  ordered_member_proxies.map(&:target_id)
33
84
  end
34
85
 
86
+ ##
87
+ # Gives the subset of #members that are PCDM objects
88
+ #
89
+ # @return [Enumerable<PCDM::ObjectBehavior>] an enumerable over the members
90
+ # that are PCDM objects
35
91
  def objects
36
92
  members.select(&:pcdm_object?)
37
93
  end
38
94
 
95
+ ##
96
+ # Gives a subset of #member_ids, where all elements are PCDM objects.
97
+ # @return [Enumerable<String>] the object ids
39
98
  def object_ids
40
99
  objects.map(&:id)
41
100
  end
42
101
 
102
+ ##
103
+ # Gives a subset of {#ordered_members}, where all elements are PCDM objects.
104
+ #
105
+ # @return [Enumerable<PCDM::ObjectBehavior>]
43
106
  def ordered_objects
44
107
  ordered_members.to_a.select(&:pcdm_object?)
45
108
  end
46
109
 
110
+ ##
111
+ # @return [Enumerable<String>] an ordered list of member ids
47
112
  def ordered_object_ids
48
113
  ordered_objects.map(&:id)
49
114
  end
50
115
 
116
+ ##
117
+ # @return [Enumerable<Hydra::PCDM::CollectionBehavior>] the collections the
118
+ # object is a member of.
51
119
  def in_collections
52
120
  member_of.select(&:pcdm_collection?).to_a
53
121
  end
54
122
 
123
+ # @return [Enumerable<String>] ids for collections the object is a member of
55
124
  def in_collection_ids
56
125
  in_collections.map(&:id)
57
126
  end
58
127
 
128
+ ##
129
+ # @return [Enumerable<String>]
130
+ def member_of_collection_ids
131
+ member_of_collections.map(&:id)
132
+ end
133
+
134
+ ##
135
+ # @param [ActiveFedora::Base] potential_ancestor the resource to check for
136
+ # ancestorship
137
+ # @return [Boolean] whether the argument is an ancestor of the object
59
138
  def ancestor?(potential_ancestor)
60
139
  ::Hydra::PCDM::AncestorChecker.former_is_ancestor_of_latter?(potential_ancestor, self)
61
140
  end
@@ -1,4 +1,12 @@
1
1
  module Hydra::PCDM
2
+ ##
3
+ # A generic implementation of `PCDM::ObjectBehavior`.
4
+ #
5
+ # @example creating a generic object
6
+ # my_object = Object.create
7
+ #
8
+ # my_object.pcdm_object? # => true
9
+ #
2
10
  class Object < ActiveFedora::Base
3
11
  include Hydra::PCDM::ObjectBehavior
4
12
  end
@@ -1,9 +1,4 @@
1
1
  module Hydra::PCDM
2
2
  class ObjectIndexer < PCDMIndexer
3
- def generate_solr_document
4
- super.tap do |solr_doc|
5
- solr_doc[Config.indexing_member_of_collection_ids_key] = object.member_of_collection_ids
6
- end
7
- end
8
3
  end
9
4
  end
@@ -6,6 +6,7 @@ module Hydra::PCDM
6
6
  solr_doc[Config.indexing_member_ids_key] += object.member_ids
7
7
  solr_doc[Config.indexing_member_ids_key].uniq!
8
8
  solr_doc[Config.indexing_object_ids_key] = object.ordered_object_ids
9
+ solr_doc[Config.indexing_member_of_collection_ids_key] = object.member_of_collection_ids
9
10
  end
10
11
  end
11
12
  end
@@ -1,9 +1,8 @@
1
1
  module Hydra::PCDM::Validators
2
2
  class PCDMObjectValidator
3
3
  def self.validate!(_association, record)
4
- unless record.try(:pcdm_object?)
5
- raise ActiveFedora::AssociationTypeMismatch, "#{record} is not a PCDM object."
6
- end
4
+ raise ActiveFedora::AssociationTypeMismatch, "#{record} is not a PCDM object." unless
5
+ record.try(:pcdm_object?)
7
6
  end
8
7
  end
9
8
  end
@@ -1,9 +1,8 @@
1
1
  module Hydra::PCDM::Validators
2
2
  class PCDMValidator
3
3
  def self.validate!(_reflection, record)
4
- if !record.try(:pcdm_object?) && !record.try(:pcdm_collection?)
5
- raise ActiveFedora::AssociationTypeMismatch, "#{record} is not a PCDM object or collection."
6
- end
4
+ raise ActiveFedora::AssociationTypeMismatch, "#{record} is not a PCDM object or collection." if
5
+ !record.try(:pcdm_object?) && !record.try(:pcdm_collection?)
7
6
  end
8
7
  end
9
8
  end
@@ -1,5 +1,5 @@
1
1
  module Hydra
2
2
  module PCDM
3
- VERSION = '0.9.0'.freeze
3
+ VERSION = '0.10.0'.freeze
4
4
  end
5
5
  end
@@ -495,12 +495,12 @@ describe Hydra::PCDM::Collection do
495
495
  end
496
496
 
497
497
  describe '#ordered_collection_ids' do
498
+ subject { object.ordered_collection_ids }
498
499
  let(:child1) { described_class.new(id: '1') }
499
500
  let(:child2) { described_class.new(id: '2') }
500
501
  let(:object) { described_class.new }
501
- before { object.ordered_members = [child1, child2] }
502
502
 
503
- subject { object.ordered_collection_ids }
503
+ before { object.ordered_members = [child1, child2] }
504
504
 
505
505
  it { is_expected.to eq %w(1 2) }
506
506
  end
@@ -569,6 +569,29 @@ describe Hydra::PCDM::Collection do
569
569
  end
570
570
  end
571
571
 
572
+ describe 'membership in collections' do
573
+ subject do
574
+ collection = described_class.new
575
+ collection.member_of_collections = [collection1, collection2]
576
+ collection
577
+ end
578
+
579
+ let(:collection1) { described_class.create }
580
+ let(:collection2) { described_class.create }
581
+
582
+ describe '#member_of_collections' do
583
+ it 'contains collections the object is a member of' do
584
+ expect(subject.member_of_collections).to match_array [collection1, collection2]
585
+ end
586
+ end
587
+
588
+ describe '#member_of_collection_ids' do
589
+ it 'contains the ids of collections the object is a member of' do
590
+ expect(subject.member_of_collection_ids).to match_array [collection1.id, collection2.id]
591
+ end
592
+ end
593
+ end
594
+
572
595
  describe '.indexer' do
573
596
  after do
574
597
  Object.send(:remove_const, :Foo)
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Hydra::PCDM::File do
4
- let(:file) { described_class.new }
4
+ let(:file) { described_class.new }
5
5
  let(:reloaded) { described_class.new(file.uri) }
6
6
 
7
7
  describe 'when saving' do
@@ -27,22 +27,50 @@ describe Hydra::PCDM::File do
27
27
  let(:date_modified) { Date.parse 'Sat, 09 May 2015 09:00:00 -0400 (EDT)' }
28
28
  let(:content) { 'hello world' }
29
29
  let(:file) { described_class.new.tap { |ds| ds.content = content } }
30
- it 'saves technical metadata' do
31
- skip('pending resolution of PCDM 182') do
32
- file.file_name = 'picture.jpg'
33
- file.file_size = content.length.to_s
34
- file.date_created = date_created
35
- file.has_mime_type = 'application/jpg'
36
- file.date_modified = date_modified
37
- file.byte_order = 'little-endian'
38
- expect(file.save).to be true
39
- expect(reloaded.file_name).to eq ['picture.jpg']
40
- expect(reloaded.file_size).to eq [content.length.to_s]
41
- expect(reloaded.has_mime_type).to eq ['application/jpg']
42
- expect(reloaded.date_created).to eq [date_created]
43
- expect(reloaded.date_modified).to eq [date_modified]
44
- expect(reloaded.byte_order).to eq ['little-endian']
45
- end
30
+
31
+ it 'handles #file_name' do
32
+ name = 'picture.jpg'
33
+ file.file_name = name
34
+ file.save
35
+
36
+ expect(reloaded.file_name).to contain_exactly(name)
37
+ end
38
+
39
+ it 'handles #file_size' do
40
+ file.file_size = content.length.to_s
41
+ file.save
42
+
43
+ expect(reloaded.file_size).to contain_exactly(content.length.to_s)
44
+ end
45
+
46
+ it 'handles #date_created' do
47
+ file.date_created = date_created
48
+ file.save
49
+
50
+ expect(reloaded.date_created).to contain_exactly(date_created)
51
+ end
52
+
53
+ it 'handles #date_modified' do
54
+ file.date_modified = date_modified
55
+ file.save
56
+
57
+ expect(reloaded.date_modified).to contain_exactly(date_modified)
58
+ end
59
+
60
+ it 'handles #byte_order' do
61
+ order = 'little-endian'
62
+ file.byte_order = order
63
+ file.save
64
+
65
+ expect(reloaded.byte_order).to contain_exactly(order)
66
+ end
67
+
68
+ it 'handles #mime_type' do
69
+ ctype = 'application/jpg'
70
+ file.mime_type = ctype
71
+ file.save
72
+
73
+ expect(reloaded.mime_type).to eq ctype
46
74
  end
47
75
 
48
76
  it 'does not save server managed properties' do
@@ -2,16 +2,16 @@ require 'spec_helper'
2
2
 
3
3
  describe Hydra::PCDM::Object do
4
4
  describe '#object_ids' do
5
+ subject { object.ordered_object_ids }
5
6
  let(:child1) { described_class.new(id: '1') }
6
7
  let(:child2) { described_class.new(id: '2') }
7
8
  let(:object) { described_class.new }
9
+
8
10
  before do
9
11
  object.ordered_members << child1
10
12
  object.ordered_members << child2
11
13
  end
12
14
 
13
- subject { object.ordered_object_ids }
14
-
15
15
  it { is_expected.to eq %w(1 2) }
16
16
  end
17
17
 
@@ -63,9 +63,7 @@ describe Hydra::PCDM::Object do
63
63
  end
64
64
  end
65
65
 
66
- before do
67
- object1.ordered_members = [object2]
68
- end
66
+ before { object1.ordered_members = [object2] }
69
67
 
70
68
  it 'raises an error' do
71
69
  expect { object2.ordered_members += [object1] }.to raise_error(error_type, error_message)
@@ -74,9 +72,7 @@ describe Hydra::PCDM::Object do
74
72
  end
75
73
 
76
74
  context 'with more ancestors' do
77
- before do
78
- object2.ordered_members = [object3]
79
- end
75
+ before { object2.ordered_members = [object3] }
80
76
 
81
77
  it 'raises an error' do
82
78
  expect { object3.ordered_members << [object1] }.to raise_error(error_type, error_message)
@@ -85,9 +81,7 @@ describe Hydra::PCDM::Object do
85
81
  end
86
82
 
87
83
  context 'with a more complicated example' do
88
- before do
89
- object3.ordered_members = [object4, object5]
90
- end
84
+ before { object3.ordered_members = [object4, object5] }
91
85
 
92
86
  it 'raises errors' do
93
87
  expect { object4.ordered_members = [object1] }.to raise_error(error_type, error_message)
@@ -147,10 +141,11 @@ describe Hydra::PCDM::Object do
147
141
  end
148
142
 
149
143
  describe 'in_objects' do
150
- let(:object) { described_class.create }
151
- subject { object.in_objects }
152
- let(:collection) { Hydra::PCDM::Collection.new }
144
+ subject { object.in_objects }
145
+ let(:object) { described_class.create }
146
+ let(:collection) { Hydra::PCDM::Collection.new }
153
147
  let(:parent_object) { described_class.new }
148
+
154
149
  context 'using ordered_members' do
155
150
  before do
156
151
  collection.ordered_members = [object]
@@ -178,11 +173,12 @@ describe Hydra::PCDM::Object do
178
173
  end
179
174
 
180
175
  describe 'in_collections' do
181
- subject { object.in_collections }
182
- let(:object) { described_class.create }
183
- let(:collection1) { Hydra::PCDM::Collection.new }
184
- let(:collection2) { Hydra::PCDM::Collection.new }
176
+ subject { object.in_collections }
177
+ let(:object) { described_class.create }
178
+ let(:collection1) { Hydra::PCDM::Collection.new }
179
+ let(:collection2) { Hydra::PCDM::Collection.new }
185
180
  let(:parent_object) { described_class.new }
181
+
186
182
  context 'using ordered_members' do
187
183
  before do
188
184
  collection1.ordered_members = [object]
@@ -219,9 +215,10 @@ describe Hydra::PCDM::Object do
219
215
  subject { object.member_of }
220
216
 
221
217
  context 'when it is aggregated by other objects' do
222
- let(:object) { described_class.create }
223
- let(:collection) { Hydra::PCDM::Collection.new }
218
+ let(:object) { described_class.create }
219
+ let(:collection) { Hydra::PCDM::Collection.new }
224
220
  let(:parent_object) { described_class.new }
221
+
225
222
  before do
226
223
  collection.ordered_members = [object]
227
224
  parent_object.ordered_members = [object]
@@ -284,6 +281,7 @@ describe Hydra::PCDM::Object do
284
281
  @non_pcdm_object = "I'm not a PCDM object"
285
282
  @af_base_object = ActiveFedora::Base.new
286
283
  end
284
+
287
285
  context 'with unacceptable related objects' do
288
286
  let(:error_message) { 'child_related_object must be a pcdm object' }
289
287
 
@@ -317,15 +315,15 @@ describe Hydra::PCDM::Object do
317
315
  expect { @af_base_object.related_objects << @object101 }.to raise_error(NoMethodError)
318
316
  end
319
317
 
320
- it 'NOT accept Hydra::PCDM::Files as parent object' do
318
+ it 'NOT access Hydra::PCDM::Files as parent object' do
321
319
  expect { @file101.related_objects }.to raise_error(NoMethodError)
322
320
  end
323
321
 
324
- it 'NOT accept non-PCDM objects as parent object' do
322
+ it 'NOT access non-PCDM objects as parent object' do
325
323
  expect { @non_pcdm_object.related_objects }.to raise_error(NoMethodError)
326
324
  end
327
325
 
328
- it 'NOT accept AF::Base objects as parent object' do
326
+ it 'NOT access AF::Base objects as parent object' do
329
327
  expect { @af_base_object.related_objects }.to raise_error(NoMethodError)
330
328
  end
331
329
  end
@@ -415,6 +413,7 @@ describe Hydra::PCDM::Object do
415
413
 
416
414
  describe '#files' do
417
415
  subject { described_class.new }
416
+
418
417
  it 'have a files relation' do
419
418
  reflection = subject.reflections[:files]
420
419
  expect(reflection.macro).to eq :directly_contains
@@ -425,6 +424,7 @@ describe Hydra::PCDM::Object do
425
424
 
426
425
  describe 'filtering files' do
427
426
  let(:object) { described_class.create }
427
+
428
428
  let(:thumbnail) do
429
429
  file = object.files.build
430
430
  Hydra::PCDM::AddTypeToFile.call(file, pcdm_thumbnail_uri)
@@ -433,15 +433,12 @@ describe Hydra::PCDM::Object do
433
433
  let(:file) { object.files.build }
434
434
  let(:pcdm_thumbnail_uri) { ::RDF::URI('http://pcdm.org/ThumbnailImage') }
435
435
 
436
- before do
437
- file
438
- end
436
+ before { file }
439
437
 
440
438
  describe 'filter_files_by_type' do
441
439
  context 'when the object has files with that type' do
442
- before do
443
- thumbnail
444
- end
440
+ before { thumbnail }
441
+
445
442
  it 'allows you to filter the contained files by type URI' do
446
443
  expect(object.filter_files_by_type(pcdm_thumbnail_uri)).to eq [thumbnail]
447
444
  end
@@ -449,6 +446,7 @@ describe Hydra::PCDM::Object do
449
446
  expect(object.files).to match_array [file, thumbnail]
450
447
  end
451
448
  end
449
+
452
450
  context 'when the object does NOT have any files with that type' do
453
451
  it 'returns an empty array' do
454
452
  expect(object.filter_files_by_type(pcdm_thumbnail_uri)).to eq []
@@ -458,13 +456,13 @@ describe Hydra::PCDM::Object do
458
456
 
459
457
  describe 'file_of_type' do
460
458
  context 'when the object has files with that type' do
461
- before do
462
- thumbnail
463
- end
459
+ before { thumbnail }
460
+
464
461
  it 'returns the first file with the requested type' do
465
462
  expect(object.file_of_type(pcdm_thumbnail_uri)).to eq thumbnail
466
463
  end
467
464
  end
465
+
468
466
  context 'when the object does NOT have any files with that type' do
469
467
  it 'initializes a contained file with the requested type' do
470
468
  returned_file = object.file_of_type(pcdm_thumbnail_uri)
@@ -477,22 +475,23 @@ describe Hydra::PCDM::Object do
477
475
  end
478
476
 
479
477
  describe '.indexer' do
480
- after do
481
- Object.send(:remove_const, :Foo)
482
- end
478
+ after { Object.send(:remove_const, :Foo) }
483
479
 
484
480
  context 'without overriding' do
481
+ subject { Foo.indexer }
482
+
485
483
  before do
486
484
  class Foo < ActiveFedora::Base
487
485
  include Hydra::PCDM::ObjectBehavior
488
486
  end
489
487
  end
490
488
 
491
- subject { Foo.indexer }
492
489
  it { is_expected.to eq Hydra::PCDM::ObjectIndexer }
493
490
  end
494
491
 
495
492
  context 'when overridden with AS::Concern' do
493
+ subject { Foo.indexer }
494
+
496
495
  before do
497
496
  module IndexingStuff
498
497
  extend ActiveSupport::Concern
@@ -512,15 +511,11 @@ describe Hydra::PCDM::Object do
512
511
  end
513
512
  end
514
513
 
515
- subject { Foo.indexer }
516
514
  it { is_expected.to eq IndexingStuff::AltIndexer }
517
515
  end
518
516
  end
519
517
 
520
518
  describe 'membership in collections' do
521
- let(:collection1) { Hydra::PCDM::Collection.create }
522
- let(:collection2) { Hydra::PCDM::Collection.create }
523
-
524
519
  subject do
525
520
  object = described_class.new
526
521
  object.member_of_collections = [collection1, collection2]
@@ -528,6 +523,9 @@ describe Hydra::PCDM::Object do
528
523
  object
529
524
  end
530
525
 
526
+ let(:collection1) { Hydra::PCDM::Collection.create }
527
+ let(:collection2) { Hydra::PCDM::Collection.create }
528
+
531
529
  describe '#member_of_collections' do
532
530
  it 'contains collections the object is a member of' do
533
531
  expect(subject.member_of_collections).to match_array [collection1, collection2]
@@ -4,13 +4,10 @@ describe Hydra::PCDM::ObjectIndexer do
4
4
  let(:object) { Hydra::PCDM::Object.new }
5
5
  let(:child_object1) { Hydra::PCDM::Object.new(id: '123') }
6
6
  let(:child_object2) { Hydra::PCDM::Object.new(id: '456') }
7
- let(:collection1) { Hydra::PCDM::Collection.new(id: 'abc') }
8
- let(:collection2) { Hydra::PCDM::Collection.new(id: 'def') }
9
7
  let(:indexer) { described_class.new(object) }
10
8
 
11
9
  before do
12
10
  allow(object).to receive(:ordered_object_ids).and_return([child_object1.id, child_object2.id])
13
- allow(object).to receive(:member_of_collection_ids).and_return([collection1.id, collection2.id])
14
11
  end
15
12
 
16
13
  describe '#generate_solr_document' do
@@ -18,7 +15,6 @@ describe Hydra::PCDM::ObjectIndexer do
18
15
 
19
16
  it 'has fields' do
20
17
  expect(subject[Hydra::PCDM::Config.indexing_object_ids_key]).to eq %w(123 456)
21
- expect(subject[Hydra::PCDM::Config.indexing_member_of_collection_ids_key]).to eq %w(abc def)
22
18
  end
23
19
  end
24
20
  end
@@ -4,9 +4,12 @@ describe Hydra::PCDM::PCDMIndexer do
4
4
  let(:collection) { Hydra::PCDM::Collection.new }
5
5
  let(:member_ids) { %w(123 456 789) }
6
6
  let(:indexer) { described_class.new(collection) }
7
+ let(:collection1) { Hydra::PCDM::Collection.new(id: 'abc') }
8
+ let(:collection2) { Hydra::PCDM::Collection.new(id: 'def') }
7
9
 
8
10
  before do
9
11
  allow(collection).to receive(:member_ids).and_return(member_ids)
12
+ allow(collection).to receive(:member_of_collection_ids).and_return([collection1.id, collection2.id])
10
13
  end
11
14
 
12
15
  describe '#generate_solr_document' do
@@ -14,6 +17,7 @@ describe Hydra::PCDM::PCDMIndexer do
14
17
 
15
18
  it 'has fields' do
16
19
  expect(subject[Hydra::PCDM::Config.indexing_member_ids_key]).to eq %w(123 456 789)
20
+ expect(subject[Hydra::PCDM::Config.indexing_member_of_collection_ids_key]).to eq %w(abc def)
17
21
  end
18
22
  end
19
23
  end
@@ -9,14 +9,16 @@ describe Hydra::PCDM::GetMimeTypeForFile do
9
9
  end
10
10
 
11
11
  context 'with a standard file type' do
12
+ subject { described_class.call(path) }
12
13
  let(:path) { '/path/file.jpg' }
13
- subject { described_class.call(path) }
14
+
14
15
  it { is_expected.to eql 'image/jpeg' }
15
16
  end
16
17
 
17
18
  context 'with an unknown file type' do
19
+ subject { described_class.call(path) }
18
20
  let(:path) { '/path/file.jkl' }
19
- subject { described_class.call(path) }
21
+
20
22
  it { is_expected.to eql 'application/octet-stream' }
21
23
  end
22
24
  end
@@ -3,13 +3,11 @@ require 'simplecov'
3
3
  require 'coveralls'
4
4
 
5
5
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
6
- [
7
- SimpleCov::Formatter::HTMLFormatter,
8
- Coveralls::SimpleCov::Formatter
9
- ])
10
- SimpleCov.start do
11
- add_filter '/spec'
12
- end
6
+ [SimpleCov::Formatter::HTMLFormatter,
7
+ Coveralls::SimpleCov::Formatter]
8
+ )
9
+
10
+ SimpleCov.start { add_filter '/spec' }
13
11
 
14
12
  require 'bundler/setup'
15
13
  Bundler.setup
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hydra-pcdm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - E. Lynette Rayle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-31 00:00:00.000000000 Z
11
+ date: 2017-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active-fedora
@@ -216,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
216
216
  version: '0'
217
217
  requirements: []
218
218
  rubyforge_project:
219
- rubygems_version: 2.5.1
219
+ rubygems_version: 2.6.8
220
220
  signing_key:
221
221
  specification_version: 4
222
222
  summary: Portland Common Data Model (PCDM)