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

pulibrary / pdc_discovery / 5af13607-7741-41ac-b110-c94c8a3ee0f0

pending completion
5af13607-7741-41ac-b110-c94c8a3ee0f0

Pull #441

circleci

hectorcorrea
Better error handling
Pull Request #441: Indexing to a new collection

99 of 99 new or added lines in 3 files covered. (100.0%)

1816 of 2220 relevant lines covered (81.8%)

95.45 hits per line

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

60.16
/app/models/solr_document.rb
1
# frozen_string_literal: true
2

3
# rubocop:disable Metrics/ClassLength
4
class SolrDocument
1✔
5
  include Blacklight::Solr::Document
1✔
6
  # The following shows how to setup this blacklight document to display marc documents
7
  extension_parameters[:marc_source_field] = :marc_ss
1✔
8
  extension_parameters[:marc_format_type] = :marcxml
1✔
9
  use_extension(Blacklight::Solr::Document::Marc) do |document|
1✔
10
    document.key?(SolrDocument.extension_parameters[:marc_source_field])
24✔
11
  end
12

13
  field_semantics.merge!(
1✔
14
    title: 'title_tesim',
15
    contributor: 'author_tesim',
16
    format: 'genre_ssim',
17
    date: 'issue_date_ssim'
18
  )
19

20
  # self.unique_key = 'id'
21

22
  # Email uses the semantic field mappings below to generate the body of an email.
23
  SolrDocument.use_extension(Blacklight::Document::Email)
1✔
24

25
  # SMS uses the semantic field mappings below to generate the body of an SMS email.
26
  SolrDocument.use_extension(Blacklight::Document::Sms)
1✔
27

28
  # DublinCore uses the semantic field mappings below to assemble an OAI-compliant Dublin Core document
29
  # Semantic mappings of solr stored fields. Fields may be multi or
30
  # single valued. See Blacklight::Document::SemanticFields#field_semantics
31
  # and Blacklight::Document::SemanticFields#to_semantic_values
32
  # Recommendation: Use field names from Dublin Core
33
  use_extension(Blacklight::Document::DublinCore)
1✔
34

35
  ABSTRACT_FIELD = 'abstract_tsim'
1✔
36
  DESCRIPTION_FIELD = 'description_tsim'
1✔
37
  ISSUED_DATE_FIELD = 'issue_date_ssim'
1✔
38
  METHODS_FIELD = 'methods_tsim'
1✔
39
  TITLE_FIELD = 'title_tesim'
1✔
40

41
  # These icons map to CSS classes in Bootstrap
42
  ICONS = {
1✔
43
    "dataset" => "bi-stack",
44
    "moving image" => "bi-film",
45
    "software" => "bi-code-slash",
46
    "image" => "bi-image",
47
    "text" => "bi-card-text",
48
    "collection" => "bi-collection-fill",
49
    "article" => "bi-journal-text",
50
    "interactive resource" => "bi-pc-display-horizontal"
51
  }.freeze
52

53
  def id
1✔
54
    fetch('id')
9✔
55
  end
56

57
  def titles
1✔
58
    fetch(TITLE_FIELD, [])
4✔
59
  end
60

61
  def title
1✔
62
    titles.first
4✔
63
  end
64

65
  # Returns the list of author names (ordered if possible)
66
  def authors
1✔
67
    authors_ordered.map { |author| author["value"] }
40✔
68
  end
69

70
  # Returns the list of authors with all their information
71
  # including name and ORCID. (ordered if possible)
72
  def authors_ordered
1✔
73
    @authors_ordered ||= begin
17✔
74
      authors_json = fetch('authors_json_ss', nil)
10✔
75
      if authors_json
10✔
76
        # PDC Describe records contain this field;
77
        # det the author data and sort it.
78
        authors = JSON.parse(authors_json)
1✔
79
        authors.sort_by { |creator| creator["sequence"] }
6✔
80
      else
81
        # DataSpace record don't contain this field;
82
        # do the best we can with author_tesim value.
83
        names = fetch('author_tesim', [])
9✔
84
        names.map { |name| author_from_name(name) }
43✔
85
      end
86
    end
87
  end
88

89
  # Returns a string with the authors and shortens it if there are more than 2 authors.
