Class: Otu

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
Housekeeping, Shared::Citable, Shared::Confidence, Shared::DataAttributes, Shared::Depictions, Shared::Identifiable, Shared::IsData, Shared::Loanable, Shared::Notable, Shared::Taggable, SoftValidation
Defined in:
app/models/otu.rb

Overview

An Otu (loosely, operational taxonomic unit) can be thought of as a unit of study. In most cases an otu is a taxon.

An Otu is defined by its underlying data and may be labeled with a name (TaxonName). Otus are used to represent rows in matrices, taxon pages, individuals or populations, or arbitrary clusters of organisms (e.g. 'unsorted specimens in this container'). Otus are a primary unit of work in TaxonWorks.

OTU is labeled with a name, either arbitrarily given or specifically linked to a taxon_name_id.

Constant Summary

Constant Summary

Constants included from SoftValidation

SoftValidation::ANCESTORS_WITH_SOFT_VALIDATIONS

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from SoftValidation

#clear_soft_validations, #fix_soft_validations, #soft_fixed?, #soft_valid?, #soft_validate, #soft_validated?, #soft_validations

Methods included from Housekeeping

#has_polymorphic_relationship?

Instance Attribute Details

- (String) name

A label for the OTU.

Returns:

  • (String)


23
24
25
26
27
28
29
30
31
32
33
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'app/models/otu.rb', line 23

