cocina_display 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68f245cc22043da571e4a9abf0f0fedd613fc19035c4a50369b95400c76573b5
4
- data.tar.gz: 86de10bbfcabc44d23d9b3df480eb6b3f0d28b358c9f4fece1ece089cf5cca20
3
+ metadata.gz: 7faaded226886ab37cfbff854b64721c55964959089a1675706ae6160d4a1a5c
4
+ data.tar.gz: 111b995bfdf70805eb7a613bf5f221bacf101be1ed3f9ad6fb2407266c7a35ab
5
5
  SHA512:
6
- metadata.gz: 9ea9ac44480ac83533704c06705f0f6f078ac4065b27756cea527f4110ab99b3bafcfcf525097368005e89534bed78a8bb17a81cb96dc1c48c479a5052b877f6
7
- data.tar.gz: 3600cc57ec5e162cb39e2547fa09c9dc7aadc87742146649a0c9d3427ad6c8a2eede1357103af6d4cab531e51d93136a69f075de0995c86daaf471fac2ff08c7
6
+ metadata.gz: 6a8586d41059d8880ac29c48f564907a51b718dc7812f2314e564032e1f19722d97620755cd53f52aa927e17e45dbfab79b56936c022255f2c22c3147e2c110c
7
+ data.tar.gz: 58ddd5de3cfe25d78904c24c1edaed72d4212eb7149b58b3b6e5c216390db75acc0c8ad81c039c9c712da99480842df2cab27c70573c848e2cb9377f0a31b909
@@ -16,6 +16,7 @@ require_relative "concerns/subjects"
16
16
  require_relative "concerns/forms"
17
17
  require_relative "concerns/languages"
18
18
  require_relative "concerns/geospatial"
19
+ require_relative "concerns/structural"
19
20
  require_relative "utils"
20
21
 
21
22
  module CocinaDisplay
@@ -30,6 +31,7 @@ module CocinaDisplay
30
31
  include CocinaDisplay::Concerns::Forms
31
32
  include CocinaDisplay::Concerns::Languages
32
33
  include CocinaDisplay::Concerns::Geospatial
34
+ include CocinaDisplay::Concerns::Structural
33
35
 
34
36
  # Fetch a public Cocina document from PURL and create a CocinaRecord.
35
37
  # @note This is intended to be used in development or testing only.
@@ -109,16 +111,27 @@ module CocinaDisplay
109
111
  content_type == "collection"
110
112
  end
111
113
 
112
- # Traverse nested FileSets and return an enumerator over their files.
113
- # Each file is a +Hash+.
114
- # @return [Enumerator] Enumerator over file hashes
115
- # @example
116
- # record.files.each do |file|
117
- # puts file["filename"] #=> "image1.jpg"
118
- # puts file["size"] #=> 123456
119
- # end
120
- def files
121
- path("$.structural.contains.*.structural.contains[*]")
114
+ # Resources related to the object.
115
+ # @return [Array<CocinaDisplay::RelatedResource>]
116
+ def related_resources
117
+ @related_resources ||= path("$.description.relatedResource[*]").map { |res| RelatedResource.new(res) }
118
+ end
119
+ end
120
+
121
+ # A resource related to the record; behaves like a CocinaRecord.
122
+ # @note Related resources have no structural metadata.
123
+ class RelatedResource < CocinaRecord
124
+ # Description of the relation to the source record.
125
+ # @return [String]
126
+ # @example "is part of"
127
+ # @see https://github.com/sul-dlss/cocina-models/blob/main/docs/description_types.md#relatedresource-types
128
+ attr_reader :type
129
+
130
+ # Restructure the hash so that everything is under "description" key, since
131
+ # it's all descriptive metadata. This makes CocinaRecord methods work.
132
+ def initialize(cocina_doc)
133
+ @type = cocina_doc["type"]
134
+ @cocina_doc = {"description" => cocina_doc.except("type")}
122
135
  end
123
136
  end
124
137
  end
@@ -0,0 +1,41 @@
1
+ require "active_support/number_helper/number_to_human_size_converter"
2
+
3
+ module CocinaDisplay
4
+ module Concerns
5
+ # Methods for inspecting structural metadata (e.g. file hierarchy)
6
+ module Structural
7
+ # Structured data for all individual files in the object.
8
+ # Traverses nested FileSet structure to return a flattened array.
9
+ # @return [Array<Hash>]
10
+ # @example
11
+ # record.files.each do |file|
12
+ # puts file["filename"] #=> "image1.jpg"
13
+ # puts file["size"] #=> 123456
14
+ # end
15
+ def files
16
+ @files ||= path("$.structural.contains.*.structural.contains.*").search
17
+ end
18
+
19
+ # All unique MIME types of files in this object.
20
+ # @return [Array<String>]
21
+ # @example ["image/jpeg", "application/pdf"]
22
+ def file_mime_types
23
+ files.pluck("hasMimeType").uniq
24
+ end
25
+
26
+ # Human-readable string representation of {total_file_size_int}.
27
+ # @return [String]
28
+ # @example "2.5 MB"
29
+ def total_file_size_str
30
+ ActiveSupport::NumberHelper.number_to_human_size(total_file_size_int)
31
+ end
32
+
33
+ # Summed size of all files in bytes.
34
+ # @return [Integer]
35
+ # @example 2621440
36
+ def total_file_size_int
37
+ files.pluck("size").sum
38
+ end
39
+ end
40
+ end
41
+ end
@@ -63,6 +63,12 @@ module CocinaDisplay
63
63
  roles.any?(&:publisher?)
