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.



201
202
203
204
205
206
207
208
209
210
211
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
# File 'app/models/protonym/format.rb', line 201

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>]]]]


323
324
325
326
327
328
329
330
331
332
333
# File 'app/models/protonym/format.rb', line 323

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)


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

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.



266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'app/models/protonym/format.rb', line 266

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



280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'app/models/protonym/format.rb', line 280

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.



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'app/models/protonym/format.rb', line 296

def get_original_combination_html
  return verbatim_name if !GENUS_AND_SPECIES_RANK_NAMES.include?(rank_string) && !verbatim_name.nil?
  return  "\"<i>Candidatus</i> #{get_original_combination}\"" if is_candidatus?

  # 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



361
362
363
364
365
366
367
# File 'app/models/protonym/format.rb', line 361

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`



347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'app/models/protonym/format.rb', line 347

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



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'app/models/protonym/format.rb', line 164

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