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

pulibrary / pdc_discovery / 6bdbb58e-50a3-48f1-97ea-998cf0c05738

pending completion
6bdbb58e-50a3-48f1-97ea-998cf0c05738

Pull #466

circleci

hectorcorrea
Note about the version of popper.js
Pull Request #466: Display author affiliation (for PDC Describe records)

49 of 49 new or added lines in 6 files covered. (100.0%)

2255 of 2337 relevant lines covered (96.49%)

188.34 hits per line

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

97.67
/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])
94✔
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
  # .*?\s is lazy match so the regex stop as soon as space is found
54
  GLOBUS_URI_REGEX = /.*(https\:\/\/app.globus.org\/file-manager.*?\s).*/.freeze
1✔
55

56
  def id
1✔
57
    fetch('id')
231✔
58
  end
59

60
  def titles
1✔
61
    fetch(TITLE_FIELD, [])
59✔
62
  end
63

64
  def title
1✔
65
    titles.first
59✔
66
  end
67

68
  # Returns the list of author names (ordered if possible)
69
  def authors
1✔
70
    authors_ordered.map(&:value)
33✔
71
  end
72

73
  # Returns the list of authors with all their information including
74
  # name, ORCID, and affiliation. List is ordered if possible.
75
  def authors_ordered
1✔
76
    @authors_ordered ||= begin
171✔
77
      authors_json = fetch('authors_json_ss', nil)
51✔
78
      if authors_json
51✔
79
        # PDC Describe records contain this field;
80
        # get the author data and sort it.
81
        authors = JSON.parse(authors_json).map { |hash| Author.new(hash) }
12✔
82
        authors.sort_by(&:sequence)
4✔
83
      else
84
        # DataSpace record don't contain this field;
85
        # do the best we can with author_tesim value.
86
        names = fetch('author_tesim', [])
47✔
87
        names.map { |name| Author.new({ "value" => name }) }
293✔
88
      end
89
    end
90
  end
91

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

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

117
  def creators
1✔
118
    fetch('creator_tesim', [])
15✔
119
  end
120

121
  def community_path
1✔
122
    communities.first
×
123
  end
124

125
  def communities
1✔
126
    fetch("communities_ssim", [])
27✔
127
  end
128

129
  def subcommunities
1✔
130
    fetch("subcommunities_ssim", [])
24✔
131
  end
132

133
  def collection_name
1✔
134
    fetch("collection_name_ssi", "")
×
135
  end
136

137
  def collection_tags
1✔
138
    fetch("collection_tag_ssim", [])
30✔
139
  end
140

141
  def contributors
1✔
142
    fetch("contributor_tsim", [])
15✔
143
  end
144

145
  def accessioned_dates
1✔
146
    fetch("date_accessioned_ssim", [])
15✔
147
  end
148

149
  def accessioned_date
1✔
150
    accessioned_dates.first
15✔
151
  end
152

153
  def issued_dates
1✔
154
    fetch(ISSUED_DATE_FIELD, [])
59✔
155
  end
156

157
  def issued_date
1✔
158
    issued_dates.first
59✔
159
  end
160

161
  def abstracts
1✔
162
    fetch(ABSTRACT_FIELD, [])
15✔
163
  end
164

165
  def abstract
1✔
166
    abstracts.first
×
167
  end
168

169
  def descriptions
1✔
170
    fetch(DESCRIPTION_FIELD, [])
28✔
171
  end
172

173
  def description
1✔
174
    descriptions.first
13✔
175
  end
176

177
  def methods
1✔
178
    fetch(METHODS_FIELD, [])
×
179
  end
180

181
  def data_source
1✔
182
    fetch("data_source_ssi", "dataspace")
77✔
183
  end
184

185
  def files
1✔
186
    @files ||= begin
47✔
187
      data = JSON.parse(fetch("files_ss", "[]"))
17✔
188
      data.map { |file| DatasetFile.from_hash(file, data_source) }.sort_by(&:sequence)
50✔
189
    end
190
  end
191

192
  # Returns an array with the counts by file extension
193
  # e.g. [{extension: "txt", file_count: 3}, {extension: "csv", file_count: 1}]
194
  def file_counts
1✔
195
    groups = files.group_by(&:extension)
18✔
196
    groups.map { |key, value| { extension: key, file_count: value.count } }.sort_by { |group| -group[:file_count] }
80✔
197
  end
198

199
  def table_of_contents
1✔
200
    fetch("tableofcontents_tesim", [])
15✔
201
  end
202

203
  def referenced_by
1✔
204
    fetch("referenced_by_ssim", [])
15✔
205
  end
206

207
  def uri
1✔
208
    fetch("uri_ssim", [])
73✔
209
  end
210

211
  def doi_url
1✔
212
    uri.each do |link|
45✔
213
      return link if link.downcase.start_with?('https://doi.org/')
51✔
214
    end
215
    nil
216
  end
217

218
  def doi_value
1✔
219
    doi_url&.gsub('https://doi.org/', '')
15✔
220
  end
221