class Otu < ActiveRecord::Base

  # TODO Add simple semantics (same_as etc.) describing taxon_name_id

  include Housekeeping
  #include Shared::AlternateValues  # 1/26/15 with MJY - not going to allow alternate values in Burlap
  include Shared::Citable               # TODO: have to think hard about this vs. using Nico's framework
  include Shared::DataAttributes
  include Shared::Identifiable
  include Shared::Notable
  include Shared::Taggable
  include Shared::IsData
  include Shared::Depictions
  include Shared::Loanable
  include Shared::Confidence

  include SoftValidation

  has_paper_trail :on => [:update] 

  belongs_to :taxon_name, inverse_of: :otus

  has_many :asserted_distributions, inverse_of: :otu
  has_many :collecting_events, -> { uniq }, through: :collection_objects

  has_many :collection_objects, through: :taxon_determinations, source: :biological_collection_object, inverse_of: :otus, class_name: 'CollectionObject::BiologicalCollectionObject'
  has_many :taxon_determinations, inverse_of: :otu, dependent: :destroy

  has_many :common_names, dependent: :destroy 
  has_many :collection_profiles # @proceps dependent: what?
  has_many :contents, inverse_of: :otu, dependent: :destroy
  has_many :geographic_areas_from_asserted_distributions, through: :asserted_distributions, source: :geographic_area
  has_many :geographic_areas_from_collecting_events, through: :collecting_events, source: :geographic_area
  has_many :georeferences, through: :collecting_events

  has_many :content_topics, through: :contents, source: :topic

  scope :with_taxon_name_id, -> (taxon_name_id) { where(taxon_name_id: taxon_name_id) }
  scope :with_name, -> (name) { where(name: name) }

  # @return scope
  def self.self_and_descendants_of(otu_id)
    o = Otu.includes(:taxon_name).find(otu_id)
    if o && o.taxon_name
      with_taxon_name_id(Otu.find(otu_id).taxon_name.self_and_descendants)
    else
      Otu.where(id: otu_id)
    end
  end

  validate :check_required_fields

  soft_validate(:sv_taxon_name, set: :taxon_name)
  soft_validate(:sv_duplicate_otu, set: :duplicate_otu)

  accepts_nested_attributes_for :common_names, allow_destroy: true

  #region class methods

  # return [Scope] the otus bound to that taxon name and its descendants
  def self.for_taxon_name(taxon_name)
    if taxon_name.kind_of?(String) || taxon_name.kind_of?(Integer) 
      tn = TaxonName.find(taxon_name)
    else
      tn = taxon_name
    end
    Otu.joins(taxon_name: [:ancestor_hierarchies]).where(taxon_name_hierarchies: {ancestor_id: tn.id} )
  end

  # TODO: This need to be renamed to reflect "simple" association
  def self.batch_preview(file: nil, ** args)
    # f     = CSV.read(file, headers: true, col_sep: "\t", skip_blanks: true, header_converters: :symbol)
    @otus = []
    File.open(file).each do |row|
      name = row.strip
      next if name.blank?
      @otus.push(Otu.new(name: row.strip))
    end
    @otus
  end

  def self.batch_create(otus: {}, ** args)
    new_otus = []
    begin
      Otu.transaction do
        otus.keys.each do |k|
          o = Otu.new(otus[k])
          o.save!
          new_otus.push(o)
        end
      end
    rescue
      return false
    end
    new_otus
  end

  #endregion

  #region instance methods
  # Hernán - this is extremely hacky, I'd like to
  # map core keys to procs, use yield:, use cached values,
  # add logic for has_many handling (e.g. identifiers) etc.
  # ultmately, each key maps to a proc that returns a value
  #
  # deprecated for new approach in CollectionObject, AssertedDistribution
  def dwca_core
    core = Dwca::GbifProfile::CoreTaxon.new

    core.nomenclaturalCode        = (taxon_name.rank_class.nomenclatural_code.to_s.upcase)
    core.taxonomicStatus          = (taxon_name.unavailable_or_invalid? ? nil : 'accepted')
    core.nomenclaturalStatus      = (taxon_name.classification_invalid_or_unavailable? ? nil : 'available') # needs tweaking
    core.scientificName           = taxon_name.cached
    core.scientificNameAuthorship = taxon_name.cached_author_year
    core.scientificNameID         = taxon_name.identifiers.first.identifier
    core.taxonRank                = taxon_name.rank
    core.namePublishedIn          = taxon_name.source.cached
    core
  end

  def otu_name
    if !name.blank?
      name
    elsif !self.taxon_name_id.nil?
      self.taxon_name.cached_html_name_and_author_year
    else
      nil
    end
  end

  def distribution_geoJSON
    a_ds   = Gis::GeoJSON.feature_collection(geographic_areas_from_asserted_distributions, :asserted_distributions)
    c_os   = Gis::GeoJSON.feature_collection(collecting_events, :collecting_events_georeferences)
    c_es   = Gis::GeoJSON.feature_collection(geographic_areas_from_collecting_events, :collecting_events_geographic_area)
    retval = Gis::GeoJSON.aggregation([a_ds, c_os, c_es], :distribution)
    retval
  end

  protected

  def check_required_fields
    if self.taxon_name_id.nil? && self.name.blank?
      errors.add(:taxon_name_id, 'and/or name should be selected')
      errors.add(:name, 'and/or taxon name should be selected')
    end
  end

  def sv_taxon_name
    soft_validations.add(:taxon_name_id, 'Taxon is not selected') if self.taxon_name_id.nil?
  end

  def sv_duplicate_otu
    unless Otu.with_taxon_name_id(self.taxon_name_id).with_name(self.name).not_self(self).with_project_id(self.project_id).empty?
      soft_validations.add(:taxon_name_id, 'Duplicate Taxon and Name combination')
      soft_validations.add(:name, 'Duplicate Taxon and Name combination')
    end
  end

  # def collecting_event_geoJSON
  #   Gis::GeoJSON.feature_collection(collecting_events, :collecting_events)
  # end
  #endregion
end

- (Integer) project_id

the project ID

Returns:

  • (Integer)


23
24
25
26
27
28
29
30
31
32
33
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'app/models/otu.rb', line 23

