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

pulibrary / tigerdata-app / d7ce1bf9-25b8-4b3e-b9dd-43f9a26f2d96

17 Oct 2025 05:51PM UTC coverage: 91.054%. Remained the same
d7ce1bf9-25b8-4b3e-b9dd-43f9a26f2d96

Pull #2055

circleci

jrgriffiniii
- 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
Pull Request #2055: Ensuring that `parallelism` is set to 4 for CircleCI and separates `system` and inconsistently-failing tests into separate CI jobs

2738 of 3007 relevant lines covered (91.05%)

380.37 hits per line

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

95.28
/app/models/project_metadata.rb
1
# frozen_string_literal: true
2

3
# rubocop:disable Metrics/ClassLength
4
class ProjectMetadata
5✔
5
  DOI_NOT_MINTED = "DOI-NOT-MINTED"
5✔
6

7
  # @return [String] The default directory protocol
8
  def self.default_directory_protocol
5✔
9
    "NFS"
46✔
10
  end
11

12
  # @return [String] The default project resource type
13
  def self.default_resource_type
5✔
14
    "TigerData Project"
460✔
15
  end
16

17
  # @return [String] The default HPC value
18
  def self.default_hpc
5✔
19
    "No"
457✔
20
  end
21

22
  # @return [String] The default project visibility
23
  def self.default_project_visibility
5✔
24
    "Restricted"
460✔
25
  end
26

27
  # @return [String] The default data use agreement
28
  def self.default_data_use_agreement
5✔
29
    "No"
460✔
30
  end
31

32
  # @return [Hash] The default globus request Hash entries
33
  def self.default_globus_request
5✔
34
    "No"
649✔
35
  end
36

37
  # @return [Hash] The default Samba/SMB request Hash entries
38
  def self.default_smb_request
5✔
39
    "No"
649✔
40
  end
41

42
  # @return [Boolean] The default value for whether a project is provisional
43
  def self.default_provisionality
5✔
44
    false
701✔
45
  end
46

47
  # Ensure that the project directory is a valid path
48
  def self.safe_directory(directory)
5✔
49
    return "" if directory.nil?
703✔
50

51
    # only alphanumeric characters and /
52
    directory.strip.gsub(/[^A-Za-z\d\/]/, "-")
702✔
53
  end
54

55
  attr_accessor(
5✔
56
    :title, :description, :status, :data_sponsor, :data_manager, :departments, :data_user_read_only, :data_user_read_write,
57
    :created_on, :created_by, :project_id, :project_directory, :project_purpose, :storage_capacity, :storage_performance_expectations,
58
    :updated_by, :updated_on, :approval_note, :schema_version, :submission,
59
    # NOTE: The following attributes are required by the XML schema
60
    :hpc,
61
    :data_use_agreement,
62
    :project_visibility,
63
    :resource_type,
64
    :project_directory_protocol,
65
    :globus_request,
66
    :smb_request,
67
    :number_of_files,
68
    :provisional
69
  )
70

71
  def initialize
5✔
72
    @departments = []
700✔
73
    @data_user_read_only = []
700✔
74
    @data_user_read_write = []
700✔
75
  end
76

77
  def self.new_from_hash(metadata_hash)
5✔
78
    pm = ProjectMetadata.new
691✔
79
    pm.initialize_from_hash(metadata_hash)
691✔
80
    pm
691✔
81
  end
82

83
  def self.new_from_params(metadata_params)
5✔
84
    pm = ProjectMetadata.new
×
85
    pm.initialize_from_params(metadata_params)
×
86
    pm
×
87
  end
88

89
  # rubocop:disable Metrics/AbcSize
90
  # rubocop:disable Metrics/CyclomaticComplexity
91
  # rubocop:disable Metrics/MethodLength
92
  # rubocop:disable Metrics/PerceivedComplexity
93
  def initialize_from_hash(metadata_hash)
5✔
94
    @title = metadata_hash[:title]
701✔
95
    @description = metadata_hash[:description]