222
  def format
1✔
223
    fetch("format_ssim", [])
15✔
224
  end
225

226
  def globus_uri
1✔
227
    # First we try to use the value indexed (only exists for PDC Describe records)
228
    indexed_uri = fetch("globus_uri_ssi", nil)
17✔
229
    return indexed_uri unless indexed_uri.nil?
17✔
230

231
    # ...then check the links indexed to see if one of them looks like a Globus URI
232
    uri.each do |link|
13✔
233
      return link if link.downcase.start_with?('https://app.globus.org/')
16✔
234
    end
235

236
    # ...if all fails, see if there is a Globus URI in the description
237
    globus_uri_from_description
10✔
238
  end
239

240
  def globus_uri_from_description
1✔
241
    match = description&.match(GLOBUS_URI_REGEX)
13✔
242
    return match.captures.first.strip if match
13✔
243
  end
244

245
  def extent
1✔
246
    fetch("extent_ssim", [])
15✔
247
  end
248

249
  def medium
1✔
250
    fetch("medium_ssim", [])
15✔
251
  end
252

253
  def mimetype
1✔
254
    fetch("mimetype_ssim", [])
15✔
255
  end
256

257
  def language
1✔
258
    fetch("language_ssim", [])
15✔
259
  end
260

261
  def publisher
1✔
262
    fetch("publisher_ssim", [])
30✔
263
  end
264

265
  def publisher_place
1✔
266
    fetch("publisher_place_ssim", [])
15✔
267
  end
268

269
  def publisher_corporate
1✔
270
    fetch("publisher_corporate_ssim", [])
15✔
271
  end
272

273
  def relation
1✔
274
    fetch("relation_ssim", [])
15✔
275
  end
276

277
  def relation_is_format_of
1✔
278
    fetch("relation_is_format_of_ssim", [])
15✔
279
  end
280

281
  def relation_has_format
1✔
282
    fetch("relation_has_format_ssim", [])
15✔
283
  end
284

285
  def relation_is_part_of
1✔
286
    fetch("relation_is_part_of_ssim", [])
15✔
287
  end
288

289
  def relation_is_part_of_series
1✔
290
    fetch("relation_is_part_of_series_ssim", [])
15✔
291
  end
292

293
  def relation_has_part
1✔
294
    fetch("relation_has_part_ssim", [])
15✔
295
  end
296

297
  def relation_is_version_of
1✔
298
    fetch("relation_is_version_of_ssim", [])
15✔
299
  end
300

301
  def relation_has_version
1✔
302
    fetch("relation_has_version_ssim", [])
15✔
303
  end
304

305
  def relation_is_based_on
1✔
306
    fetch("relation_is_based_on_ssim", [])
15✔
307
  end
308

309
  def relation_is_referenced_by
1✔
310
    fetch("relation_is_referenced_by_ssim", [])
15✔
311
  end
312

313
  def relation_is_required_by
1✔
314
    fetch("relation_is_required_by_ssim", [])
15✔
315
  end
316

317
  def relation_requires
1✔
318
    fetch("relation_requires_ssim", [])
15✔
319
  end
320

321
  def relation_replaces
1✔
322
    fetch("relation_replaces_ssim", [])
15✔
323
  end
324

325
  def relation_is_replaced_by
1✔
326
    fetch("relation_is_replaced_by_ssim", [])
15✔
327
  end
328

329
  def relation_uri
1✔
330
    fetch("relation_uri_ssim", [])
15✔
331
  end
332

333
  def rights
1✔
334
    fetch("rights_ssim", [])
12✔
335
  end
336

337
  def rights_uri
1✔
338
    fetch("rights_uri_ssim", [])
12✔
339
  end
340

341
  # For PDC Describe records we have a single value for the name and the uri
342
  # and we can safely assume they are related.
343
  def rights_name_and_uri
1✔
344
    name = fetch("rights_name_ssi", nil)
21✔
345
    uri = fetch("rights_uri_ssi", nil)
21✔
346
    return nil if name.nil? || uri.nil?
21✔
347
    { name: name, uri: uri }
9✔
348
  end
349

350
  def rights_holder
1✔
351
    fetch("rights_holder_ssim", [])
15✔
352
  end
353

354
  def subject
1✔
355
    fetch("subject_tesim", [])
15✔
356
  end
357

358
  def subject_classification
1✔
359
    fetch("subject_classification_tesim", [])
15✔
360
  end
361

362
  def subject_ddc
1✔
363
    fetch("subject_ddc_tesim", [])
15✔
364
  end
365

366
  def subject_lcc
1✔
367
    fetch("subject_lcc_tesim", [])
15✔
368
  end
369

370
  def subject_lcsh
1✔
371
    fetch("subject_lcsh_tesim", [])
15✔
372
  end
373

374
  def subject_mesh
1✔
375
    fetch("subject_mesh_tesim", [])
15✔
376
  end
377

378
  def subject_other
1✔
379
    fetch("subject_other_tesim", [])
15✔
380
  end
381

382
  def alternative_title
