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

pulibrary / pdc_describe / cace366a-ffad-45f1-9b60-678e607fa527

14 May 2024 02:21PM UTC coverage: 60.862% (-35.0%) from 95.908%
cace366a-ffad-45f1-9b60-678e607fa527

push

circleci

jrgriffiniii
wip

1 of 3 new or added lines in 2 files covered. (33.33%)

1194 existing lines in 57 files now uncovered.

2076 of 3411 relevant lines covered (60.86%)

22.71 hits per line

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

72.97
/app/services/work_validator.rb
1
# frozen_string_literal: true
2
class WorkValidator
1✔
3
  attr_reader :work
1✔
4

5
  delegate :errors, :metadata, :resource, :ark, :doi, :user_entered_doi, :id, :group,
1✔
6
           :pre_curation_uploads, :post_curation_uploads, to: :work
7

8
  def initialize(work)
1✔
9
    @work = work
55✔
10
  end
11

12
  def valid?
1✔
13
    if work.none?
58✔
14
      validate_ids
14✔
15
    elsif work.draft?
44✔
16
      valid_to_draft
40✔
17
    else
18
      valid_to_submit
4✔
19
    end
20
  end
21

22
  def valid_to_draft(*)
1✔
23
    errors.add(:base, "Must provide a title") if resource.main_title.blank?
49✔
24
    validate_ark
49✔
25
    validate_creators
49✔
26
    validate_related_objects if resource.present? && !resource.related_objects.empty?
49✔
27
    errors.count == 0
49✔
28
  end
29

30
  def valid_to_complete(*args)
1✔
31
    validate_files
1✔
32
    valid_to_submit(args)
1✔
33
  end
34

35
  def valid_to_submit(*args)
1✔
36
    valid_to_draft(args)
5✔
37
    validate_metadata
5✔
38
    if errors.count == 0
5✔
39
      valid_datacite? # test if the datacite update will be valid
5✔
40
    end
41
    errors.count == 0
5✔
42
  end
43

44
  def valid_to_approve(user)
1✔
UNCOV
45
    if resource.doi.blank?
×
UNCOV
46
      errors.add :base, "DOI must be present for a work to be approved"
×
47
    end
UNCOV
48
    valid_to_submit(user)
×
UNCOV
49
    unless user.has_role? :group_admin, group
×
UNCOV
50
      errors.add :base, "Unauthorized to Approve"
×
51
    end
UNCOV
52
    validate_files
×
UNCOV
53
    if pre_curation_uploads.empty? && post_curation_uploads.empty?
×
UNCOV
54
      errors.add :base, "Uploads must be present for a work to be approved"
×
55
    end
UNCOV
56
    errors.count == 0
×
57
  end
58

59
  def valid_datacite?
1✔
60
    datacite_serialization = resource.datacite_serialization
5✔
61
    datacite_serialization.valid?
5✔
62
    datacite_serialization.errors.each { |error| errors.add(:base, error) }
5✔
63
    errors.count == 0
5✔
64
  rescue ArgumentError => error
UNCOV
65
    argument_path = error.backtrace_locations.first.path
×
UNCOV
66
    argument_file = argument_path.split("/").last
×
UNCOV
67
    argument_name = argument_file.split(".").first
×
UNCOV
68
    errors.add(:base, "#{argument_name.titleize}: #{error.message}")
×
UNCOV
69
    false
×
70
  end
71

72
  private
1✔
73

74
    def validate_ark
1✔
75
      return if ark.blank?
49✔
76
      return false unless unique_ark
28✔
77
      first_save = id.blank?
28✔
78
      changed_value = metadata["ark"] != ark
28✔
79
      if first_save || changed_value
28✔
80
        errors.add(:base, "Invalid ARK provided for the Work: #{ark}") unless Ark.valid?(ark)
17✔
81
      end
82
    end
83

84
    def validate_related_objects
1✔
85
      return if resource.related_objects.empty?
25✔
86
      invalid = resource.related_objects.reject(&:valid?)
