Module: Protonym::Format

Extended by:
ActiveSupport::Concern
Included in:
Protonym
Defined in:
app/models/protonym/format.rb

Overview

Methods for gathering elements for use in constructing names from the graph of data.

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#full_name_hashObject

This method covers scientific name, gathering all string elements, including ‘[sic]’ and pointing to them by rank.



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'app/models/protonym/format.rb', line 212

def full_name_hash
  gender = nil
  data = {}

  # Faster to sort in memory.
  r = TaxonName.rank_order(
    self_and_ancestors.unscope(:order)
  )

  # In the first pass we build out the known vectors
  r.each do |i|
    rank = i.rank

    # Sort order is critical, we need to hit genus before
    # species name to set a gender constant.
    gender = i.cached_gender if rank == 'genus'

    if i.is_genus_or_species_rank?
      if ['genus', 'subgenus', 'species', 'subspecies'].include?(rank) && rank_string =~ /Iczn/
        data[rank] = i.genderized_elements(gender)
      elsif ['genus', 'subgenus', 'species'].include?(rank)
        data[rank] = i.genderized_elements(gender)
      else
        v = i.genderized_elements(gender)
        v[0] = i.rank_class.abbreviation
        data[rank] = v
      end
    else
      data[rank] = i.name
    end
  end

  # In the second pass we populate gaps where we can infer them,
  # for rendering purposes.
  if TaxonName::COMBINATION_ELEMENTS.include?(rank.to_sym)
    if data['genus'].nil?
      if original_genus
        data['genus'] = [nil, "[#{original_genus&.name}]"]
      else
        data['genus'] = [nil, '[GENUS NOT SPECIFIED]']
      end
    end

    if data['species'].nil? && (!data['subspecies'].nil? || !data['variety'].nil? || !data['subvariety'].nil? || !data['form'].nil? || !data['subform'].nil?)
      data['species'] = [nil, '[SPECIES NOT SPECIFIED]']
    end

    if !data['subvariety'].nil? && data['variety'].nil?
      data['variety'] = [nil, '[VARIETY NOT SPECIFIED]']
    end

    if !data['subform'].nil? && data['form'].nil?
      data['form'] = [nil, '[FORM NOT SPECIFIED]']
    end
  end

  data
end

#genderized_elements(gender) ⇒ Object

!! No parens shoould be added here

Returns:

  • an Array

    <rank abbreiviation>, name, <misspelling tag>]]]]


336
337
338
339
340
341
342
343
344
345
346
# File 'app/models/protonym/format.rb', line 336

def genderized_elements(gender)
  n = genderized_name(gender)

  if n.blank?
    n = verbatim_name.nil? ? name : verbatim_name
  end

  v = [nil, n]
  v.push misspelling_tag if cached_misspelling
  v
end

#genderized_name(gender = nil) ⇒ String?

Returns:

  • (String, nil)


349
350
351
352
353
354
355
# File 'app/models/protonym/format.rb', line 349

def genderized_name(gender = nil)
  if gender.nil? || is_genus_rank?
    name
  else
    name_in_gender(gender)
  end
end

#get_full_nameString?

Returns A monominal if names is above genus, or a full epithet if below. Does not include author_year. Does not include HTML.

!! Combination has its own version now.

Returns:

  • (String, nil)

    A monominal if names is above genus, or a full epithet if below. Does not include author_year. Does not include HTML.

    !! Combination has its own version now.



277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'app/models/protonym/format.rb', line 277

def get_full_name
  # TODO: eliminate these for full_name_hash
  return [name, (cached_misspelling? ? misspelling_tag : nil)].compact.join(' ') if !is_genus_or_species_rank?
  return name if rank_class.to_s =~ /Icvcn/

  # Technically we don't always want/need full_name_hash, as it gives us
  # all ancestors.
  ::Utilities::Nomenclature.full_name(
    full_name_hash,
    rank: rank_name,
    non_binomial: not_binominal?
  )
end

#get_original_combinationObject



291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'app/models/protonym/format.rb', line 291

def get_original_combination
  return verbatim_name if !GENUS_AND_SPECIES_RANK_NAMES.include?(rank_string) && !verbatim_name.nil?
  e = original_combination_elements
  return nil if e.none?

  # TODO: try to catch this before we hit it here.
  # In ICVCN the species name is "Potato spindle tuber viroid", the genus name is only used for classification
  return e[:species][1] if rank_class.to_s =~ /Icvcn/

  # Order the results.
  s = TaxonName::COMBINATION_ELEMENTS.collect{|k| e[k]}.flatten.compact.join(' ')
  @_cached_build_state[:original_combination] = s.presence
end

#get_original_combination_htmlObject

TODO: Deprecate for pattern in Utilities::Nomencalture.htmlize This should never require hitting the database.



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'app/models/protonym/format.rb', line 307

def get_original_combination_html
  return verbatim_name if !GENUS_AND_SPECIES_RANK_NAMES.include?(rank_string) && !verbatim_name.nil?
  if is_candidatus?
    return cached_html if get_original_combination.nil?
    return  "\"<i>Candidatus</i> #{get_original_combination}\""
  end
  # x = get_original_combination
  # y = cached_original_combination # In a transaction this is not available
  v = @_cached_build_state[:original_combination]

  return nil if v.blank?

  if is_hybrid?
    w = v.split(' ')
    w[-1] = ('×' + w[-1]).gsub('×(', '').gsub(') [sic]', ' [sic])').gsub(') (sic)', ' (sic))')
    v = w.join(' ')
  end

  v = v.gsub(') [sic]', ' [sic])').gsub(') (sic)', ' (sic))')

  v = Utilities::Italicize.taxon_name(v) if is_genus_or_species_rank?
  v = '' + v  if is_fossil? # This doesn't belong here, it's touching the DB.
  v
end

#misspelling_tagObject



374
375
376
377
378
379
380
# File 'app/models/protonym/format.rb', line 374

def misspelling_tag
  if rank_string =~ /Icnp/
    '(sic)'
  else
    '[sic]'
  end
end

#name_in_gender(gender = nil) ⇒ Object

Returns String then name according to the gender requested, if none, then ‘name`.

Parameters:

  • gender,

    String

Returns:

  • String then name according to the gender requested, if none, then ‘name`



360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'app/models/protonym/format.rb', line 360

def name_in_gender(gender = nil)
  case gender
  when 'masculine'
    n = masculine_name
  when 'feminine'
    n = feminine_name
  when 'neuter'
    n = neuter_name
  else
    n = nil
  end
  n.presence || name
end

#original_combination_flatObject

End Class methods



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'app/models/protonym/format.rb', line 175

def original_combination_flat
  s = []
  ::ORIGINAL_COMBINATION_RANKS.each do |rank, t|
    s.push "MAX(name) FILTER (WHERE rt = '#{t}') AS #{rank},
            MAX(cached_gender) FILTER (WHERE rt = '#{t}') AS #{rank}_gender,
            MAX(neuter_name) FILTER (WHERE rt = '#{t}') AS #{rank}_neuter,
            MAX(masculine_name) FILTER (WHERE rt = '#{t}') AS #{rank}_masculine,
            MAX(feminine_name) FILTER (WHERE rt = '#{t}') AS #{rank}_feminine"
  end

  a = Protonym
    .joins(:original_combination_relationships)
    .where(taxon_name_relationships: {
      object_taxon_name_id: id
    }).select(:id, :name, :cached_gender, :neuter_name, :masculine_name, :feminine_name, 'taxon_name_relationships.type as rt')

  Protonym.with(filtered: a).select(s.join(',')).from('filtered').unscope(:where)[0]
end