Class: Observation
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Observation
- Includes:
- Housekeeping, Shared::Citations, Shared::Confidences, Shared::DataAttributes, Shared::Depictions, Shared::Identifiers, Shared::IsData, Shared::Notes, Shared::ObservationIndex, Shared::ProtocolRelationships, Shared::Tags
- Defined in:
- app/models/observation.rb
Overview
Records Qualitative, Quantitative, Statistical, free-text (Working), Media and other types of “measurements” gathered from our observations. Where we record the data behind concepts like traits, phenotypes, measurements, character matrices, and descriptive matrices.
Subclasses of Observation define the applicable attributes for its type. Type is echoed 1:1 in each corresponding Descriptor, for convenience and validation purposes.
Subclass specific attributes
Observation::Qualitative attributes
Observation::Quantiative attributes
Observation::Working
Observation::??
Observation::PresenceAbsence
Observation::Sample !! Should only apply to OTUs technically, as this is an aggregation of measurements seen in a typical statistical summary
Direct Known Subclasses
Continuous, Media, PresenceAbsence, Qualitative, Sample, Working
Defined Under Namespace
Classes: Continuous, Media, PresenceAbsence, Qualitative, Sample, Working
Instance Attribute Summary collapse
-
#cached ⇒ string
!! Not used.
-
#cached_column_label ⇒ string
!! Not used.
-
#cached_row_label ⇒ string
!! Not used.
-
#character_state_id ⇒ Integer
The corresponding CharacterState id for “traditional” Qualitative “characters”.
-
#continuous_unit ⇒ String
A controlled vocabulary from Ruby::Units, like ‘m“.
-
#continuous_value ⇒ String
The value of a quantitative measurement.
-
#day_made ⇒ Integer
2 digit day the observation originated.
-
#descriptions ⇒ String
Free text description of an Observation.
-
#descriptor_id ⇒ Descriptor#id
The type of observation according to it’s Descriptor.
-
#frequency ⇒ Descriptor#id
?! Candidate or removal ?!.
-
#month_made ⇒ Integer
2 digit month the observation originated.
-
#observation_object_global_id ⇒ String
TODO: this is not memoized correctly ?!.
-
#observation_object_id ⇒ Object#id
The id of the observed object.
-
#observation_object_type ⇒ Object#class.name
The type of the observed object.
- #presence ⇒ Boolean
-
#project_id ⇒ Integer
the project ID.
-
#sample_max ⇒ Boolean
Statistical max.
-
#sample_mean ⇒ Boolean
Statistical mean.
-
#sample_median ⇒ Boolean
Statistical median.
-
#sample_min ⇒ Boolean
Statistical median.
-
#sample_n ⇒ Boolean
Statistical n.
-
#sample_standard_deviation ⇒ Boolean
Statistical standard deviation.
-
#sample_standard_error ⇒ Boolean
Statistical standard error.
-
#sample_standard_units ⇒ Boolean
A controlled vocabulary from Ruby::Units, like ‘m’ (meters).
-
#time_made ⇒ Integer
Time without time zone.
-
#type ⇒ String
The type of observation.
-
#year_made ⇒ Integer
4 digit year the observation originated (not when it was recorded in TaxonWorks, though these might be the close to the same).
Class Method Summary collapse
- .by_matrix_and_position(observation_matrix_id, options = {}) ⇒ Object
- .by_observation_matrix_row(observation_matrix_row_id) ⇒ Object
-
.code_column(observation_matrix_column_id, observation_params) ⇒ Hash
{ created: 1, failed: 2 }.
- .copy(old_global_id, new_global_id) ⇒ Boolean
-
.destroy_column(observation_matrix_column_id) ⇒ Object
Destroy observations for the set of descriptors in a given column.
-
.destroy_row(observation_matrix_row_id) ⇒ Object
Destroy all observations for the set of descriptors in a given row.
- .human_name ⇒ Object
- .in_observation_matrix(observation_matrix_id) ⇒ Object
-
.object_scope(object) ⇒ Object
TODO: deprecate or remove.
Instance Method Summary collapse
- #continuous? ⇒ Boolean
- #presence_absence? ⇒ Boolean
-
#qualitative? ⇒ Boolean
depends on timeliness 6.0, which is breaking something validates_time :time_made, allow_nil: true.
- #type_matches_descriptor ⇒ Object protected
Methods included from Shared::IsData
#errors_excepting, #full_error_messages_excepting, #identical, #is_community?, #is_destroyable?, #is_editable?, #is_in_use?, #is_in_users_projects?, #metamorphosize, #similar
Methods included from Shared::ProtocolRelationships
#protocolled?, #reject_protocols
Methods included from Shared::Confidences
Methods included from Shared::Depictions
#has_depictions?, #image_array=, #reject_depictions, #reject_images
Methods included from Shared::Tags
#reject_tags, #tag_with, #tagged?, #tagged_with?
Methods included from Shared::Notes
#concatenated_notes_string, #reject_notes
Methods included from Shared::Identifiers
#dwc_occurrence_id, #identified?, #next_by_identifier, #previous_by_identifier, #reject_identifiers, #uri, #uuid
Methods included from Shared::DataAttributes
#import_attributes, #internal_attributes, #keyword_value_hash, #reject_data_attributes
Methods included from Shared::Citations
#cited?, #mark_citations_for_destruction, #nomenclature_date, #origin_citation_source_id, #reject_citations, #requires_citation?, #sources_by_topic_id
Methods included from Housekeeping
#has_polymorphic_relationship?
Methods inherited from ApplicationRecord
Instance Attribute Details
#cached ⇒ string
Returns !! Not used. Perhaps records a human readable short description ultimately.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#cached_column_label ⇒ string
Returns !! Not used. Candidate for removal.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#cached_row_label ⇒ string
Returns !! Not used. Candidate for removal.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#character_state_id ⇒ Integer
Returns The corresponding CharacterState id for “traditional” Qualitative “characters”.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#continuous_unit ⇒ String
Returns A controlled vocabulary from Ruby::Units, like ‘m“. The unit of the quantitative measurement.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#continuous_value ⇒ String
Returns The value of a quantitative measurement.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#day_made ⇒ Integer
Returns 2 digit day the observation originated.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#descriptions ⇒ String
Returns Free text description of an Observation.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#descriptor_id ⇒ Descriptor#id
Returns The type of observation according to it’s Descriptor. See also ‘type`.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#frequency ⇒ Descriptor#id
Returns ?! Candidate or removal ?!.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#month_made ⇒ Integer
Returns 2 digit month the observation originated.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#observation_object_global_id ⇒ String
TODO: this is not memoized correctly ?!
145 146 147 |
# File 'app/models/observation.rb', line 145 def observation_object_global_id @observation_object_global_id end |
#observation_object_id ⇒ Object#id
Returns The id of the observed object.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#observation_object_type ⇒ Object#class.name
Returns The type of the observed object.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#presence ⇒ Boolean
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#project_id ⇒ Integer
the project ID
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#sample_max ⇒ Boolean
Returns statistical max.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#sample_mean ⇒ Boolean
Returns statistical mean.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#sample_median ⇒ Boolean
Returns statistical median.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#sample_min ⇒ Boolean
Returns statistical median.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#sample_n ⇒ Boolean
Returns statistical n.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#sample_standard_deviation ⇒ Boolean
Returns statistical standard deviation.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#sample_standard_error ⇒ Boolean
Returns statistical standard error.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#sample_standard_units ⇒ Boolean
Returns A controlled vocabulary from Ruby::Units, like ‘m’ (meters). The unit of the sample observation.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#time_made ⇒ Integer
Returns time without time zone.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#type ⇒ String
Returns The type of observation. Defines the attribute set that is applicable to it.
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
#year_made ⇒ Integer
Returns 4 digit year the observation originated (not when it was recorded in TaxonWorks, though these might be the close to the same).
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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'app/models/observation.rb', line 127 class Observation < ApplicationRecord include Housekeeping include Shared::Citations include Shared::DataAttributes include Shared::Identifiers include Shared::Notes include Shared::Tags include Shared::Depictions include Shared::Confidences include Shared::ProtocolRelationships include Shared::IsData include Shared::ObservationIndex ignore_whitespace_on(:description) self.skip_time_zone_conversion_for_attributes = [:time_made] # String, not GlobalId attr_accessor :observation_object_global_id belongs_to :character_state, inverse_of: :observations belongs_to :descriptor, inverse_of: :observations belongs_to :observation_object, polymorphic: true # before_validation :convert_observation_object_global_id validates_presence_of :descriptor_id # should be :descriptor validates_presence_of :type # not required, it's STI validates_presence_of :observation_object validate :type_matches_descriptor validates :year_made, date_year: { min_year: 1757, max_year: -> {Time.now.year} } validates :month_made, date_month: true validates :day_made, date_day: {year_sym: :year_made, month_sym: :month_made}, unless: -> {year_made.nil? || month_made.nil?} # depends on timeliness 6.0, which is breaking something # validates_time :time_made, allow_nil: true def qualitative? type == 'Observation::Qualitative' end def presence_absence? type == 'Observation::PresenceAbsence' end def continuous? type == 'Observation::Continuous' end def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end # TODO: deprecate or remove def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end def self.human_name 'YAY' end def observation_object_global_id=(value) self.observation_object = GlobalID::Locator.locate(value) @observation_object_global_id = value end # @return [String] # TODO: this is not memoized correctly ?! def observation_object_global_id if observation_object observation_object.to_global_id.to_s else @observation_object_global_id end end # @return [Boolean] # @params old_global_id [String] # global_id of collection object or Otu # # @params new_global_id [String] # global_id of collection object or Otu # def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end # Destroy all observations for the set of descriptors in a given row def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end # Destroy observations for the set of descriptors in a given column def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end # @return [Hash] # { created: 1, failed: 2 } def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end protected def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end end |
Class Method Details
.by_matrix_and_position(observation_matrix_id, options = {}) ⇒ Object
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'app/models/observation.rb', line 184 def self.by_matrix_and_position(observation_matrix_id, = {}) opts = { row_start: 1, row_end: 'all', col_start: 1, col_end: 'all' }.merge!(.symbolize_keys) return in_observation_matrix(observation_matrix_id).order('omc.position, omr.position') if opts[:row_start] == 1 && opts[:row_end] == 'all' && opts[:col_start] == 1 && opts[:col_end] == 'all' base = Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id = ? AND omc.observation_matrix_id = ?', observation_matrix_id, observation_matrix_id) # row scope base = base.where('omr.position >= ?', opts[:row_start]) base = base.where('omr.position <= ?', opts[:row_end]) if !(opts[:row_end] == 'all') # col scope base = base.where('omc.position >= ?', opts[:col_start]) base = base.where('omc.position <= ?', opts[:col_end]) if !(opts[:col_end] == 'all') base end |
.by_observation_matrix_row(observation_matrix_row_id) ⇒ Object
209 210 211 212 213 214 |
# File 'app/models/observation.rb', line 209 def self.by_observation_matrix_row(observation_matrix_row_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.id = ?', observation_matrix_row_id) .order('omc.position') end |
.code_column(observation_matrix_column_id, observation_params) ⇒ Hash
Returns { created: 1, failed: 2 }.
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'app/models/observation.rb', line 300 def self.code_column(observation_matrix_column_id, observation_params) c = ObservationMatrixColumn.find(observation_matrix_column_id) o = ObservationMatrix.find(c.observation_matrix_id) descriptor = c.descriptor # Type is required on the onset p = observation_params.merge( type: descriptor.observation_type ) h = Hash.new(0) Observation.transaction do o.observation_matrix_rows.each do |r| begin if !Observation.where(observation_object: r.observation_object, descriptor: descriptor).any? Observation.create!( p.merge( observation_object: r.observation_object, descriptor: descriptor, ) ) h[:passed] += 1 else h[:exists] += 1 end rescue ActiveRecord::RecordInvalid h[:failed] += 1 end end end h end |
.copy(old_global_id, new_global_id) ⇒ Boolean
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'app/models/observation.rb', line 248 def self.copy(old_global_id, new_global_id) begin old = GlobalID::Locator.locate(old_global_id) Observation.transaction do old.observations.each do |o| d = o.dup d.update(observation_object_global_id: new_global_id) # Copy depictions o.depictions.each do |i| j = i.dup j.update(depiction_object: d) end end end true rescue return false end true end |
.destroy_column(observation_matrix_column_id) ⇒ Object
Destroy observations for the set of descriptors in a given column
285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'app/models/observation.rb', line 285 def self.destroy_column(observation_matrix_column_id) c = ObservationMatrixColumn.find(observation_matrix_column_id) observations = self.in_observation_matrix(c.observation_matrix_id).where(descriptor_id: c.descriptor_id) begin Observation.transaction do observations.destroy_all end rescue raise end true end |
.destroy_row(observation_matrix_row_id) ⇒ Object
Destroy all observations for the set of descriptors in a given row
272 273 274 275 276 277 278 279 280 281 282 |
# File 'app/models/observation.rb', line 272 def self.destroy_row(observation_matrix_row_id) r = ObservationMatrixRow.find(observation_matrix_row_id) begin Observation.transaction do r.observations.destroy_all end rescue raise end true end |
.human_name ⇒ Object
222 223 224 |
# File 'app/models/observation.rb', line 222 def self.human_name 'YAY' end |
.in_observation_matrix(observation_matrix_id) ⇒ Object
178 179 180 181 182 |
# File 'app/models/observation.rb', line 178 def self.in_observation_matrix(observation_matrix_id) Observation.joins('JOIN observation_matrix_rows omr on (omr.observation_object_type = observations.observation_object_type AND omr.observation_object_id = observations.observation_object_id)') .joins('JOIN observation_matrix_columns omc on omc.descriptor_id = observations.descriptor_id') .where('omr.observation_matrix_id IN (?) AND omc.observation_matrix_id IN (?)', observation_matrix_id, observation_matrix_id) end |
.object_scope(object) ⇒ Object
TODO: deprecate or remove
217 218 219 220 |
# File 'app/models/observation.rb', line 217 def self.object_scope(object) return Observation.none if object.nil? Observation.where(observation_object: object) end |
Instance Method Details
#continuous? ⇒ Boolean
174 175 176 |
# File 'app/models/observation.rb', line 174 def continuous? type == 'Observation::Continuous' end |
#presence_absence? ⇒ Boolean
170 171 172 |
# File 'app/models/observation.rb', line 170 def presence_absence? type == 'Observation::PresenceAbsence' end |
#qualitative? ⇒ Boolean
depends on timeliness 6.0, which is breaking something validates_time :time_made, allow_nil: true
166 167 168 |
# File 'app/models/observation.rb', line 166 def qualitative? type == 'Observation::Qualitative' end |
#type_matches_descriptor ⇒ Object (protected)
337 338 339 340 341 |
# File 'app/models/observation.rb', line 337 def type_matches_descriptor a = type&.split('::')&.last b = descriptor&.type&.split('::')&.last errors.add(:type, 'type of Observation does not match type of Descriptor') if a && b && a != b end |