Module: Export::Coldp

Defined in:
lib/export/coldp.rb

Overview

Exports to the Catalog of Life in the new “coldp” format. api.col.plus/datapackage

TODO:

then each module will provide a correspond method to each field github.com/frictionlessdata/datapackage-rb github.com/frictionlessdata/tableschema-rb

  • write tests to check for coverage (missing methods)

  • Update all files formats to use tabs

  • Pending handling of both BibTeX and Verbatim

Constant Summary collapse

FILETYPES =
%w{Description Name Synonym VernacularName}.freeze

Class Method Summary collapse

Class Method Details

.basionym_id(taxon_name) ⇒ Object

Parameters:

  • taxon_name (a valid Protonym or a Combination)

    see also exclusion of OTUs/Names based on Ranks not handled



125
126
127
128
129
130
131
132
133
# File 'lib/export/coldp.rb', line 125

def self.basionym_id(taxon_name)
  if taxon_name.type == 'Protonym'
    taxon_name.id
  elsif taxon_name.type == 'Combination'
    taxon_name.protonyms.last.id
  else
    nil # shouldn't be hit
  end
end

.download(otu, request = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/export/coldp.rb', line 70

def self.download(otu, request = nil)
  file_path = ::Export::Coldp.export(otu.id)
  name = "coldp_otu_id_#{otu.id}_#{DateTime.now}.zip"

  ::Download.create!(
    name: "ColDP Download for #{otu.otu_name} on #{Time.now}.",
    description: 'A zip file containing CoLDP formatted data.',
    filename: name,
    source_file_path: file_path,
    request: request,
    expires: 2.days.from_now
  )
end

.download_async(otu, request = nil) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/export/coldp.rb', line 84

def self.download_async(otu, request = nil)
  download = ::Download.create!(
    name: "ColDP Download for #{otu.otu_name} on #{Time.now}.",
    description: 'A zip file containing CoLDP formatted data.',
    filename: "coldp_otu_id_#{otu.id}_#{DateTime.now}.zip",
    request: request,
    expires: 2.days.from_now
  )

  ColdpCreateDownloadJob.perform_later(otu, download)

  download
end

.export(otu_id) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/export/coldp.rb', line 34

def self.export(otu_id)
  otus = otus(otu_id)

  # source_id => [csv_array]
  ref_csv = {}

  # TODO: This will likely have to change, it is renamed on serving the file.
  zip_file_path = "/tmp/_#{SecureRandom.hex(8)}_coldp.zip"

  Zip::File.open(zip_file_path, Zip::File::CREATE) do |zipfile|
    (FILETYPES - ['Name']).each do |ft|
      m = "Export::Coldp::Files::#{ft}".safe_constantize
      zipfile.get_output_stream("#{ft}.csv") { |f| f.write m.generate(otus, ref_csv) }
    end

    zipfile.get_output_stream('Name.csv') { |f| f.write Export::Coldp::Files::Name.generate( Otu.find(otu_id), ref_csv) }
    zipfile.get_output_stream('Taxon.csv') { |f| f.write Export::Coldp::Files::Taxon.generate( otus, otu_id, ref_csv) }


    # Sort the refs by full citation string
    sorted_refs = ref_csv.values.sort{|a,b| a[1] <=> b[1]}

    d = CSV.generate(col_sep: "\t") do |csv|
      csv << %w{ID citation	doi} # author year source details
      sorted_refs.each do |r|
        csv << r 
      end
    end

    zipfile.get_output_stream('References.csv') { |f| f.write d }

  end

  zip_file_path
end

.original_field(taxon_name) ⇒ Boolean

Returns true if no parens in cached_author_year false if parens in cached_author_year

Returns:

  • (Boolean)

    true if no parens in cached_author_year false if parens in cached_author_year



103
104
105
# File 'lib/export/coldp.rb', line 103

def self.original_field(taxon_name)
  (taxon_name.type == 'Protonym') && taxon_name.is_original_name?
end

.otus(otu_id) ⇒ Scope

TODO: include options for validity, sets of tags, etc. At present otus are a mix of valid and invalid

Returns:

  • (Scope)

    Should return the full set of Otus (= Taxa in CoLDP) that are to be sent.



26
27
28
29
30
31
32
# File 'lib/export/coldp.rb', line 26

def self.otus(otu_id)
  o = ::Otu.find(otu_id)
  return ::Otu.none if o.taxon_name_id.nil?
  
  a = o.taxon_name.self_and_descendants
  ::Otu.joins(:taxon_name).where(taxon_name: a)
end

.reified_id(taxon_name) ⇒ Object

There are suite of issues with TaxonWorks model all tied to the fact that we do not treat original combinations (lower case) as Combinations (model). All these problems go away if/when we remodel the original Combination. These problems include:

* inablity to site historical usages of the protonym that are properly latinized (e.g. var or f. names as subspecies)
* providing unique IDs for form/var names

Parameters:

  • taxon_name (an invalid Protonym)


114
115
116
117
118
119
120
121
# File 'lib/export/coldp.rb', line 114

def self.reified_id(taxon_name)
  if taxon_name.original_combination_relationships.any?
    taxon_name.id.to_s + '/' + Digest::MD5.hexdigest(taxon_name.cached_original_combination)
  else
    # there is no need to MD5 the name, as it hasn't been potentially altered by original combination assertions
    taxon_name.id.to_s
  end
end