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

pulibrary / pdc_describe / 9091a1ae-29be-458c-984a-339d213919c4

12 Dec 2024 07:41PM UTC coverage: 26.434% (-69.7%) from 96.113%
9091a1ae-29be-458c-984a-339d213919c4

Pull #2000

circleci

jrgriffiniii
Removing integration with ActiveStorage
Pull Request #2000: Bump actionpack from 7.2.1.1 to 7.2.2.1

945 of 3575 relevant lines covered (26.43%)

0.35 hits per line

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

18.6
/app/models/dataset_citation.rb
1
# frozen_string_literal: true
2

3
# Handles citations for datasets
4
# rubocop:disable Metrics/ParameterLists
5
# rubocop:disable Metrics/ClassLength
6
# rubocop:disable Style/NumericPredicate
7
# rubocop:disable Style/IfUnlessModifier
8
class DatasetCitation
1✔
9
  NEWLINE_INDENTED = "\r\n\t\t\t\t\t\t\t\t"
1✔
10

11
  # @param authors [<String>] Array of authors.
12
  # @param years [<String>] Array of years (expected 1 or 2 values).
13
  # @param title [String>] Title of the dataset
14
  # @param type [String] Type of the dataset (e.g. "Data set" or "Unpublished raw data")
15
  # @publisher [String] Publisher of the dataset
16
  # @doi [String] DOI URL
17
  def initialize(authors, years, title, type, publisher, doi)
1✔
18
    @authors = authors || []
×
19
    @years = years || []
×
20
    @title = title
×
21
    @type = type
×
22
    @publisher = publisher
×
23
    @doi = doi
×
24
  end
25

26
  def to_s(style)
1✔
27
    if style == "BibTeX"
×
28
      bibtex
×
29
    else
30
      apa
×
31
    end
32
  end
33

34
  # Returns a string with APA-ish citation for the dataset
35
  # Reference: https://libguides.usc.edu/APA7th/datasets#s-lg-box-22855503
36
  def apa
1✔
37
    apa_title = DatasetCitation.custom_strip(@title)
×
38
    apa_title += " [#{@type}]" if @type.present?
×
39
    apa_title = append_dot(apa_title)
×
40

41
    apa_publisher = append_dot(@publisher)
×
42
    apa_doi = @doi
×
43

44
    tokens = [append_dot(apa_author), append_dot(apa_year), apa_title, apa_publisher, apa_doi].compact_blank
×
45
    tokens.join(" ")
×
46
  rescue => ex
47
    Rails.logger.error "Error generating APA citation for (#{@title}): #{ex.message}"
×
48
    nil
×
49
  end
50

51
  # Returns a string with BibTeX citation for the dataset.
52
  #
53
  # There is no set standard for datasets and therefore the format we produce
54
  # was put together from a variety of sources including mimicking what Zotero
55
  # does and looking at examples from Zenodo (e.g. https://zenodo.org/record/6062882/export/hx#.Yiejad9OnUL)
56
  #
57
  # Notice that we use the @electronic{...} identifier instead of @dataset{...} since
58
  # Zotero does not recognize the later.
59
  def bibtex
1✔
60
    tokens = bibtex_checks
×
61

62
    text = "@electronic{#{bibtex_id},\r\n"
×
63
    text += tokens.map { |token| "\t#{token}" }.join(",\r\n") + "\r\n"
×
64
    text += "}"
×
65
    text
×
66
  rescue => ex
67
    Rails.logger.error "Error generating BibTex citation for (#{@title}): #{ex.message}"
×
68
    nil
×
69
  end
70

71
  # Returns an ID value for a BibTex citation
72
  def bibtex_id
1✔
73
    author_id = "unknown"
×
74
    if @authors.count > 0
×
75
      author_id = @authors.first.downcase.tr(" ", "_").gsub(/[^a-z0-9_]/, "")
×
76
    end
77
    year_id = @years.first&.to_s || "unknown"
×
78
    "#{author_id}_#{year_id}"
×
79
  end
