SpeciesFileGroup/taxonworks

View on GitHub
app/models/documentation.rb

Summary

Maintainability
A
0 mins
Test Coverage
# A Documentation instance describes the relationship between a digital document (e.g pdf, txt file) and some data instance.
# Data types that can be document use Shared::Documentation.
#
# Documentation is to Documents as Depictions are to Images.
# !!`Documentation` is both singular and plural!!
#
# @!attribute documentation_object_id
#   @return [String]
#    the id of the documented object
#
# @!attribute documentation_object_type
#   @return [String]
#    the type of the documented object
#
# @!attribute document_id
#   @return [String]
#     the id of the Document
#
# @!attribute position
#   @return [Integer]
#     for acts as list, scopes to document
#
class Documentation < ApplicationRecord

  acts_as_list scope: [:project_id, :documentation_object_id, :documentation_object_type]

  include Housekeeping
  include Shared::Identifiers
  include Shared::Notes
  include Shared::Tags
  include Shared::IsData
  include SoftValidation
  include Shared::PolymorphicAnnotator
  polymorphic_annotates(:documentation_object)

  # These are all handled on the database side as not-null constraints
  # They can't be validated because we use accepts_nested_attributes
  # validates_presence_of :documentation_object_type, :documentation_object_id, :document_id
  # TODO: above is probably bs
  #
  # We catch invalid statements with this around:
  around_save :catch_statement_invalid

  after_save :check_for_projects_source, if: Proc.new {|n| n.documentation_object_type == 'Source'}

  belongs_to :documentation_object, polymorphic: true
  belongs_to :document, inverse_of: :documentation

  validates_presence_of :document

  accepts_nested_attributes_for :document
  accepts_nested_attributes_for :documentation_object

  protected

  def check_for_projects_source
    ProjectSource.find_or_create_by(
      project_id:,
      source_id: documentation_object_id)
  end

  def catch_statement_invalid
    begin
      yield # calls :after_save callback
    rescue ActiveRecord::StatementInvalid => e
      if e.cause.class.name == 'PG::NotNullViolation'
        errors.add(:base, 'a required field was not provided')
      else
        raise
      end
    end
  end

end