• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / pdc_describe / 1aaf6302-d8cf-4943-bb96-5e86951c32a3

pending completion
1aaf6302-d8cf-4943-bb96-5e86951c32a3

Pull #1079

circleci

Bess Sadler
Nil safe doi gsub
Pull Request #1079: Nil safe collection title

2 of 2 new or added lines in 1 file covered. (100.0%)

1777 of 2063 relevant lines covered (86.14%)

100.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/app/models/pdc_metadata/resource.rb
1
# frozen_string_literal: true
2
module PDCMetadata
1✔
3
  # Represents a PUL Datacite resource
4
  # https://support.datacite.org/docs/datacite-metadata-schema-v44-properties-overview
5

6
  def self.fuzzy_match(obj, value)
1✔
7
    obj.key.to_s == value or obj.value.casecmp(value).zero?
×
8
  end
9

10
  class Resource
1✔
11
    attr_accessor :creators, :titles, :publisher, :publication_year, :resource_type, :resource_type_general,
1✔
12
      :description, :doi, :ark, :rights, :version_number, :collection_tags, :keywords, :related_objects,
13
      :funders, :organizational_contributors, :domains
14

15
    # rubocop:disable Metrics/MethodLength
16
    def initialize(doi: nil, title: nil, resource_type: nil, resource_type_general: nil, creators: [], description: nil)
1✔
17
      @titles = []
1,309✔
18
      @titles << PDCMetadata::Title.new(title: title) unless title.nil?
1,309✔
19
      @description = description
1,309✔
20
      @collection_tags = []
1,309✔
21
      @creators = creators
1,309✔
22
      @resource_type = resource_type || "Dataset"
1,309✔
23
      @resource_type_general = resource_type_general || self.class.default_resource_type_general
1,309✔
24
      @publisher = "Princeton University"
1,309✔
25
      @publication_year = Time.zone.today.year
1,309✔
26
      @ark = nil
1,309✔
27
      @doi = doi
1,309✔
28
      @rights = nil
1,309✔
29
      @version_number = "1"
1,309✔
30
      @related_objects = []
1,309✔
31
      @keywords = []
1,309✔
32
      @contributors = []
1,309✔
33
      @organizational_contributors = []
1,309✔
34
      @funders = []
1,309✔
35
      @domains = []
1,309✔
36
    end
37
    # rubocop:enable Metrics/MethodLength
38

39
    def accessors
1✔
40
      setters = methods.map(&:to_s).filter { |s| s.match?(/\w=$/) }
5,250✔
41
      setters.map { |s| s.delete("=").to_sym }
665✔
42
    end
43

44
    def individual_contributors
1✔
45
      @contributors
1,265✔
46
    end
47

48
    def individual_contributors=(value)
1✔
49
      @contributors = value
45✔
50
    end
51

52
    def identifier
1✔
53
      @doi
×
54
    end
55

56
    def identifier_type
1✔
57
      return nil if @doi.nil?
×
58
      "DOI"
×
59
    end
60

61
    def main_title
1✔
62
      @titles.find(&:main?)&.title
950✔
63
    end
64

65
    def other_titles
1✔
66
      @titles.select { |title| title.main? == false }
130✔
67
    end
68

69
    def to_xml
1✔
70
      xml_declaration = '<?xml version="1.0"?>'
19✔
71
      xml_body = PDCSerialization::Datacite.new_from_work_resource(self).to_xml
19✔
72
      xml_declaration + "\n" + xml_body + "\n"
19✔
73
    end
74

75
    class << self
1✔
76
      # Creates a PDCMetadata::Resource from a JSONB postgres field
77
      #  This jsonb_hash can be created by running JSON.parse(pdc_metadata_resource.to_json)
78
      #   or by loading it from the work.metadata jsonb field
79
      def new_from_jsonb(jsonb_hash)
1✔
80
        resource = PDCMetadata::Resource.new
1,083✔
81
        return resource if jsonb_hash.blank?
1,083✔
82
        set_basics(resource, jsonb_hash)
1,044✔
83
        set_curator_controlled_metadata(resource, jsonb_hash)
1,044✔
84
        set_additional_metadata(resource, jsonb_hash)
1,044✔
85
        set_titles(resource, jsonb_hash)
1,044✔
86
        set_creators(resource, jsonb_hash)
1,044✔
87
        set_individual_contributors(resource, jsonb_hash)
1,044✔
88
        set_organizational_contributors(resource, jsonb_hash)
1,044✔
89
        set_related_objects(resource, jsonb_hash)
