Class: InaturalistImportJob
- Inherits:
-
ApplicationJob
- Object
- ActiveJob::Base
- ApplicationJob
- InaturalistImportJob
- Defined in:
- app/jobs/inaturalist_import_job.rb
Instance Method Summary collapse
- #import_observation(result, project_id:, match_otu_by_name:, use_community_taxon:, import_images:, import_sounds:) ⇒ Object private
- #import_photos(result, fo:) ⇒ Object private
-
#import_sounds(result, fo:) ⇒ Object
private
For each CC/PD-licensed sound on the observation, create a Sound with full licensing metadata and attach it as a Conveyance on the FO.
-
#observer_person(result) ⇒ Object
private
The observation's observer as a saved Person, deduplicated across the run.
- #perform(results:, project_id:, user_id:, match_otu_by_name: false, use_community_taxon: true, import_images: false, import_sounds: false, taxon_determination: nil) ⇒ Object
Instance Method Details
#import_observation(result, project_id:, match_otu_by_name:, use_community_taxon:, import_images:, import_sounds:) ⇒ Object (private)
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 |
# File 'app/jobs/inaturalist_import_job.rb', line 42 def import_observation(result, project_id:, match_otu_by_name:, use_community_taxon:, import_images:, import_sounds:) ApplicationRecord.transaction do # Save the OTU first so otu.id is available for the TaxonDetermination nested # attributes — reject_taxon_determinations rejects entries with a blank otu_id # and a blank otu.id, which is the case for any new (unsaved) OTU object. taxon_determination_attributes = if @taxon_determination @taxon_determination else otu = ::Vendor::Nasturtium.stub_otu( result, project_id:, match_by_name: match_otu_by_name, use_community_taxon: ) unless otu Rails.logger.warn( "InaturalistImportJob: skipping observation #{result['id']} " \ '— no taxon name' ) return end otu.save! if otu.new_record? d = result['observed_on_details'] { otu_id: otu.id, year_made: d['year'], month_made: d['month'], day_made: d['day'], } end # Save the CE (and its nested georeference) before the FO so that # collecting_event_id is set when the FO is created. ce = ::Vendor::Nasturtium.stub_collecting_event(result, person_cache: @person_cache) ce.save! if (georef = ce.georeferences.first) georef.georeferencer_roles.create!(person: observer_person(result)) end fo = FieldOccurrence.new( total: 1, collecting_event: ce, taxon_determinations_attributes: [taxon_determination_attributes], identifiers: [::Vendor::Nasturtium.stub_identifier(result)].compact, ) fo.save! ::Vendor::Nasturtium.stub_biocuration_classes(result, project_id:).each do |biocuration_class| BiocurationClassification.create!(biocuration_class:, biocuration_classification_object: fo) end # The observer's iNat identification isn't the determination when one # was given for all results. if !use_community_taxon && @taxon_determination.nil? td = fo.taxon_determinations.first td.determiner_roles.create!(person: observer_person(result)) if (ident_uuid = ::Vendor::Nasturtium.observer_identification_uuid(result)) Identifier::Global::Uuid::InaturalistIdentification.create!( identifier_object: td, identifier: ident_uuid ) end end if result['description'].present? Note.create!(note_object: fo, text: result['description']) end import_photos(result, fo:) if import_images import_sounds(result, fo:) if import_sounds end rescue => e # Failures are logged but do not interrupt the remaining imports Rails.logger.error( "InaturalistImportJob: failed to import observation #{result['id']}: " \ "#{e.class}: #{e.}\n#{e.backtrace&.first(5)&.join("\n")}" ) end |
#import_photos(result, fo:) ⇒ Object (private)
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'app/jobs/inaturalist_import_job.rb', line 142 def import_photos(result, fo:) observed_year = result.dig('observed_on_details', 'year') ::Vendor::Nasturtium.permitted_photos(result).each do |obs_photo| ApplicationRecord.transaction do image = ::Vendor::Nasturtium.build_image!(obs_photo, result:, observed_year:, person_cache: @person_cache) Depiction.create!(image:, depiction_object: fo) end rescue => e Rails.logger.error( "InaturalistImportJob: failed to import photo #{obs_photo['uuid']} " \ "for observation #{result['uuid']}: #{e.class}: #{e.}\n" \ "#{e.backtrace&.first(5)&.join("\n")}" ) end end |
#import_sounds(result, fo:) ⇒ Object (private)
For each CC/PD-licensed sound on the observation, create a Sound with full licensing metadata and attach it as a Conveyance on the FO.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'app/jobs/inaturalist_import_job.rb', line 125 def import_sounds(result, fo:) observed_year = result.dig('observed_on_details', 'year') ::Vendor::Nasturtium.permitted_sounds(result).each do |obs_sound| ApplicationRecord.transaction do sound = ::Vendor::Nasturtium.build_sound!(obs_sound, result:, observed_year:, person_cache: @person_cache) Conveyance.create!(sound:, conveyance_object: fo) end rescue => e Rails.logger.error( "InaturalistImportJob: failed to import sound #{obs_sound['uuid']} " \ "for observation #{result['uuid']}: #{e.class}: #{e.}\n" \ "#{e.backtrace&.first(5)&.join("\n")}" ) end end |
#observer_person(result) ⇒ Object (private)
The observation's observer as a saved Person, deduplicated across the run.
36 37 38 39 40 |
# File 'app/jobs/inaturalist_import_job.rb', line 36 def observer_person(result) person = ::Vendor::Nasturtium.stub_observer_person(result, person_cache: @person_cache) person.save! if person.new_record? person end |
#perform(results:, project_id:, user_id:, match_otu_by_name: false, use_community_taxon: true, import_images: false, import_sounds: false, taxon_determination: nil) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'app/jobs/inaturalist_import_job.rb', line 14 def perform( results:, project_id:, user_id:, match_otu_by_name: false, use_community_taxon: true, import_images: false, import_sounds: false, taxon_determination: nil ) Current.project_id = project_id Current.user_id = user_id @taxon_determination = taxon_determination # Reuse one Person across this run for an observer/copyright holder/etc. # that would otherwise be built repeatedly. @person_cache = {} results.each do |result| import_observation(result, project_id:, match_otu_by_name:, use_community_taxon:, import_images:, import_sounds:) end end |