class Otu < ActiveRecord::Base

  # TODO Add simple semantics (same_as etc.) describing taxon_name_id

  include Housekeeping
  #include Shared::AlternateValues  # 1/26/15 with MJY - not going to allow alternate values in Burlap
  include Shared::Citable               # TODO: have to think hard about this vs. using Nico's framework
  include Shared::DataAttributes
  include Shared::Identifiable
  include Shared::Notable
  include Shared::Taggable
  include Shared::IsData
  include Shared::Depictions
  include Shared::Loanable
  include Shared::Confidence

  include SoftValidation

  has_paper_trail :on => [:update] 

  belongs_to :taxon_name, inverse_of: :otus

  has_many :asserted_distributions, inverse_of: :otu
  has_many :collecting_events, -> { uniq }, through: :collection_objects

  has_many :collection_objects, through: :taxon_determinations, source: :biological_collection_object, inverse_of: :otus, class_name: 'CollectionObject::BiologicalCollectionObject'
  has_many :taxon_determinations, inverse_of: :otu, dependent: :destroy

  has_many :common_names, dependent: :destroy 
  has_many :collection_profiles # @proceps dependent: what?
  has_many :contents, inverse_of: :otu, dependent: :destroy
  has_many :geographic_areas_from_asserted_distributions, through: :asserted_distributions, source: :geographic_area
  has_many :geographic_areas_from_collecting_events, through: :collecting_events, source: :geographic_area
  has_many :georeferences, through: :collecting_events

  has_many :content_topics, through: :contents, source: :topic

  scope :with_taxon_name_id, -> (taxon_name_id) { where(taxon_name_id: taxon_name_id) }
  scope :with_name, -> (name) { where(name: name) }

  # @return scope
  def self.self_and_descendants_of(otu_id)
    o = Otu.includes(:taxon_name).find(otu_id)
    if o && o.taxon_name
      with_taxon_name_id(Otu.find(otu_id).taxon_name.self_and_descendants)
    else
      Otu.where(id: otu_id)
    end
  end

  validate :check_required_fields

  soft_validate(:sv_taxon_name, set: :taxon_name)
  soft_validate(:sv_duplicate_otu, set: :duplicate_otu)

  accepts_nested_attributes_for :common_names, allow_destroy: true

  #region class methods

  # return [Scope] the otus bound to that taxon name and its descendants
  def self.for_taxon_name(taxon_name)
    if taxon_name.kind_of?(String) || taxon_name.kind_of?(Integer) 
      tn = TaxonName.find(taxon_name)
    else
      tn = taxon_name
    end
    Otu.joins(taxon_name: [:ancestor_hierarchies]).where(taxon_name_hierarchies: {ancestor_id: tn.id} )
  end

  # TODO: This need to be renamed to reflect "simple" association
  def self.batch_preview(file: nil, ** args)
    # f     = CSV.read(file, headers: true, col_sep: "\t", skip_blanks: true, header_converters: :symbol)
    @otus = []
    File.open(file).each do |row|
      name = row.strip
      next if name.blank?
      @otus.push(Otu.new(name: row.strip))
    end
    @otus
  end

  def self.batch_create(otus: {}, ** args)
    new_otus = []
    begin
      Otu.transaction do
        otus.keys.each do |k|
          o = Otu.new(otus[k])
          o.save!
          new_otus.push(o)
        end
      end
    rescue
      return false
    end
    new_otus
  end

  #endregion

  #region instance methods
  # Hernán - this is extremely hacky, I'd like to
  # map core keys to procs, use yield:, use cached values,
  # add logic for has_many handling (e.g. identifiers) etc.
  # ultmately, each key maps to a proc that returns a value
  #
  # deprecated for new approach in CollectionObject, AssertedDistribution
  def dwca_core
    core = Dwca::GbifProfile::CoreTaxon.new

    core.nomenclaturalCode        = (taxon_name.rank_class.nomenclatural_code.to_s.upcase)
    core.taxonomicStatus          = (taxon_name.unavailable_or_invalid? ? nil : 'accepted')
    core.nomenclaturalStatus      = (taxon_name.classification_invalid_or_unavailable? ? nil : 'available') # needs tweaking
    core.scientificName           = taxon_name.cached
    core.scientificNameAuthorship = taxon_name.cached_author_year
    core.scientificNameID         = taxon_name.identifiers.first.identifier
    core.taxonRank                = taxon_name.rank
    core.namePublishedIn          = taxon_name.source.cached
    core
  end

  def otu_name
    if !name.blank?
      name
    elsif !self.taxon_name_id.nil?
      self.taxon_name.cached_html_name_and_author_year
    else
      nil
    end
  end

  def distribution_geoJSON
    a_ds   = Gis::GeoJSON.feature_collection(geographic_areas_from_asserted_distributions, :asserted_distributions)
    c_os   = Gis::GeoJSON.feature_collection(collecting_events, :collecting_events_georeferences)
    c_es   = Gis::GeoJSON.feature_collection(geographic_areas_from_collecting_events, :collecting_events_geographic_area)
    retval = Gis::GeoJSON.aggregation([a_ds, c_os, c_es], :distribution)
    retval
  end

  protected

  def check_required_fields
    if self.taxon_name_id.nil? && self.name.blank?
      errors.add(:taxon_name_id, 'and/or name should be selected')
      errors.add(:name, 'and/or taxon name should be selected')
    end
  end

  def sv_taxon_name
    soft_validations.add(:taxon_name_id, 'Taxon is not selected') if self.taxon_name_id.nil?
  end

  def sv_duplicate_otu
    unless Otu.with_taxon_name_id(self.taxon_name_id).with_name(self.name).not_self(self).with_project_id(self.project_id).empty?
      soft_validations.add(:taxon_name_id, 'Duplicate Taxon and Name combination')
      soft_validations.add(:name, 'Duplicate Taxon and Name combination')
    end
  end

  # def collecting_event_geoJSON
  #   Gis::GeoJSON.feature_collection(collecting_events, :collecting_events)
  # end
  #endregion