90
  # https://owl.purdue.edu/owl/research_and_citation/apa_style/apa_formatting_and_style_guide/in_text_citations_author_authors.html
91
  def authors_et_al
1✔
92
    authors_all = authors
8✔
93
    if authors_all.count <= 2
8✔
94
      authors_all.join(" & ")
6✔
95
    else
96
      authors_all.first + " et al."
2✔
97
    end
98
  end
99

100
  # Create an author hash when we only have an author name (e.g. for records coming from DataSpace)
101
  # In this case order/sequence cannot be determined.
102
  def author_from_name(name)
1✔
103
    {
104
      "value" => name,
34✔
105
      "name_type" => "Personal",
106
      "given_name" => nil,
107
      "family_name" => nil,
108
      "identifier" => nil,
109
      "affiliations" => [],
110
      "sequence" => 0
111
    }
112
  end
113

114
  def creators
1✔
115
    fetch('creator_tesim', [])
×
116
  end
117

118
  def community_path
1✔
119
    fetch("community_path_name_ssi", "")
×
120
  end
121

122
  def collection_name
1✔
123
    fetch("collection_name_ssi", "")
×
124
  end
125

126
  def collection_tags
1✔
127
    fetch("collection_tag_ssim", [])
×
128
  end
129

130
  def contributors
1✔
131
    fetch("contributor_tsim", [])
×
132
  end
133

134
  def accessioned_dates
1✔
135
    fetch("date_accessioned_ssim", [])
×
136
  end
137

138
  def accessioned_date
1✔
139
    accessioned_dates.first
×
140
  end
141

142
  def issued_dates
1✔
143
    fetch(ISSUED_DATE_FIELD, [])
4✔
144
  end
145

146
  def issued_date
1✔
147
    issued_dates.first
4✔
148
  end
149

150
  def abstracts
1✔
151
    fetch(ABSTRACT_FIELD, [])
×
152
  end
153

154
  def abstract
1✔
155
    abstracts.first
×
156
  end
157

158
  def descriptions
1✔
159
    fetch(DESCRIPTION_FIELD, [])
×
160
  end
161

162
  def description
1✔
163
    descriptions.first
×
164
  end
165

166
  def methods
1✔
167
    fetch(METHODS_FIELD, [])
×
168
  end
169

170
  def data_source
1✔
171
    fetch("data_source_ssi", "dataspace")
3✔
172
  end
173

174
  def files
1✔
175
    @files ||= begin
3✔
176
      data = JSON.parse(fetch("files_ss", "[]"))
2✔
177
      data.map { |x| DatasetFile.from_hash(x, data_source) }.sort_by(&:sequence)
5✔
178
    end
179
  end
180

181
  # Returns an array with the counts by file extension
182
  # e.g. [{extension: "txt", file_count: 3}, {extension: "csv", file_count: 1}]
183
  def file_counts
1✔
184
    groups = files.group_by(&:extension)
3✔
185
    groups.map { |key, value| { extension: key, file_count: value.count } }.sort_by { |group| -group[:file_count] }
11✔
186
  end
187

188
  def table_of_contents
1✔
189
    fetch("tableofcontents_tesim", [])
×
190
  end
191

192
  def referenced_by
1✔
193
    fetch("referenced_by_ssim", [])
×
194
  end
195

196
  def uri
1✔
197
    fetch("uri_ssim", [])
×
198
  end
199

200
  def doi_url
1✔
201
    uri.each do |link|
×
202
      return link if link.downcase.start_with?('https://doi.org/')
×
203
    end
204
    nil
205
  end
206

207
  def doi_value
1✔
208
    doi_url&.gsub('https://doi.org/', '')
×
209
  end
210

211
  def format
1✔
212
    fetch("format_ssim", [])
×
213
  end
214

215
  def globus_uri
1✔
216
    uri.each do |link|
×
217
      return link if link.downcase.start_with?('https://app.globus.org/')
×
218
    end
219
    nil
220
  end
221

222
  def extent
1✔
223
    fetch("extent_ssim", [])
×
224
  end
225

226
  def medium
1✔
227
    fetch("medium_ssim", [])
×
228
  end
229

230
  def mimetype
1✔
231
    fetch("mimetype_ssim", [])
×
232
  end
233

234
  def language
