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

pulibrary / tigerdata-app / 751a8b7a-3dcf-4fbf-b16e-522d27f88642

03 Nov 2025 02:30PM UTC coverage: 91.4% (+0.006%) from 91.394%
751a8b7a-3dcf-4fbf-b16e-522d27f88642

push

circleci

web-flow
Make sure all projects are fetched (not only the first 100) (#2131)

This fixes an issue we noted while testing in Staging since
Administrators should be able to fetch all projects that they have
access to, not only the first 100 (which is the default when not
indicating a `size` parameter to Mediaflux.)

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

191 existing lines in 11 files now uncovered.

2827 of 3093 relevant lines covered (91.4%)

486.73 hits per line

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

100.0
/app/models/request.rb
1
# frozen_string_literal: true
2
# rubocop:disable Metrics/ClassLength
3
class Request < ApplicationRecord
5✔
4
  DRAFT = "draft" # default state set by database
5✔
5
  SUBMITTED = "submitted" # Ready to be approved
5✔
6

7
  def valid_to_submit?
5✔
8
    errors.clear
61✔
9
    # run all validations and then check for errors otherwise ruby stops at the first error
10
    valid_title?
61✔
11
    valid_data_sponsor?
61✔
12
    valid_data_manager?
61✔
13
    valid_departments?
61✔
14
    valid_quota?
61✔
15
    valid_project_purpose?
61✔
16
    valid_description?
61✔
17
    # Is parent folder really required?  For Skeletor let's skip it.
18
    # valid_parent_folder?
19
    valid_project_folder?
61✔
20
    # For Skeletor we are setting the requestor to the data sponsor
21
    # valid_requested_by?
22
    errors.count == 0
61✔
23
  end
24

25
  def valid_title?
5✔
26
    check_errors? do
70✔
27
      field_present?(project_title, :project_title)
70✔
28
      valid_length(project_title, 200, :project_title)
70✔
29
      no_quotes(project_title, :project_title)
70✔
30
    end
31
  end
32

33
  def valid_data_sponsor?
5✔
34
    check_errors? { validate_uid(data_sponsor, :data_sponsor) }
128✔
35
  end
36

37
  def valid_data_manager?
5✔
38
    check_errors? { validate_uid(data_manager, :data_manager) }
128✔
39
  end
40

41
  def valid_departments?
5✔
42
    check_errors? { field_present?(departments, :departments) }
126✔
43
  end
44

45
  def valid_project_purpose?
5✔
46
    check_errors? { project_purpose_present?(project_purpose, :project_purpose) }
122✔
47
  end
48

49
  def valid_description?
5✔
50
    check_errors? do
66✔
51
      field_present?(description, :description)
66✔
52
      valid_length(description, 1000, :description)
66✔
53
      no_quotes(description, :description)
66✔
54
    end
55
  end
56

57
  def valid_parent_folder?
5✔
UNCOV
58
    check_errors? do
2✔
UNCOV
59
      field_present?(parent_folder, :parent_folder)
2✔
UNCOV
60
      no_quotes(project_title, :parent_folder)
2✔
61
    end
62
  end
63

64
  def valid_project_folder?
5✔
65
    check_errors? do
64✔
66
      field_present?(project_folder, :project_folder)
64✔
67
      no_quotes(project_folder, :project_folder)
64✔
68
    end
69
  end
70

71
  def valid_quota?
5✔
72
    if ((quota == "500 GB") || (quota == "2 TB") || (quota == "10 TB") || (quota == "25 TB")) ||
69✔
UNCOV
73
       (custom_quota? && (storage_size.present? && (storage_size > 0)) && ((storage_unit == "GB") || (storage_unit == "TB")))
6✔
74
      true
65✔
75
    else
UNCOV
76
      errors.add(:quota, :invalid, message: "must be one of '500 GB', '2 TB', '10 TB', '25 TB', or 'custom'")
4✔
UNCOV
77
      false
4✔
78
    end
79
  end
80

81
  def custom_quota?
5✔
82
    quota == "custom"
554✔
83
  end
84

85
  def valid_requested_by?
5✔
UNCOV
86
    check_errors? { field_present?(requested_by, :requested_by) }
4✔
87
  end
88

89
  def approve(approver)
5✔
90
    create_project_operation = ProjectCreate.new
230✔
91
    result = create_project_operation.call(request: self, approver: approver)
230✔
92
    if result.success?
230✔
93
      result.value!
227✔
94
    else
95
      self.error_message = { message: result.failure }
3✔
96
      save!
3✔
97
      cleanup_incomplete_project
3✔
98
      raise ProjectCreate::ProjectCreateError, result.failure
3✔
99
    end
100
  end
101

102
  def approved_quota_size
5✔
103
    if approved_quota.present?
253✔
104
      if approved_quota == "custom"
221✔
105
        approved_storage_size.to_f
219✔
106
      else
UNCOV
107
        approved_quota.split.first.to_f
2✔
108
      end
109
    else
110
      requested_quota_size
32✔
111
    end
112
  end
113

114
  def requested_quota_size
5✔
115
    if custom_quota?
274✔
116
      storage_size.to_f
224✔
117
    else
118
      quota.split.first.to_f
50✔
119
    end
120
  end
121

122
  def approved_quota_unit
5✔
123
    if approved_quota.present?
256✔
124
      if approved_quota == "custom"
223✔
125
        approved_storage_unit
221✔
126
      else
UNCOV
127
        approved_quota.split.last
2✔
128
      end
129
    else
130
      requested_quota_unit
33✔
131
    end
132
  end
133

134
  def requested_quota_unit
5✔
135
    if custom_quota?
274✔
136
      storage_unit
224✔
137
    else
138
      quota.split.last
50✔
139
    end
140
  end
141

142
  def submitted?
5✔
143
    state == Request::SUBMITTED
84✔
144
  end
145

146
  def project_path
5✔
UNCOV
147
    return project_folder if parent_folder.blank?
3✔
148

UNCOV
149
    [parent_folder, project_folder].join("/")
1✔
150
  end
151

152
  def requestor
5✔
UNCOV
153
    return "missing" if requested_by.blank?
2✔
UNCOV
154
    User.find_by(uid: requested_by).display_name_safe
1✔
155
  end
156

157
  private
5✔
158

159
    def check_errors?
5✔
160
      original_error_count = errors.count
456✔
161
      yield
456✔
162
      original_error_count == errors.count
456✔
163
    end
164

165
    def field_present?(value, name)
5✔
166
      if value.blank?
267✔
167
        errors.add(name, :invalid, message: "cannot be empty")
86✔
168
      end
169
    end
170

171
    def validate_uid(uid, field)
5✔
172
      if uid.blank?
128✔
173
        errors.add(field, :blank, message: "cannot be empty")
37✔
174
      elsif User.where(uid: uid).count == 0
91✔
UNCOV
175
        errors.add(field, :invalid, message: "must be a valid user")
2✔
176
      end
177
    end
178

179
    def project_purpose_present?(project_purpose, field)
5✔
180
      if project_purpose.blank?
61✔
181
        errors.add(field, :blank, message: "select a project purpose")
25✔
182
      end
183
    end
184

185
    def valid_length(value, length, field)
5✔
186
      return if value.blank?
136✔
187
      if value.length > length
96✔
UNCOV
188
        errors.add(field, :invalid, message: "cannot exceed #{length} characters")
8✔
189
      end
190
    end
191

192
    def no_quotes(value, field)
5✔
193
      return if value.blank?
202✔
194
      if value.include?('"')
137✔
UNCOV
195
        errors.add(field, :invalid, message: "cannot include quotes")
5✔
196
      end
197
    end
198

199
    # If a request fails to be a approved we make sure there were not orphan
200
    # project records left in our Rails database that do not have a matching
201
    # project in Mediaflux (i.e. collection asset).
202
    def cleanup_incomplete_project
5✔
203
      project = Project.find_by_id(project_id)
3✔
204
      if project && project.mediaflux_id.nil?
3✔
UNCOV
205
        Rails.logger.warn("Deleting project #{project.id} because the approval for request #{id} failed and it was not created in Mediaflux.")
2✔
UNCOV
206
        project.destroy!
2✔
207
      end
208
    end
209
end
210
# rubocop:enable Metrics/ClassLength
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