701✔
96
    @status = metadata_hash[:status] if metadata_hash[:status]
701✔
97
    @data_sponsor = metadata_hash[:data_sponsor]
701✔
98
    @data_manager = metadata_hash[:data_manager]
701✔
99
    @departments = metadata_hash[:departments]
701✔
100
    @data_user_read_only = metadata_hash[:data_user_read_only] if metadata_hash[:data_user_read_only]
701✔
101
    @data_user_read_write = metadata_hash[:data_user_read_write] if metadata_hash[:data_user_read_write]
701✔
102

103
    @project_id = metadata_hash[:project_id] || ProjectMetadata::DOI_NOT_MINTED
701✔
104
    @project_purpose = metadata_hash[:project_purpose]
701✔
105
    @project_directory = ProjectMetadata.safe_directory(metadata_hash[:project_directory])
701✔
106

107
    @storage_capacity = metadata_hash[:storage_capacity]
701✔
108
    @storage_performance_expectations = metadata_hash[:storage_performance_expectations]
701✔
109

110
    @created_by = metadata_hash[:created_by] if metadata_hash[:created_by]
701✔
111
    @created_on = metadata_hash[:created_on] if metadata_hash[:created_on]
701✔
112
    @updated_by = metadata_hash[:updated_by] if metadata_hash[:updated_by]
701✔
113
    @updated_on = metadata_hash[:updated_on] if metadata_hash[:updated_on]
701✔
114

115
    # NOTE: The following attributes are required by the 0.8 XML schema
116
    @number_of_files = metadata_hash[:number_of_files] || "Less than 10,000"
701✔
117
    @hpc = metadata_hash[:hpc] || self.class.default_hpc
701✔
118
    @globus_request = metadata_hash[:globus] || self.class.default_globus_request
701✔
119
    @smb_request = metadata_hash[:smb] || self.class.default_smb_request
701✔
120

121
    @data_use_agreement = metadata_hash[:data_use_agreement] || self.class.default_data_use_agreement
701✔
122

123
    @project_visibility = metadata_hash[:project_visibility] || self.class.default_project_visibility
701✔
124
    @resource_type = metadata_hash[:resource_type] || self.class.default_resource_type
701✔
125

126
    @provisional = metadata_hash[:provisional] || self.class.default_provisionality
701✔
127

128
    set_defaults
701✔
129
  end
130
  # rubocop:enable Metrics/PerceivedComplexity
131
  # rubocop:enable Metrics/MethodLength
132
  # rubocop:enable Metrics/CyclomaticComplexity
133
  # rubocop:enable Metrics/AbcSize
134

135
  # Initializes the object with the values in the params (which is an ActionController::Parameters)
136
  def initialize_from_params(params)
5✔
137
    @data_user_read_only = ro_users_from_params(params)
7✔
138
    @data_user_read_write = rw_users_from_params(params)
7✔
139
    initialize_from_hash(params)
7✔
140
  end
141

142
  # Updates the object with the values in the params (which is an ActionController::Parameters)
143
  # Notice how we only update values that come in the params and don't change the values that
144
  # don't come as part of the params
145
  # rubocop:disable Metrics/MethodLength
146
  def update_with_params(params, current_user)
5✔
147
    set_value(params, "title")
7✔
148
    set_value(params, "description")
7✔
149
    set_value(params, "status")
7✔
150
    set_value(params, "data_sponsor")
7✔
151
    set_value(params, "data_manager")
7✔
152
    set_value(params, "departments")
7✔
153
    set_value(params, "project_id")
7✔
154
    set_value(params, "project_purpose")
7✔
155
    calculate_project_directory(params)
7✔
156

157
    if params["data_user_counter"].present?
7✔
158
      @data_user_read_only = ro_users_from_params(params)
×
159
      @data_user_read_write = rw_users_from_params(params)
×
160
    end
161

162
    update_storage_capacity(params)
7✔
163
    update_storage_performance_expectations
7✔
164
    update_approval_note(params, current_user)