64
64
  end
65
65
 
66
+ # Does this contributor have a role that indicates they are a funder?
67
+ # @return [Boolean]
68
+ def funder?
69
+ roles.any?(&:funder?)
70
+ end
71
+
66
72
  # Does this contributor have any roles defined?
67
73
  # @return [Boolean]
68
74
  def role?
@@ -77,6 +83,20 @@ module CocinaDisplay
77
83
  names.map { |name| name.to_s(with_date: with_date) }.first
78
84
  end
79
85
 
86
+ # The full forename for the contributor from the first available name.
87
+ # @see Contributor::Name::forename_str
88
+ # @return [String, nil]
89
+ def forename
90
+ names.map(&:forename_str).first.presence
91
+ end
92
+
93
+ # The full surname for the contributor from the first available name.
94
+ # @see Contributor::Name::surname_str
95
+ # @return [String, nil]
96
+ def surname
97
+ names.map(&:surname_str).first.presence
98
+ end
99
+
80
100
  # A string representation of the contributor's roles, formatted for display.
81
101
  # If there are multiple roles, they are joined with commas.
82
102
  # @return [String]
@@ -37,8 +37,6 @@ module CocinaDisplay
37
37
  end
38
38
  end
39
39
 
40
- private
41
-
42
40
  # The full name as a string, combining all name components and terms of address.
43
41
  # @return [String]
44
42
  def full_name_str
@@ -56,33 +54,35 @@ module CocinaDisplay
56
54
  # Otherwise, fall back to any names explicitly marked as "name" or untyped.
57
55
  # @return [Array<String>]
58
56
  def name_components
59
- [surname_str, forename_ordinal_str].compact_blank.presence || Array(name_values["name"])
57
+ [surname_str, forename_str].compact_blank.presence || Array(name_values["name"])
60
58
  end
61
59
 
62
- # Flatten all forenames and ordinals into a single string.
60
+ # Flatten all terms of address into a comma-delimited string.
63
61
  # @return [String]
64
- def forename_ordinal_str
65
- Utils.compact_and_join(Array(name_values["forename"]) + Array(name_values["ordinal"]), delimiter: " ")
62
+ def terms_of_address_str
63
+ Utils.compact_and_join(Array(name_values["term of address"]), delimiter: ", ")
66
64
  end
67
65
 
68
- # Flatten all terms of address into a single string.
66
+ # Flatten all forename values and ordinals into a whitespace-delimited string.
69
67
  # @return [String]
70
- def terms_of_address_str
71
- Utils.compact_and_join(Array(name_values["term of address"]), delimiter: ", ")
68
+ def forename_str
69
+ Utils.compact_and_join(Array(name_values["forename"]) + Array(name_values["ordinal"]), delimiter: " ")
72
70
  end
73
71
 
74
- # Flatten all surnames into a single string.
72
+ # Flatten all surname values into a whitespace-delimited string.
75
73
  # @return [String]
76
74
  def surname_str
77
75
  Utils.compact_and_join(Array(name_values["surname"]), delimiter: " ")
78
76
  end
79
77
 
80
- # Flatten all life and activity dates into a single string.
78
+ # Flatten all life and activity dates into a comma-delimited string.
81
79
  # @return [String]
82
80
  def dates_str
83
81
  Utils.compact_and_join(Array(name_values["life dates"]) + Array(name_values["activity dates"]), delimiter: ", ")
84
82
  end
85
83
 
84
+ private
85
+
86
86
  # A hash mapping destructured name types to their values.
87
87
  # Name values with no type are grouped under "name".
88
88
  # @return [Hash<String, Array<String>>]
@@ -30,7 +30,7 @@ module CocinaDisplay
30
30
  # Does this role indicate the contributor is an author?
31
31
  # @return [Boolean]
32
32
  def author?
33
- to_s =~ /^(author|creator)/i
33
+ to_s =~ /^(author|creator|primary investigator)/i
34
34
  end
35
35
 
36
36
  # Does this role indicate the contributor is a publisher?
@@ -39,6 +39,12 @@ module CocinaDisplay
39
39
  to_s =~ /^publisher/i
40
40
  end
41
41
 
42
+ # Does this role indicate the contributor is a funder?
43
+ # @return [Boolean]
44
+ def funder?
45
+ to_s =~ /^funder/i
46
+ end
47
+
42
48
  private
43
49
 
44
50
  # Does this role have a MARC relator code?
@@ -2,5 +2,5 @@
2
2
 
3
3
  # :nodoc:
4
4
  module CocinaDisplay
5
- VERSION = "1.0.0" # :nodoc:
5
+ VERSION = "1.1.0" # :nodoc:
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocina_display
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Budak
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-08-08 00:00:00.000000000 Z
11
+ date: 2025-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: janeway-jsonpath
@@ -219,6 +219,7 @@ files:
219
219
  - lib/cocina_display/concerns/geospatial.rb
220
220
  - lib/cocina_display/concerns/identifiers.rb
221
221
  - lib/cocina_display/concerns/languages.rb
222
+ - lib/cocina_display/concerns/structural.rb
222
223
  - lib/cocina_display/concerns/subjects.rb
223
224
  - lib/cocina_display/concerns/titles.rb
224
225
  - lib/cocina_display/contributors/contributor.rb