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

pulibrary / tigerdata-app / 88c82417-71e1-4f84-8337-7bf4bd1a5618

29 Jul 2025 08:15PM UTC coverage: 75.423% (-5.2%) from 80.666%
88c82417-71e1-4f84-8337-7bf4bd1a5618

Pull #1656

circleci

hectorcorrea
Marked a bunch of tests as integration since they create projects in Mediaflux
Pull Request #1656: Added error handling to the request to project workflow

12 of 17 new or added lines in 4 files covered. (70.59%)

157 existing lines in 19 files now uncovered.

2274 of 3015 relevant lines covered (75.42%)

344.11 hits per line

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

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

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

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

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

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

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

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

32
  # @return [Hash] The default globus request Hash entries
33
  def self.default_globus_request
1✔
34
    {
319✔
35
      requested: false,
36
      approved: false
37
    }
38
  end
39

40
  # @return [Hash] The default Samba/SMB request Hash entries
41
  def self.default_smb_request
1✔
42
    {
319✔
43
      requested: false,
44
      approved: false
45
    }
46
  end
47

48
  # @return [Boolean] The default value for whether a project is provisional
49
  def self.default_provisionality
1✔
50
    false
683✔
51
  end
52

53
  # Ensure that the project directory is a valid path
54
  def self.safe_directory(directory)
1✔
55
    return "" if directory.nil?
689✔
56

57
    # only alphanumeric characters and /
58
    directory.strip.gsub(/[^A-Za-z\d\/]/, "-")
665✔
59
  end
60

61
  attr_accessor(
1✔
62
    :title, :description, :status, :data_sponsor, :data_manager, :departments, :data_user_read_only, :data_user_read_write,
63
    :created_on, :created_by, :project_id, :project_directory, :project_purpose, :storage_capacity, :storage_performance_expectations,
64
    :updated_by, :updated_on, :approval_note, :schema_version, :submission,
65
    # NOTE: The following attributes are required by the XML schema
66
    :hpc,
67
    :data_use_agreement,
68
    :project_visibility,
69
    :resource_type,
70
    :project_directory_protocol,
71
    :globus_request,
72
    :smb_request,
73
    :provisional
74
  )
75

76
  def initialize
1✔
77
    @departments = []
682✔
78
    @data_user_read_only = []
682✔
79
    @data_user_read_write = []
682✔
80
  end
81

82
  def self.new_from_hash(metadata_hash)
1✔
83
    pm = ProjectMetadata.new
661✔
84
    pm.initialize_from_hash(metadata_hash)
661✔
85
    pm
661✔
86
  end
87

88
  def self.new_from_params(metadata_params)
1✔
89
    pm = ProjectMetadata.new
12✔
90
    pm.initialize_from_params(metadata_params)
12✔
91
    pm
12✔
92
  end
93

94
  # rubocop:disable Metrics/AbcSize
95
  # rubocop:disable Metrics/CyclomaticComplexity
96
  # rubocop:disable Metrics/MethodLength
97
  # rubocop:disable Metrics/PerceivedComplexity
98
  def initialize_from_hash(metadata_hash)
1✔
99
    @title = metadata_hash[:title]
683✔
100
    @description = metadata_hash[:description]
683✔
101
    @status = metadata_hash[:status] if metadata_hash[:status]
683✔
102
    @data_sponsor = metadata_hash[:data_sponsor]
683✔
103
    @data_manager = metadata_hash[:data_manager]
683✔
104
    @departments = metadata_hash[:departments]
683✔
105
    @data_user_read_only = metadata_hash[:data_user_read_only] if metadata_hash[:data_user_read_only]
683✔
106
    @data_user_read_write = metadata_hash[:data_user_read_write] if metadata_hash[:data_user_read_write]
683✔
107

108
    @project_id = metadata_hash[:project_id] || ProjectMetadata::DOI_NOT_MINTED
683✔
109
    @project_purpose = metadata_hash[:project_purpose]
683✔
110
    @project_directory = ProjectMetadata.safe_directory(metadata_hash[:project_directory])
683✔
111

112
    @storage_capacity = metadata_hash[:storage_capacity]
683✔
113
    @storage_performance_expectations = metadata_hash[:storage_performance_expectations]
683✔
114

115
    @created_by = metadata_hash[:created_by] if metadata_hash[:created_by]
683✔
116
    @created_on = metadata_hash[:created_on] if metadata_hash[:created_on]
683✔
117
    @updated_by = metadata_hash[:updated_by] if metadata_hash[:updated_by]
683✔
118
    @updated_on = metadata_hash[:updated_on] if metadata_hash[:updated_on]
683✔
119

120
    # NOTE: The following attributes are required by the 0.8 XML schema
121
    @hpc = metadata_hash[:hpc] || self.class.default_hpc
683✔
122

123
    @data_use_agreement = metadata_hash[:data_use_agreement] || self.class.default_data_use_agreement
683✔
124

125
    @project_visibility = metadata_hash[:project_visibility] || self.class.default_project_visibility
683✔
126
    @resource_type = metadata_hash[:resource_type] || self.class.default_resource_type
683✔
127

128
    @globus_request = metadata_hash[:globus_request] || self.class.default_globus_request