1,044✔
90
        set_funders(resource, jsonb_hash)
1,044✔
91

92
        resource
1,044✔
93
      end
94

95
      def resource_type_general_values
1✔
96
        Datacite::Mapping::ResourceTypeGeneral.map(&:value)
32✔
97
      end
98

99
      def default_resource_type_general
1✔
100
        "Dataset"
1,309✔
101
      end
102

103
      private
1✔
104

105
        def rights(form_rights)
1✔
106
          PDCMetadata::Rights.find(form_rights["identifier"]) if form_rights
1,044✔
107
        end
108

109
        def set_basics(resource, hash)
1✔
110
          resource.description = hash["description"]
1,044✔
111
          resource.publisher = hash["publisher"]
1,044✔
112
          resource.publication_year = hash["publication_year"]
1,044✔
113
          resource.rights = rights(hash["rights"])
1,044✔
114
          resource.domains = hash["domains"] || []
1,044✔
115
        end
116

117
        def set_curator_controlled_metadata(resource, hash)
1✔
118
          resource.doi = hash["doi"]
1,044✔
119
          resource.ark = hash["ark"]
1,044✔
120
          resource.version_number = hash["version_number"]
1,044✔
121
          resource.collection_tags = hash["collection_tags"] || []
1,044✔
122
          resource.resource_type = hash["resource_type"]
1,044✔
123

124
          # TODO: Older records have a different format.
125
          # When we migrate these, then this can be removed.
126
          resource_type_general = hash["resource_type_general"]
1,044✔
127
          unless resource_type_general.blank? || Datacite::Mapping::ResourceTypeGeneral.find_by_value(resource_type_general)
1,044✔
128
            resource_type_general = ::Datacite::Mapping::ResourceTypeGeneral.find do |obj|
×
129
              ::PDCMetadata.fuzzy_match(obj, resource_type_general)
×
130
            end.value
131
          end
132
          resource.resource_type_general = resource_type_general
1,044✔
133
        end
134

135
        def set_additional_metadata(resource, hash)
1✔
136
          resource.keywords = hash["keywords"] || []
1,044✔
137
        end
138

139
        def set_titles(resource, hash)
1✔
140
          titles = hash["titles"] || []
1,044✔
141

142
          titles.each do |title|
1,044✔
143
            resource.titles << PDCMetadata::Title.new(title: title["title"], title_type: title["title_type"])
1,049✔
144
          end
145
        end
146

147
        def set_related_objects(resource, hash)
1✔
148
          related_objects = hash["related_objects"] || []
1,044✔
149

150
          related_objects.each do |related_object|
1,044✔
151
            next if related_object["related_identifier"].blank? && related_object["related_identifier_type"].blank?
74✔
152
            resource.related_objects << PDCMetadata::RelatedObject.new(
74✔
153
                                          related_identifier: related_object["related_identifier"],
154
                                          related_identifier_type: related_object["related_identifier_type"],
155
                                          relation_type: related_object["relation_type"]
156
                                        )
157
          end
158
        end
159

160
        def set_creators(resource, hash)
1✔
161
          creators = hash["creators"] || []
1,044✔
162

163
          creators.each do |creator|
1,044✔
164
            resource.creators << Creator.from_hash(creator)
1,858✔
165
          end
166
          resource.creators.sort_by!(&:sequence)
1,044✔
167
        end
168

169
        def set_individual_contributors(resource, hash)
1✔
170
          individual_contributors = hash["contributors"] || []
1,044✔
171

172
          individual_contributors.each do |contributor|
1,044✔
173
            resource.individual_contributors << Creator.individual_contributor_from_hash(contributor)
15✔
174
          end
175
          resource.individual_contributors.sort_by!(&:sequence)
1,044✔
176
        end
177

178
        def set_organizational_contributors(resource, hash)
1✔
179
          organizational_contributors = hash["organizational_contributors"] || []
1,044✔
180

181
          organizational_contributors.each do |contributor|
1,044✔
182
            resource.organizational_contributors << Creator.organizational_contributor_from_hash(contributor)
×
183
          end
184
        end
185

186
        def set_funders(resource, hash)
1✔
187
          funders = hash["funders"] || []
1,044✔
188

189
          funders.each do |funder|
1,044✔
190
            resource.funders << Funder.funder_from_hash(funder)
149✔
191
          end
192
          # TODO: Make funders reorderable
193
          # resource.funders.sort_by!(&:sequence)
194
        end
195
    end
196
  end
197
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc