Module: Shared::Dwc::CollectingEventExtensions

Extended by:
ActiveSupport::Concern
Included in:
CollectionObject::DwcExtensions, FieldOccurrence::DwcExtensions
Defined in:
app/models/concerns/shared/dwc/collecting_event_extensions.rb

Overview

Shared code for data classes that can be indexed/serialized as DwcOccurrence records

Instance Method Summary collapse

Instance Method Details

#dwc_coordinate_uncertainty_in_metersObject

TODO: extend to Georeferences when we understand how to describe spatial uncertainty



92
93
94
95
96
97
98
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 92

def dwc_coordinate_uncertainty_in_meters
  if georeference_attributes[:coordinateUncertaintyInMeters]
    georeference_attributes[:coordinateUncertaintyInMeters]
  else
    collecting_event&.verbatim_geolocation_uncertainty
  end
end

#dwc_countryObject



218
219
220
221
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 218

def dwc_country
  v = try(:collecting_event).try(:geographic_names)
  v[:country] if v
end

#dwc_countyObject



228
229
230
231
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 228

def dwc_county
  v = try(:collecting_event).try(:geographic_names)
  v[:county] if v
end

#dwc_dayObject



291
292
293
294
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 291

def dwc_day
  return unless collecting_event
  collecting_event.start_date_day.presence
end

#dwc_decimal_latitudeObject



237
238
239
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 237

def dwc_decimal_latitude
  georeference_attributes[:decimalLatitude]
end

#dwc_decimal_longitudeObject



241
242
243
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 241

def dwc_decimal_longitude
  georeference_attributes[:decimalLongitude]
end

#dwc_end_day_of_yearObject



301
302
303
304
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 301

def dwc_end_day_of_year
  return unless collecting_event
  collecting_event.end_day_of_year.presence
end

#dwc_event_dateObject



266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 266

def dwc_event_date
  return unless collecting_event
  return if collecting_event.start_date_year.blank? # don't need to check end, it requires start in model

  %w{start_date end_date}
    .map { |d| %w{year month day}
    .map { |p| collecting_event["#{d}_#{p}"] }
    .map { |p| '%02d' % p if p } # At least two digits
    }
      .map { |d| d.compact.join('-') }
      .reject(&:blank?)
      .join('/').presence
end

#dwc_event_idObject



114
115
116
117
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 114

def dwc_event_id
  return nil unless collecting_event
  collecting_event.identifiers.where(type: 'Identifier::Local::Event').first&.cached.presence
end

#dwc_event_remarksObject



59
60
61
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 59

def dwc_event_remarks
  collecting_event&.notes&.collect {|n| n.text}&.join(Export::Dwca::DELIMITER).presence
end

#dwc_event_timeObject



249
250
251
252
253
254
255
256
257
258
259
260
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 249

def dwc_event_time
  return unless collecting_event

  %w{start_time end_time}
    .map { |t| %w{hour minute second}
    .map { |p| collecting_event["#{t}_#{p}"] }
    .map { |p| '%02d' % p if p } # At least two digits
    }
      .map { |t| t.compact.join(':') }
      .reject(&:blank?)
      .join('/').presence
end

#dwc_field_numberObject

Prioritize the formalized version of the identifier for data-sharing purposes



109
110
111
112
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 109

def dwc_field_number
  return nil unless collecting_event
  collecting_event.identifiers.where(type: 'Identifier::Local::FieldNumber').first&.cached || collecting_event&.verbatim_field_number
end

#dwc_footprint_wktObject



71
72
73
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 71

def dwc_footprint_wkt
  georeference_attributes[:footprintWKT]
end

#dwc_geodetic_datumObject



83
84
85
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 83

def dwc_geodetic_datum
  georeference_attributes[:geodeticDatum]
end

#dwc_georeference_protocolObject



306
307
308
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 306

def dwc_georeference_protocol
  georeference_attributes[:georeferenceProtocol]
end

