SpeciesFileGroup/taxonworks

View on GitHub
app/models/concerns/shared/is_data/annotation.rb

Summary

Maintainability
A
0 mins
Test Coverage

module Shared::IsData::Annotation

  extend ActiveSupport::Concern

  # This is indirectly responsible for
  # visual position placement in radial annotator
  # middle is left, top/bottom right

  # see config/initializes/constanst/model/annotations for types

  included do

    # @return [Boolean]
    # true if model is an "annotator" (e.g. identifiers, tags, notes, data attributes, alternate values, citations), i.e. data that references another data element through STI
    def annotates?
      respond_to?(:annotated_object)
    end
  end


  module ClassMethods

    def annotates?
      self < Shared::PolymorphicAnnotator ? true : false
    end

    # Determines whether the class can be annotated
    # in one of the following ways
    ::ANNOTATION_TYPES.each do |t|
      define_method("has_#{t}?") do
        k = "Shared::#{t.to_s.singularize.classify.pluralize}".safe_constantize
        self < k ? true : false
      end
    end

    def available_annotation_types
      ::ANNOTATION_TYPES.collect do |a|
        self.send("has_#{a}?") ? a.to_s.classify : nil
      end.compact
    end
  end

  # Determines whether the instance can be annotated
  # in one of the following ways
  ::ANNOTATION_TYPES.each do |t|
    define_method("has_#{t}?") do
      k = "Shared::#{t.to_s.singularize.classify.pluralize}".safe_constantize
      self.class < k ? true : false
    end
  end

  def available_annotation_types
    ::ANNOTATION_TYPES.select do |a|
      self.send("has_#{a}?")
    end
  end

  # Doesn't belong here
  def has_loans?
    self.class < Shared::Loanable ? true : false
  end

  # @return [Hash]
  #   an accessor for the annotations_hash, overwritten by some inheriting classes
  def annotations
    annotations_hash
  end

  # @return [Hash]
  def annotation_metadata(project_id = nil)
    h = {}

    # Use a fixed order for UI stability
    ANNOTATION_TYPES.each do |t|
      next unless available_annotation_types.include?(t)
      case t
      when :documentation

        if project_id
          h[:documentation] = {total: documentation.where(documentation: {project_id:}).count}
        else
          h[:documentation] = {total: ( send(:documentation).count) }
        end

      when :attribution
        h[:attribution] = {total: (send(:attribution).present? ? 1 : 0)}
      when :identifiers

        if project_id
          h[:identifiers] = {total: ( send(:identifiers).visible(project_id).count)}
        else
          h[:identifiers] = {total: ( send(:identifiers).count) }
        end
      else
        h[t] = { total: send(t).count }
      end
    end
    h
  end

  protected

  # @return [Hash]
  # Contains all "annotations" for this instance
  def annotations_hash
    result = {}
    result['citations'] = citations if has_citations? && citations.load.any? # Use load since we nearly always are going ot reference the result
    result['data attributes'] = data_attributes if has_data_attributes? && data_attributes.load.any?
    result['identifiers'] = identifiers if has_identifiers? && identifiers.load.any? # !! TODO:  Load is broken here.
    result['notes'] = notes if has_notes? && notes.load.any?
    result['tags'] = tags if has_tags? && tags.load.any?
    result['depictions'] = depictions.order('depictions.position') if has_depictions? && depictions.load.any?
    result['confidences'] = confidences if has_confidences? && confidences.load.any?
    result['protocol relationships'] = protocols if has_protocol_relationships? && protocolled?
    result['alternate values'] = alternate_values if has_alternate_values? && alternate_values.load.any?
    result['attribution'] = attribution if has_attribution? && attribution.load.any?

    result['verifiers'] = verifiers if has_verifiers? && verifiers.load.any?
    result
  end

end