end

- (Integer) taxon_name_id

The id of the nomenclatural name for this OTU. The presence of a nomenclatural name carries no biological meaning, it is simply a means to organize concepts within a nomenclatural system.

Returns:

  • (Integer)


23
24
25
26
27
28
29
30
31
32
33
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'app/models/otu.rb', line 23

class Otu < ActiveRecord::Base

  # TODO Add simple semantics (same_as etc.) describing taxon_name_id

  include Housekeeping
  #include Shared::AlternateValues  # 1/26/15 with MJY - not going to allow alternate values in Burlap
  include Shared::Citable               # TODO: have to think hard about this vs. using Nico's framework
  include Shared::DataAttributes
  include Shared::Identifiable
  include Shared::Notable
  include Shared::Taggable
  include Shared::IsData
  include Shared::Depictions
  include Shared::Loanable
  include Shared::Confidence

  include SoftValidation

  has_paper_trail :on => [:update] 

  belongs_to :taxon_name, inverse_of: :otus

  has_many :asserted_distributions, inverse_of: :otu
  has_many :collecting_events, -> { uniq }, through: :collection_objects

  has_many :collection_objects, through: :taxon_determinations, source: :biological_collection_object, inverse_of: :otus, class_name: 'CollectionObject::BiologicalCollectionObject'
  has_many :taxon_determinations, inverse_of: :otu, dependent: :destroy

  has_many :common_names, dependent: :destroy 
  has_many :collection_profiles # @proceps dependent: what?
  has_many :contents, inverse_of: :otu, dependent: :destroy
  has_many :geographic_areas_from_asserted_distributions, through: :asserted_distributions, source: :geographic_area
  has_many :geographic_areas_from_collecting_events, through: :collecting_events, source: :geographic_area
  has_many :georeferences, through: :collecting_events

  has_many :content_topics, through: :contents, source: :topic

  scope :with_taxon_name_id, -> (taxon_name_id) { where(taxon_name_id: taxon_name_id) }
  scope :with_name, -> (name) { where(name: name) }

  # @return scope
  def self.self_and_descendants_of(otu_id)
    o = Otu.includes(:taxon_name).find(otu_id)
    if o && o.taxon_name
      with_taxon_name_id(Otu.find(otu_id).taxon_name.self_and_descendants)
    else
      Otu.where(id: otu_id)
    end
  end

  validate :check_required_fields

  soft_validate(:sv_taxon_name, set: :taxon_name)
  soft_validate(:sv_duplicate_otu, set: :duplicate_otu)

  accepts_nested_attributes_for :common_names, allow_destroy: true

  #region class methods

  # return [Scope] the otus bound to that taxon name and its descendants
  def self.for_taxon_name(taxon_name)
    if taxon_name.kind_of?(String) || taxon_name.kind_of?(Integer) 
      tn = TaxonName.find(taxon_name)
    else
      tn = taxon_name
    end
    Otu.joins(taxon_name: [:ancestor_hierarchies]).where(taxon_name_hierarchies: {ancestor_id: tn.id} )
  end

  # TODO: This need to be renamed to reflect "simple" association
  def self.batch_preview(file: nil, ** args)
    # f     = CSV.read(file, headers: true, col_sep: "\t", skip_blanks: true, header_converters: :symbol)
    @otus = []
    File.open(file).each do |row|
      name = row.strip
      next if name.blank?
      @otus.push(Otu.new(name: row.strip))
    end
    @otus
  end

  def self.batch_create(otus: {}, ** args)
    new_otus = []
    begin
      Otu.transaction do
        otus.keys.each do |k|
          o = Otu.new(otus[k])
          o.save!
          new_otus.push(o)
        end
      end
    rescue
      return false
    end
    new_otus
  end

  #endregion

  #region instance methods
  # Hernán - this is extremely hacky, I'd like to
  # map core keys to procs, use yield:, use cached values,
  # add logic for has_many handling (e.g. identifiers) etc.
  # ultmately, each key maps to a proc that returns a value
  #
  # deprecated for new approach in CollectionObject, AssertedDistribution
  def dwca_core
    core = Dwca::GbifProfile::CoreTaxon.new

    core.nomenclaturalCode        = (taxon_name.rank_class.nomenclatural_code.to_s.upcase)
    core.taxonomicStatus          = (taxon_name.unavailable_or_invalid? ? nil : 'accepted')
    core.nomenclaturalStatus      = (taxon_name.classification_invalid_or_unavailable? ? nil : 'available') # needs tweaking
    core.scientificName           = taxon_name.cached
    core.scientificNameAuthorship = taxon_name.cached_author_year
    core.scientificNameID         = taxon_name.identifiers.first.identifier
    core.taxonRank                = taxon_name.rank
    core.namePublishedIn          = taxon_name.source.cached
    core
  end

  def otu_name
    if !name.blank?
      name
    elsif !self.taxon_name_id.nil?
      self.taxon_name.cached_html_name_and_author_year
    else
      nil
    end
  end

  def distribution_geoJSON
    a_ds   = Gis::GeoJSON.feature_collection(geographic_areas_from_asserted_distributions, :asserted_distributions)
    c_os   = Gis::GeoJSON.feature_collection(collecting_events, :collecting_events_georeferences)
    c_es   = Gis::GeoJSON.feature_collection(geographic_areas_from_collecting_events, :collecting_events_geographic_area)
    retval = Gis::GeoJSON.aggregation([a_ds, c_os, c_es], :distribution)
    retval
  end

  protected

  def check_required_fields
    if self.taxon_name_id.nil? && self.name.blank?
      errors.add(:taxon_name_id, 'and/or name should be selected')
      errors.add(:name, 'and/or taxon name should be selected')
    end
  end

  def sv_taxon_name
    soft_validations.add(:taxon_name_id, 'Taxon is not selected') if self.taxon_name_id.nil?
  end

  def sv_duplicate_otu
    unless Otu.with_taxon_name_id(self.taxon_name_id).with_name(self.name).not_self(self).with_project_id(self.project_id).empty?
      soft_validations.add(:taxon_name_id, 'Duplicate Taxon and Name combination')
      soft_validations.add(:name, 'Duplicate Taxon and Name combination')
    end
  end

  # def collecting_event_geoJSON
  #   Gis::GeoJSON.feature_collection(collecting_events, :collecting_events)
  # end
  #endregion