683✔
129
    @smb_request = metadata_hash[:smb_request] || self.class.default_smb_request
683✔
130

131
    @provisional = metadata_hash[:provisional] || self.class.default_provisionality
683✔
132

133
    set_defaults
683✔
134
  end
135
  # rubocop:enable Metrics/PerceivedComplexity
136
  # rubocop:enable Metrics/MethodLength
137
  # rubocop:enable Metrics/CyclomaticComplexity
138
  # rubocop:enable Metrics/AbcSize
139

140
  # Initializes the object with the values in the params (which is an ActionController::Parameters)
141
  def initialize_from_params(params)
1✔
142
    @data_user_read_only = ro_users_from_params(params)
19✔
143
    @data_user_read_write = rw_users_from_params(params)
19✔
144
    initialize_from_hash(params)
19✔
145
  end
146

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

162
    if params["data_user_counter"].present?
11✔
163
      @data_user_read_only = ro_users_from_params(params)
4✔
164
      @data_user_read_write = rw_users_from_params(params)
4✔
165
    end
166

167
    update_storage_capacity(params)
11✔
168
    update_storage_performance_expectations
11✔
169
    update_approval_note(params, current_user)
11✔
170
    @submission = params[:submission] if params[:submission]
11✔
171

172
    # Fields that come from the edit form
173
    @updated_by = current_user.uid
11✔
174
    @updated_on = Time.current.in_time_zone("America/New_York").iso8601
11✔
175
  end
176
  # rubocop:enable Metrics/MethodLength
177

178
  # Alias for `data_user_read_only`
179
  def ro_users
1✔
180
    @data_user_read_only
57✔
181
  end
182

183
  # Alias for `data_user_read_write`
184
  def rw_users
1✔
185
    @data_user_read_write
57✔
186
  end
187

188
    private
1✔
189

190
      def data_users_from_params(params, access)
1✔
191
        return [] if params.nil?
46✔
192
        users = []
46✔
193
        counter = params[:data_user_counter].to_i
46✔
194
        (1..counter).each do |i|
46✔
195
          key = "data_user_#{i}"
22✔
196
          access_key = key + "_read_access"
22✔
197
          if params[access_key] == access
22✔
198
            users << params[key]
11✔
199
          end
200
        end
201
        users.compact.uniq
46✔
202
      end
203

204
      def ro_users_from_params(params)
1✔
205
        data_users_from_params(params, "read-only")
23✔
206
      end
207

208
      def rw_users_from_params(params)
1✔
209
        data_users_from_params(params, "read-write")
23✔
210
      end
211

212
      # Initializes values that we have defaults for.
213
      def set_defaults
1✔
214
        if @storage_capacity.nil?
683✔
215
          @storage_capacity = Rails.configuration.project_defaults[:storage_capacity]
95✔
216
        end
217

218
        if @storage_performance_expectations.nil?
683✔
219
          @storage_performance_expectations = Rails.configuration.project_defaults[:storage_performance_expectations]
95✔
220
        end
221

222
        if @project_purpose.nil?
683✔
223
          @project_purpose = Rails.configuration.project_defaults[:project_purpose]
115✔
224
        end
225

226
        @submission = { "requested_by" => @created_by, "request_date_time" => @created_on } if @submission.nil?
683✔
227
        @schema_version = TigerdataSchema::SCHEMA_VERSION
683✔
228
      end
229

230
      # Sets a value in the object if the value exists in the params
231
      def set_value(params, key)
1✔
232
        if params.include?(key)
88✔
233
          send("#{key}=", params[key])
36✔
234
        end
235
      end
236

237
      def update_storage_capacity(params)
1✔
238
        if params["storage_capacity"].present?
11✔
239
          @storage_capacity = {
UNCOV
240
            "size" => {
×
241
              "approved" => params["storage_capacity"].to_i,
242
              "requested" => storage_capacity[:size][:requested]
243
            },
244
            "unit" => {
245
              "approved" => params["storage_unit"],
246
              "requested" => storage_capacity[:unit][:requested]
247
            }
248
          }
249
        end
250
      end
251

252
      def update_storage_performance_expectations
1✔
253
        # we don't allow the user to specify an approve value so we use the requested
254
        @storage_performance_expectations = {
255
          "requested" => storage_performance_expectations[:requested],
11✔
256
          "approved" => storage_performance_expectations[:requested]
257
        }
258
      end
259

260
      def update_approval_note(params, current_user)
1✔
261
        if params[:event_note_message].present?
11✔
262
          @approval_note = {
263
            note_by: current_user.uid,
2✔
264
            note_date_time: Time.current.in_time_zone("America/New_York").iso8601,
265
            event_type: params[:event_note],
266
            message: params[:event_note_message]
267
          }
268
        end
269
      end
270

271
      def calculate_project_directory(params)
1✔
272
        if params.key?("project_directory_prefix") || params.key?("project_directory")
11✔
273
          full_path = [params["project_directory_prefix"], params["project_directory"]].compact.join("/")
6✔
274
          @project_directory = ProjectMetadata.safe_directory(full_path)
6✔
275
        end
276
      end
277
end
278
# 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