1✔
383
    fetch("alternative_title_tesim", [])
15✔
384
  end
385

386
  def genres
1✔
387
    fetch("genre_ssim", []).sort
45✔
388
  end
389

390
  # Sometimes we need a single genre for an item, even though an item may have more than one.
391
  # This method makes sure we always get the same value (the first one from a sorted list).
392
  def genre
1✔
393
    genres.first
30✔
394
  end
395

396
  def peer_review_status
1✔
397
    fetch("peer_review_status_ssim", [])
15✔
398
  end
399

400
  def translator
1✔
401
    fetch("translator_ssim", [])
15✔
402
  end
403

404
  def isan
1✔
405
    fetch("isan_ssim", [])
15✔
406
  end
407

408
  def access_rights
1✔
409
    fetch("access_rights_ssim", [])
15✔
410
  end
411

412
  def funding_agency
1✔
413
    fetch("funding_agency_ssim", [])
15✔
414
  end
415

416
  def provenance
1✔
417
    fetch("provenance_ssim", [])
15✔
418
  end
419

420
  def license
1✔
421
    fetch("license_ssim", [])
15✔
422
  end
423

424
  def accrual_method
1✔
425
    fetch("accrual_method_ssim", [])
15✔
426
  end
427

428
  def accrual_periodicity
1✔
429
    fetch("accrual_periodicity_ssim", [])
15✔
430
  end
431

432
  def accrual_policy
1✔
433
    fetch("accrual_policy_ssim", [])
15✔
434
  end
435

436
  def audience
1✔
437
    fetch("audience_ssim", [])
15✔
438
  end
439

440
  def available
1✔
441
    fetch("available_ssim", [])
15✔
442
  end
443

444
  def bibliographic_citation
1✔
445
    fetch("bibliographic_citation_ssim", [])
15✔
446
  end
447

448
  def conforms_to
1✔
449
    fetch("conforms_to_ssim", [])
15✔
450
  end
451

452
  def coverage
1✔
453
    fetch("coverage_tesim", [])
15✔
454
  end
455

456
  def spatial_coverage
1✔
457
    fetch("spatial_coverage_tesim", [])
15✔
458
  end
459

460
  def temporal_coverage
1✔
461
    fetch("temporal_coverage_tesim", [])
15✔
462
  end
463

464
  def dates_created
1✔
465
    fetch("date_created_ssim", [])
15✔
466
  end
467

468
  def date_created
1✔
469
    dates_created.first
15✔
470
  end
471

472
  def dates_submitted
1✔
473
    fetch("date_submitted_ssim", [])
15✔
474
  end
475

476
  def date_submitted
1✔
477
    dates_submitted.first
15✔
478
  end
479

480
  def dates_accepted
1✔
481
    fetch("date_accepted_ssim", [])
15✔
482
  end
483

484
  def date_accepted
1✔
485
    dates_accepted.first
15✔
486
  end
487

488
  def dates_copyrighted
1✔
489
    fetch("copyright_date_ssim", [])
15✔
490
  end
491

492
  def date_copyrighted
1✔
493
    dates_copyrighted.first
15✔
494
  end
495

496
  def dates_modified
1✔
497
    fetch("date_modified_ssim", [])
15✔
498
  end
499

500
  def date_modified
1✔
501
    dates_modified.first
15✔
502
  end
503

504
  def dates_valid
1✔
505
    fetch("date_valid_ssim", [])
15✔
506
  end
507

508
  def education_level
1✔
509
    fetch("education_level_ssim", [])
15✔
510
  end
511

512
  def other_identifier
1✔
513
    fetch("other_identifier_ssim", [])
15✔
514
  end
515

516
  def instructional_method
1✔
517
    fetch("instructional_method_ssim", [])
15✔
518
  end
519

520
  def mediator
1✔
521
    fetch("mediator_ssim", [])
15✔
522
  end
523

524
  def source
1✔
525
    fetch("source_ssim", [])
15✔
526
  end
527

528
  def domains
1✔
529
    fetch("domain_ssim", "")
26✔
530
  end
531

532
  def icon_css
1✔
533
    ICONS[genre&.downcase] || 'bi-file-earmark-fill'
16✔
534
  end
535

536
  # Returns a DatasetCitation object for the current document
537
  def citation
1✔
538
    @citation ||= begin
60✔
539
      year_available = fetch('year_available_itsi', nil)
15✔
540
      years = year_available ? [year_available.to_s] : []
15✔
541
      DatasetCitation.new(authors, years, title, 'Data set', publisher.first, doi_url)
15✔
542
    end
543
  end
544

545
  # Returns a string with the indicated citation style (e.g. APA or BibTeX)
546
  def cite(style)
1✔
547
    citation.to_s(style)
45✔
548
  end
549

550
  # Returns the ID for a BibTeX citation for this document.
551
  # rubocop:disable Rails/Delegate
552
  def bibtex_id
1✔
553
    citation.bibtex_id
×
554
  end
555
  # rubocop:enable Rails/Delegate
556
end
557
# 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