end

Class Method Details

+ (Object) batch_create(otus: {}, **args)



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'app/models/otu.rb', line 104

def self.batch_create(otus: {}, ** args)
  new_otus = []
  begin
    Otu.transaction do
      otus.keys.each do |k|
        o = Otu.new(otus[k])
        o.save!
        new_otus.push(o)
      end
    end
  rescue
    return false
  end
  new_otus
end

+ (Object) batch_preview(file: nil, **args)

TODO: This need to be renamed to reflect “simple” association



93
94
95
96
97
98
99
100
101
102
# File 'app/models/otu.rb', line 93

def self.batch_preview(file: nil, ** args)
  # f     = CSV.read(file, headers: true, col_sep: "\t", skip_blanks: true, header_converters: :symbol)
  @otus = []
  File.open(file).each do |row|
    name = row.strip
    next if name.blank?
    @otus.push(Otu.new(name: row.strip))
  end
  @otus
end

+ (Object) for_taxon_name(taxon_name)

return [Scope] the otus bound to that taxon name and its descendants



83
84
85
86
87
88
89
90
# File 'app/models/otu.rb', line 83

def self.for_taxon_name(taxon_name)
  if taxon_name.kind_of?(String) || taxon_name.kind_of?(Integer) 
    tn = TaxonName.find(taxon_name)
  else
    tn = taxon_name
  end
  Otu.joins(taxon_name: [:ancestor_hierarchies]).where(taxon_name_hierarchies: {ancestor_id: tn.id} )
