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

pulibrary / tigerdata-app / 6a5be3a8-ecd4-400d-9134-33099047b33b

21 Oct 2025 03:31PM UTC coverage: 91.184% (+0.1%) from 91.054%
6a5be3a8-ecd4-400d-9134-33099047b33b

push

circleci

web-flow
Ensuring that `parallelism` is set to 4 for CircleCI and separates `system` tests into separate CI jobs (#2055)

* - Ensuring that `parallelism` is set to 4
- Separating `system` RSpec spec suites in the CI build
- Using an `inconsistent` RSpec tag to mark inconsistently failing tests
- Ensuring that CI does not run for `inconsistent` tests

* Removing `inconsistent` tag for RSpec test suites

2741 of 3006 relevant lines covered (91.18%)

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

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

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

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

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

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

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

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

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

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

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

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

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

102
  def approved_quota_size
5✔
103
    if approved_quota.present?
254✔
104
      if approved_quota == "custom"
212✔
105
        approved_storage_size.to_f
210✔
106
      else
107
        approved_quota.split.first.to_f
2✔
108
      end
109
    else
110
      requested_quota_size
42✔
111
    end
112
  end
113

114
  def requested_quota_size
5✔
115
    if custom_quota?
320✔
116
      storage_size.to_f
220✔
117
    else
118
      quota.split.first.to_f
100✔
119
    end
120
  end
121

122
  def approved_quota_unit
5✔
123
    if approved_quota.present?
260✔
124
      if approved_quota == "custom"
216✔
125
        approved_storage_unit
214✔
126
      else
127
        approved_quota.split.last
2✔
128
      end
129
    else
130
      requested_quota_unit
44✔
131
    end
132
  end
133

134
  def requested_quota_unit
5✔
135
    if custom_quota?
320✔
136
      storage_unit
220✔
137
    else
138
      quota.split.last
100✔
139
    end
140
  end
141

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

146
  private
5✔
147

148
    def check_errors?
5✔
149
      original_error_count = errors.count
968✔
150
      yield
968✔
151
      original_error_count == errors.count
968✔
152
    end
153

154
    def field_present?(value, name)
5✔
155
      if value.blank?
566✔
156
        errors.add(name, :invalid, message: "cannot be empty")
172✔
157
      end
158
    end
159

160
    def validate_uid(uid, field)
5✔
161
      if uid.blank?
272✔
162
        errors.add(field, :blank, message: "cannot be empty")
74✔
163
      elsif User.where(uid: uid).count == 0
198✔
164
        errors.add(field, :invalid, message: "must be a valid user")
4✔
165
      end
166
    end
167

168
    def project_purpose_present?(project_purpose, field)
5✔
169
      if project_purpose.blank?
130✔
170
        errors.add(field, :blank, message: "select a project purpose")
50✔
171
      end
172
    end
173

174
    def valid_length(value, length, field)
5✔
175
      return if value.blank?
288✔
176
      if value.length > length
208✔
177
        errors.add(field, :invalid, message: "cannot exceed #{length} characters")
16✔
178
      end
179
    end
180

181
    def no_quotes(value, field)
5✔
182
      return if value.blank?
428✔
183
      if value.include?('"')
298✔
184
        errors.add(field, :invalid, message: "cannot include quotes")
10✔
185
      end
186
    end
187

188
    # If a request fails to be a approved we make sure there were not orphan
189
    # project records left in our Rails database that do not have a matching
190
    # project in Mediaflux (i.e. collection asset).
191
    def cleanup_incomplete_project
5✔
192
      project = Project.find_by_id(project_id)
6✔
193
      if project && project.mediaflux_id.nil?
6✔
194
        Rails.logger.warn("Deleting project #{project.id} because the approval for request #{id} failed and it was not created in Mediaflux.")
4✔
195
        project.destroy!
4✔
196
      end
197
    end
198
end
199
# 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