1✔
235
    fetch("language_ssim", [])
×
236
  end
237

238
  def publisher
1✔
239
    fetch("publisher_ssim", [])
×
240
  end
241

242
  def publisher_place
1✔
243
    fetch("publisher_place_ssim", [])
×
244
  end
245

246
  def publisher_corporate
1✔
247
    fetch("publisher_corporate_ssim", [])
×
248
  end
249

250
  def relation
1✔
251
    fetch("relation_ssim", [])
×
252
  end
253

254
  def relation_is_format_of
1✔
255
    fetch("relation_is_format_of_ssim", [])
×
256
  end
257

258
  def relation_has_format
1✔
259
    fetch("relation_has_format_ssim", [])
×
260
  end
261

262
  def relation_is_part_of
1✔
263
    fetch("relation_is_part_of_ssim", [])
×
264
  end
265

266
  def relation_is_part_of_series
1✔
267
    fetch("relation_is_part_of_series_ssim", [])
×
268
  end
269

270
  def relation_has_part
1✔
271
    fetch("relation_has_part_ssim", [])
×
272
  end
273

274
  def relation_is_version_of
1✔
275
    fetch("relation_is_version_of_ssim", [])
×
276
  end
277

278
  def relation_has_version
1✔
279
    fetch("relation_has_version_ssim", [])
×
280
  end
281

282
  def relation_is_based_on
1✔
283
    fetch("relation_is_based_on_ssim", [])
×
284
  end
285

286
  def relation_is_referenced_by
1✔
287
    fetch("relation_is_referenced_by_ssim", [])
×
288
  end
289

290
  def relation_is_required_by
1✔
291
    fetch("relation_is_required_by_ssim", [])
×
292
  end
293

294
  def relation_requires
1✔
295
    fetch("relation_requires_ssim", [])
×
296
  end
297

298
  def relation_replaces
1✔
299
    fetch("relation_replaces_ssim", [])
×
300
  end
301

302
  def relation_is_replaced_by
1✔
303
    fetch("relation_is_replaced_by_ssim", [])
×
304
  end
305

306
  def relation_uri
1✔
307
    fetch("relation_uri_ssim", [])
×
308
  end
309

310
  def rights
1✔
311
    fetch("rights_ssim", [])
×
312
  end
313

314
  def rights_uri
1✔
315
    fetch("rights_uri_ssim", [])
×
316
  end
317

318
  # For PDC Describe records we have a single value for the name and the uri
319
  # and we can safely assume they are related.
320
  def rights_name_and_uri
1✔
321
    name = fetch("rights_name_ssi", nil)
×
322
    uri = fetch("rights_uri_ssi", nil)
×
323
    return nil if name.nil? || uri.nil?
×
324
    { name: name, uri: uri }
×
325
  end
326

327
  def rights_holder
1✔
328
    fetch("rights_holder_ssim", [])
×
329
  end
330

331
  def subject
1✔
332
    fetch("subject_tesim", [])
×
333
  end
334

335
  def subject_classification
1✔
336
    fetch("subject_classification_tesim", [])
×
337
  end
338

339
  def subject_ddc
1✔
340
    fetch("subject_ddc_tesim", [])
×
341
  end
342

343
  def subject_lcc
1✔
344
    fetch("subject_lcc_tesim", [])
×
345
  end
346

347
  def subject_lcsh
1✔
348
    fetch("subject_lcsh_tesim", [])
×
349
  end
350

351
  def subject_mesh
1✔
352
    fetch("subject_mesh_tesim", [])
×
353
  end
354

355
  def subject_other
1✔
356
    fetch("subject_other_tesim", [])
×
357
  end
358

359
  def alternative_title
1✔
360
    fetch("alternative_title_tesim", [])
×
361
  end
362

363
  def genres
1✔
364
    fetch("genre_ssim", []).sort
10✔
365
  end
366

367
  # Sometimes we need a single genre for an item, even though an item may have more than one.
368
  # This method makes sure we always get the same value (the first one from a sorted list).
369
  def genre
1✔
370
    genres.first
10✔
371
  end
372

373
  def peer_review_status
1✔
374
    fetch("peer_review_status_ssim", [])
×
375
  end
376

377
  def translator
1✔
378
    fetch("translator_ssim", [])