#dwc_georeference_remarksObject



67
68
69
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 67

def dwc_georeference_remarks
  georeference_attributes[:georeferenceRemarks]
end

#dwc_georeference_sourcesObject



63
64
65
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 63

def dwc_georeference_sources
  georeference_attributes[:georeferenceSources]
end

#dwc_georeferenced_byObject



75
76
77
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 75

def dwc_georeferenced_by
  georeference_attributes[:georeferencedBy]
end

#dwc_georeferenced_dateObject



79
80
81
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 79

def dwc_georeferenced_date
  georeference_attributes[:georeferencedDate]
end

#dwc_habitatObject

Prioritize the curated AssertedEnvironments (ENVO terms) over the free-text verbatim_habitat, falling back to the latter when none have been asserted.



180
181
182
183
184
185
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 180

def dwc_habitat
  return nil unless collecting_event

  collecting_event.asserted_environments.order(:position).pluck(:uri_label)
    .join(Export::Dwca::DELIMITER).presence || collecting_event.verbatim_habitat
end

#dwc_internal_attribute_for(target = :collection_object, dwc_term_name) ⇒ Object

TODO: hmm...



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 120

def dwc_internal_attribute_for(target = :collection_object, dwc_term_name)
  return nil if dwc_term_name.nil?

  case target
  when  :collecting_event
    return nil unless collecting_event
    collecting_event.internal_attributes.includes(:predicate)
      .where(
        controlled_vocabulary_terms: {uri: ::DWC_ATTRIBUTE_URIS[dwc_term_name.to_sym] })
      .pluck(:value)&.join(', ').presence
  when :collection_object
    internal_attributes.includes(:predicate)
      .where(
        controlled_vocabulary_terms: {uri: ::DWC_ATTRIBUTE_URIS[dwc_term_name.to_sym] })
      .pluck(:value)&.join(', ').presence
  else
    nil
  end
end

#dwc_localityObject



233
234
235
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 233

def dwc_locality
  collecting_event.try(:verbatim_locality)
end

#dwc_maximum_depth_in_metersObject



148
149
150
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 148

def dwc_maximum_depth_in_meters
  dwc_internal_attribute_for(:collecting_event, :maximumDepthInMeters)
end

#dwc_maximum_elevation_in_metersObject



165
166
167
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 165

def dwc_maximum_elevation_in_meters
  collecting_event&.maximum_elevation
end

#dwc_minimum_depth_in_metersObject



144
145
146
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 144

def dwc_minimum_depth_in_meters
  dwc_internal_attribute_for(:collecting_event, :minimumDepthInMeters)
end

#dwc_minimum_elevation_in_metersObject



169
170
171
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 169

def dwc_minimum_elevation_in_meters
  collecting_event&.minimum_elevation
end

#dwc_monthObject



285
286
287
288
289
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 285

def dwc_month
  return unless collecting_event
  return if collecting_event.start_date_month.present? && collecting_event.end_date_month.present?
  collecting_event.start_date_month.presence
end

#dwc_recorded_byObject

Definition: A list (concatenated and separated) of names of people, groups, or organizations responsible for recording the original Occurrence. The primary collector or observer, especially one who applies a personal identifier (recordNumber), should be listed first.

This was interpreted as collectors (in the field in this context), not those who recorded other aspects of the data.



205
206
207
208
209
210
211
212
213
214
215
216
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 205

def dwc_recorded_by
  v = nil
  if collecting_event
    v = collecting_event.collectors
      .order('roles.position')
      .map(&:name)
      .join(Export::Dwca::DELIMITER)
      .presence
    v = collecting_event.verbatim_collectors.presence if v.blank?
  end
  v
end

#dwc_recorded_by_idObject

See dwc_recorded_by TODO: Expand to any GlobalIdentifier



189
190
191
192
193
194
195
196
197
198
199
200
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 189