80

81
  # Breaks a string into lines of at most max_length.
82
  # Returns an array with the lines.
83
  def bibtex_lines(string, max_length = 40)
1✔
84
    string = string.to_s # handles non-string values gracefully
×
85
    lines = []
×
86
    until string.nil?
×
87
      # TODO: it would be nice it we break on spaces rather than in the middle of a word.
88
      lines << string[0..max_length - 1]
×
89
      string = string[max_length..-1]
×
90
    end
91
    lines
×
92
  end
93

94
  # Creates a line to represent a BibTex field.
95
  # Breaks long lines into smaller lines.
96
  # Examples:
97
  #
98
  #     field_name = {{ short value }}
99
  #     field_name = {{ very very very
100
  #                 very very very very
101
  #                 long value }}
102
  #
103
  def bibtex_field(name, value, open_tag = "", close_tag = "")
1✔
104
    return nil if value.blank?
×
105

106
    value_trim = bibtex_lines(value).join(NEWLINE_INDENTED)
×
107
    name.ljust(12) + "= " + open_tag + value_trim + close_tag
×
108
  end
109

110
  # Creates a line to represent multiple authors in a BibTex field
111
  # https://en.wikibooks.org/wiki/LaTeX/Bibliography_Management#Authors
112
  #
113
  # Example:
114
  #
115
  #     author = { author1 and
116
  #              author2 and
117
  #              author3 }
118
  #
119
  def bibtex_field_author(name, authors, open_tag = "{", close_tag = "}")
1✔
120
    return nil if @authors.count <= 0
×
121

122
    value_trim = authors.join(" and #{NEWLINE_INDENTED}")
×
123
    name.ljust(12) + "= " + open_tag + value_trim + close_tag
×
124
  end
125

126
  # Appends a dot to a string if it does not end with one.
127
  def append_dot(value)
1✔
128
    return nil if value.nil?
×
129
    return "" if value.empty?
×
130
    DatasetCitation.custom_strip(value) + "."
×
131
  end
132

133
  # Strip a few specific characters that tend to mess up citations (e.g. trailing periods, commas, et cetera)
134
  def self.custom_strip(value)
1✔
135
    return nil if value.nil?
×
136
    return "" if value.empty?
×
137
    while true
×
138
      last_char = value[-1]
×
139
      break if last_char.nil? || !last_char.in?(". ,")
×
140
      value = value.chomp(last_char)
×
141
    end
142
    value
×
143
  end
144

145
  private
1✔
146

147
    def apa_author
1✔
148
      apa_author = ""
×
149
      case @authors.count
×
150
      when 0
151
        # do nothing
152
      when 1
153
        apa_author += @authors.first
×
154
      when 2
155
        apa_author += @authors.join(" & ")
×
156
      else
157
        apa_author += @authors[0..-2].join(", ") + ", & " + @authors[-1]
×
158
      end
159
      apa_author
×
160
    end
161

162
    def apa_year
1✔
163
      apa_year = ""
×
164
      case @years.count
×
165
      when 0
166
        # do nothing
167
      when 1
168
        apa_year += "(#{@years.first})"
×
169
      else
170
        apa_year += "(#{@years.join('-')})"
×
171
      end
172
      apa_year
×
173
    end
174

175
    def bibtex_checks
1✔
176
      tokens = []
×
177

178
      tokens << bibtex_field_author("author", @authors)
×
179

180
      tokens << bibtex_field("title", @title, "{{", "}}")
×
181

182
      tokens << bibtex_field("publisher", @publisher, "{{", "}}")
×
183

184
      tokens << bibtex_field("year", @years.first)
×
185

186
      tokens << bibtex_field("url", @doi, "{", "}")
×
187

188
      tokens.compact # remove nil values
×
189
    end
190
end
191
# rubocop:enable Metrics/ParameterLists
192
# rubocop:enable Metrics/ClassLength
193
# rubocop:enable Style/NumericPredicate
194
# rubocop:enable Style/IfUnlessModifier
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