×
379
  end
380

381
  def isan
1✔
382
    fetch("isan_ssim", [])
×
383
  end
384

385
  def access_rights
1✔
386
    fetch("access_rights_ssim", [])
×
387
  end
388

389
  def funding_agency
1✔
390
    fetch("funding_agency_ssim", [])
×
391
  end
392

393
  def provenance
1✔
394
    fetch("provenance_ssim", [])
×
395
  end
396

397
  def license
1✔
398
    fetch("license_ssim", [])
×
399
  end
400

401
  def accrual_method
1✔
402
    fetch("accrual_method_ssim", [])
×
403
  end
404

405
  def accrual_periodicity
1✔
406
    fetch("accrual_periodicity_ssim", [])
×
407
  end
408

409
  def accrual_policy
1✔
410
    fetch("accrual_policy_ssim", [])
×
411
  end
412

413
  def audience
1✔
414
    fetch("audience_ssim", [])
×
415
  end
416

417
  def available
1✔
418
    fetch("available_ssim", [])
×
419
  end
420

421
  def bibliographic_citation
1✔
422
    fetch("bibliographic_citation_ssim", [])
×
423
  end
424

425
  def conforms_to
1✔
426
    fetch("conforms_to_ssim", [])
×
427
  end
428

429
  def coverage
1✔
430
    fetch("coverage_tesim", [])
×
431
  end
432

433
  def spatial_coverage
1✔
434
    fetch("spatial_coverage_tesim", [])
×
435
  end
436

437
  def temporal_coverage
1✔
438
    fetch("temporal_coverage_tesim", [])
×
439
  end
440

441
  def dates_created
1✔
442
    fetch("date_created_ssim", [])
×
443
  end
444

445
  def date_created
1✔
446
    dates_created.first
×
447
  end
448

449
  def dates_submitted
1✔
450
    fetch("date_submitted_ssim", [])
×
451
  end
452

453
  def date_submitted
1✔
454
    dates_submitted.first
×
455
  end
456

457
  def dates_accepted
1✔
458
    fetch("date_accepted_ssim", [])
×
459
  end
460

461
  def date_accepted
1✔
462
    dates_accepted.first
×
463
  end
464

465
  def dates_copyrighted
1✔
466
    fetch("copyright_date_ssim", [])
×
467
  end
468

469
  def date_copyrighted
1✔
470
    dates_copyrighted.first
×
471
  end
472

473
  def dates_modified
1✔
474
    fetch("date_modified_ssim", [])
×
475
  end
476

477
  def date_modified
1✔
478
    dates_modified.first
×
479
  end
480

481
  def dates_valid
1✔
482
    fetch("date_valid_ssim", [])
×
483
  end
484

485
  def education_level
1✔
486
    fetch("education_level_ssim", [])
×
487
  end
488

489
  def other_identifier
1✔
490
    fetch("other_identifier_ssim", [])
×
491
  end
492

493
  def instructional_method
1✔
494
    fetch("instructional_method_ssim", [])
×
495
  end
496

497
  def mediator
1✔
498
    fetch("mediator_ssim", [])
×
499
  end
500

501
  def source
1✔
502
    fetch("source_ssim", [])
×
503
  end
504

505
  def domain
1✔
506
    fetch("domain_ssi", "")
×
507
  end
508

509
  def icon_css
1✔
510
    ICONS[genre&.downcase] || 'bi-file-earmark-fill'
6✔
511
  end
512

513
  # Returns a DatasetCitation object for the current document
514
  def citation
1✔
515
    @citation ||= begin
×
516
      year_available = fetch('year_available_itsi', nil)
×
517
      years = year_available ? [year_available.to_s] : []
×
518
      DatasetCitation.new(authors, years, title, 'Data set', publisher.first, doi_url)
×
519
    end
520
  end
521

522
  # Returns a string with the indicated citation style (e.g. APA or BibTeX)
523
  def cite(style)
1✔
524
    citation.to_s(style)
×
525
  end
526

527
  # Returns the ID for a BibTeX citation for this document.
528
  # rubocop:disable Rails/Delegate
529
  def bibtex_id
1✔
530
    citation.bibtex_id
×
531
  end
532
  # rubocop:enable Rails/Delegate
533
end
534
# 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