def dwc_recorded_by_id
  if collecting_event
    collecting_event.collectors
      .joins(:identifiers)
      .where(identifiers: {type: ['Identifier::Global::Orcid', 'Identifier::Global::Wikidata']})
      .select('identifiers.identifier_object_id, identifiers.cached')
      .unscope(:order)
      .distinct
      .pluck('identifiers.cached')
      .join(Export::Dwca::DELIMITER)&.presence
  end
end

#dwc_sampling_protocolObject

TODO: Reconcile with Protocol (capital P) assignments



174
175
176
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 174

def dwc_sampling_protocol
  collecting_event&.verbatim_method
end

#dwc_start_day_of_yearObject



296
297
298
299
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 296

def dwc_start_day_of_year
  return unless collecting_event
  collecting_event.start_day_of_year.presence
end

#dwc_state_provinceObject



223
224
225
226
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 223

def dwc_state_province
  v = try(:collecting_event).try(:geographic_names)
  v[:state] if v
end

#dwc_verbatim_coordinatesObject



156
157
158
159
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 156

def dwc_verbatim_coordinates
  return nil unless collecting_event
  [collecting_event.verbatim_latitude, collecting_event.verbatim_longitude].compact.join(' ').presence
end

#dwc_verbatim_depthObject



152
153
154
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 152

def dwc_verbatim_depth
  dwc_internal_attribute_for(:collecting_event, :verbatimDepth)
end

#dwc_verbatim_elevationObject



161
162
163
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 161

def dwc_verbatim_elevation
  collecting_event&.verbatim_elevation
end

#dwc_verbatim_event_dateObject



262
263
264
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 262

def dwc_verbatim_event_date
  collecting_event&.verbatim_date
end

#dwc_verbatim_latitudeObject



100
101
102
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 100

def dwc_verbatim_latitude
  collecting_event&.verbatim_latitude
end

#dwc_verbatim_localityObject



245
246
247
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 245

def dwc_verbatim_locality
  collecting_event.try(:verbatim_locality)
end

#dwc_verbatim_longitudeObject



104
105
106
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 104

def dwc_verbatim_longitude
  collecting_event&.verbatim_longitude
end

#dwc_verbatim_srsObject



87
88
89
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 87

def dwc_verbatim_srs
  georeference_attributes[:dwcVerbatimSrs]
end

#dwc_water_bodyObject



140
141
142
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 140

def dwc_water_body
  dwc_internal_attribute_for(:collecting_event, :waterBody)
end

#dwc_yearObject



280
281
282
283
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 280

def dwc_year
  return unless collecting_event
  collecting_event.start_date_year.presence
end

#set_georeference_attributesHash

TODO: Revisit

Returns:

  • (Hash)


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
# File 'app/models/concerns/shared/dwc/collecting_event_extensions.rb', line 24

def set_georeference_attributes
  case collecting_event&.dwc_georeference_source
  when :georeference
    collecting_event.preferred_georeference.dwc_georeference_attributes
  when :verbatim
    h = collecting_event.dwc_georeference_attributes

    # Our interpretation is now that georeferencedBy is the person who "computed" the
    # values, not transcribed the values.
    #
    #     if a = collecting_event&.attribute_updater(:verbatim_latitude)
    #       h[:georeferencedBy] = User.find(a).name
    #     end

    # verbatim_longitude could technically be different, but...
    h[:georeferencedDate] = (collecting_event.attribute_updated(:verbatim_latitude) if collecting_event.verbatim_latitude)

    h

  when :geographic_area
    h = collecting_event.geographic_area.dwc_georeference_attributes

    if collecting_event.geographic_area_id && (a = collecting_event.attribute_updater(:geographic_area_id))
      h[:georeferencedBy] = User.find_by(id: a)&.name # User might have been deleted if coming from PaperTrail versioning
    end

    h[:georeferencedDate] = (collecting_event.attribute_updated(:geographic_area_id) if collecting_event.geographic_area_id)

    h
  else
    {}
  end
end