7✔
165
    @submission = params[:submission] if params[:submission]
7✔
166

167
    # Fields that come from the edit form
168
    @updated_by = current_user.uid
7✔
169
    @updated_on = Time.current.in_time_zone("America/New_York").iso8601
7✔
170
  end
171
  # rubocop:enable Metrics/MethodLength
172

173
  # Alias for `data_user_read_only`
174
  def ro_users
5✔
175
    @data_user_read_only
142✔
176
  end
177

178
  # Alias for `data_user_read_write`
179
  def rw_users
5✔
180
    @data_user_read_write
142✔
181
  end
182

183
    private
5✔
184

185
      def data_users_from_params(params, access)
5✔
186
        return [] if params.nil?
14✔
187
        users = []
14✔
188
        counter = params[:data_user_counter].to_i
14✔
189
        (1..counter).each do |i|
14✔
190
          key = "data_user_#{i}"
4✔
191
          access_key = key + "_read_access"
4✔
192
          if params[access_key] == access
4✔
193
            users << params[key]
2✔
194
          end
195
        end
196
        users.compact.uniq
14✔
197
      end
198

199
      def ro_users_from_params(params)
5✔
200
        data_users_from_params(params, "read-only")
7✔
201
      end
202

203
      def rw_users_from_params(params)
5✔
204
        data_users_from_params(params, "read-write")
7✔
205
      end
206

207
      # Initializes values that we have defaults for.
208
      def set_defaults
5✔
209
        if @storage_capacity.nil?
701✔
210
          @storage_capacity = Rails.configuration.project_defaults[:storage_capacity]
60✔
211
        end
212

213
        if @storage_performance_expectations.nil?
701✔
214
          @storage_performance_expectations = Rails.configuration.project_defaults[:storage_performance_expectations]
60✔
215
        end
216

217
        if @project_purpose.nil?
701✔
218
          @project_purpose = Rails.configuration.project_defaults[:project_purpose]
189✔
219
        end
220

221
        @submission = { "requested_by" => @created_by, "request_date_time" => @created_on } if @submission.nil?
701✔
222
        @schema_version = TigerdataSchema::SCHEMA_VERSION
701✔
223
      end
224

225
      # Sets a value in the object if the value exists in the params
226
      def set_value(params, key)
5✔
227
        if params.include?(key)
56✔
228
          send("#{key}=", params[key])
15✔
229
        end
230
      end
231

232
      def update_storage_capacity(params)
5✔
233
        if params["storage_capacity"].present?
7✔
234
          @storage_capacity = {
235
            "size" => {
×
236
              "approved" => params["storage_capacity"].to_i,
237
              "requested" => storage_capacity[:size][:requested]
238
            },
239
            "unit" => {
240
              "approved" => params["storage_unit"],
241
              "requested" => storage_capacity[:unit][:requested]
242
            }
243
          }
244
        end
245
      end
246

247
      def update_storage_performance_expectations
5✔
248
        # we don't allow the user to specify an approve value so we use the requested
249
        @storage_performance_expectations = {
250
          "requested" => storage_performance_expectations[:requested],
7✔
251
          "approved" => storage_performance_expectations[:requested]
252
        }
253
      end
254

255
      def update_approval_note(params, current_user)
5✔
256
        if params[:event_note_message].present?
7✔
257
          @approval_note = {
258
            note_by: current_user.uid,
2✔
259
            note_date_time: Time.current.in_time_zone("America/New_York").iso8601,
260
            event_type: params[:event_note],
261
            message: params[:event_note_message]
262
          }
263
        end
264
      end
265

266
      def calculate_project_directory(params)
5✔
267
        if params.key?("project_directory_prefix") || params.key?("project_directory")
7✔
268
          full_path = [params["project_directory_prefix"], params["project_directory"]].compact.join("/")
2✔
269
          @project_directory = ProjectMetadata.safe_directory(full_path)
2✔
270
        end
271
      end
272
end
273
# 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