23✔
87
      if invalid.count.positive?
23✔
UNCOV
88
        related_object_errors = "Related Objects are invalid: "
×
UNCOV
89
        prev_errors = errors.to_a
×
UNCOV
90
        prev_related_object_errors = prev_errors.map { |e| e.include?(related_object_errors) }.reduce(:|)
×
91

UNCOV
92
        errors.add(:base, "#{related_object_errors}#{invalid.map(&:errors).join(', ')}") unless prev_related_object_errors
×
93
      end
94
    end
95

96
    def validate_creators
1✔
97
      if resource.creators.count == 0
54✔
UNCOV
98
        errors.add(:base, "Must provide at least one Creator")
×
99
      else
100
        resource.creators.each do |creator|
54✔
101
          if creator.orcid.present? && Orcid.invalid?(creator.orcid)
353✔
UNCOV
102
            errors.add(:base, "ORCID for creator #{creator.value} is not in format 0000-0000-0000-0000")
×
103
          end
104
        end
105
      end
106
    end
107

108
    def validate_required_metadata
1✔
109
      return if metadata.blank?
5✔
110
      errors.add(:base, "Must provide a title") if resource.main_title.blank?
5✔
111
      validate_creators
5✔
112
    end
113

114
    def validate_doi
1✔
115
      return true unless user_entered_doi
14✔
116
      return false unless unique_doi
1✔
117
      if /^10.\d{4,9}\/[-._;()\/:a-z0-9\-]+$/.match?(doi.downcase)
1✔
118
        response = Faraday.get("#{Rails.configuration.datacite.doi_url}#{doi}")
1✔
119
        errors.add(:base, "Invalid DOI: can not verify it's authenticity") unless response.success? || response.status == 302
1✔
120
      else
UNCOV
121
        errors.add(:base, "Invalid DOI: does not match format")
×
122
      end
123
      errors.count == 0
1✔
124
    end
125

126
    def unique_ark
1✔
127
      return true if ark.blank?
42✔
128
      other_record = Work.find_by_ark(ark)
30✔
129
      return true if other_record == work
10✔
UNCOV
130
      errors.add(:base, "Invalid ARK: It has already been applied to another work #{other_record.id}")
×
UNCOV
131
      false
×
132
    rescue ActiveRecord::RecordNotFound
133
      true
20✔
134
    end
135

136
    def validate_ids
1✔
137
      validate_doi
14✔
138
      unique_ark
14✔
139
    end
140

141
    def unique_doi
1✔
142
      other_record = Work.find_by_doi(doi)
1✔
UNCOV
143
      return true if other_record == work
×
UNCOV
144
      errors.add(:base, "Invalid DOI: It has already been applied to another work #{other_record.id}")
×
UNCOV
145
      false
×
146
    rescue ActiveRecord::RecordNotFound
147
      true
1✔
148
    end
149

150
    def validate_metadata
1✔
151
      return if metadata.blank?
5✔
152
      validate_required_metadata
5✔
153
      errors.add(:base, "Must provide a description") if resource.description.blank?
5✔
154
      errors.add(:base, "Must indicate the Publisher") if resource.publisher.blank?
5✔
155
      errors.add(:base, "Must indicate the Publication Year") if resource.publication_year.blank?
5✔
156
      errors.add(:base, "Must indicate at least one Rights statement") if resource.rights_many.count == 0
5✔
157
      errors.add(:base, "Must provide a Version number") if resource.version_number.blank?
5✔
158
      validate_related_objects
5✔
159
    end
160

161
    def validate_files
1✔
162
      return if @work.resource.migrated
1✔
UNCOV
163
      readme = Readme.new(work, nil)
×
UNCOV
164
      errors.add(:base, "Must provide a README") if readme.blank?
×
UNCOV
165
      errors.add(:base, "Must provide only one README file upload") if work.readme_uploads.length > 1
×
NEW
166
      errors.add(:base, "Must provide at least one file in addition to the README file upload") if work.artifact_uploads.empty?
×
167
    end
168
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