end

+ (Object) self_and_descendants_of(otu_id)

Returns scope

Returns:

  • scope



64
65
66
67
68
69
70
71
# File 'app/models/otu.rb', line 64

def self.self_and_descendants_of(otu_id)
  o = Otu.includes(:taxon_name).find(otu_id)
  if o && o.taxon_name
    with_taxon_name_id(Otu.find(otu_id).taxon_name.self_and_descendants)
  else
    Otu.where(id: otu_id)
  end
end

Instance Method Details

- (Object) check_required_fields (protected)



163
164
165
166
167
168
# File 'app/models/otu.rb', line 163

def check_required_fields
  if self.taxon_name_id.nil? && self.name.blank?
    errors.add(:taxon_name_id, 'and/or name should be selected')
    errors.add(:name, 'and/or taxon name should be selected')
  end
end

- (Object) distribution_geoJSON



153
154
155
156
157
158
159
# File 'app/models/otu.rb', line 153

def distribution_geoJSON
  a_ds   = Gis::GeoJSON.feature_collection(geographic_areas_from_asserted_distributions, :asserted_distributions)
  c_os   = Gis::GeoJSON.feature_collection(collecting_events, :collecting_events_georeferences)
  c_es   = Gis::GeoJSON.feature_collection(geographic_areas_from_collecting_events, :collecting_events_geographic_area)
  retval = Gis::GeoJSON.aggregation([a_ds, c_os, c_es], :distribution)
  retval
end

- (Object) dwca_core

region instance methods Hernán - this is extremely hacky, I'd like to map core keys to procs, use yield:, use cached values, add logic for has_many handling (e.g. identifiers) etc. ultmately, each key maps to a proc that returns a value

deprecated for new approach in CollectionObject, AssertedDistribution



129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'app/models/otu.rb', line 129

def dwca_core
  core = Dwca::GbifProfile::CoreTaxon.new

  core.nomenclaturalCode        = (taxon_name.rank_class.nomenclatural_code.to_s.upcase)
  core.taxonomicStatus          = (taxon_name.unavailable_or_invalid? ? nil : 'accepted')
  core.nomenclaturalStatus      = (taxon_name.classification_invalid_or_unavailable? ? nil : 'available') # needs tweaking
  core.scientificName           = taxon_name.cached
  core.scientificNameAuthorship = taxon_name.cached_author_year
  core.scientificNameID         = taxon_name.identifiers.first.identifier
  core.taxonRank                = taxon_name.rank
  core.namePublishedIn          = taxon_name.source.cached
  core
end

- (Object) otu_name



143
144
145
146
147
148
149
150
151
# File 'app/models/otu.rb', line 143

def otu_name
  if !name.blank?
    name
  elsif !self.taxon_name_id.nil?
    self.taxon_name.cached_html_name_and_author_year
  else
    nil
  end
end

- (Object) sv_duplicate_otu (protected)



174
175
176
177
178
179
# File 'app/models/otu.rb', line 174

def sv_duplicate_otu
  unless Otu.with_taxon_name_id(self.taxon_name_id).with_name(self.name).not_self(self).with_project_id(self.project_id).empty?
    soft_validations.add(:taxon_name_id, 'Duplicate Taxon and Name combination')
    soft_validations.add(:name, 'Duplicate Taxon and Name combination')
  end
end

- (Object) sv_taxon_name (protected)



170
171
172
# File 'app/models/otu.rb', line 170

def sv_taxon_name
  soft_validations.add(:taxon_name_id, 'Taxon is not selected') if self.taxon_name_id.nil?
end