SpeciesFileGroup/taxonworks

View on GitHub
app/models/controlled_vocabulary_term.rb

Summary

Maintainability
A
1 hr
Test Coverage
# A controlled vocabulary term is a user defineable attribute, a name and definition is required.
#
# @!attribute type
#   @return [String]
#    The subclass of the CVT.
#
# @!attribute name
#   @return [String]
#     The term name.
#
# @!attribute definition
#   @return [String]
#    The term definition, required.
#
# @!attribute project_id
#   @return [Integer]
#   the project ID
#
# @!attribute uri
#   @return [String]
#    A URI for an external concept that matches this CVT.
#
# @!attribute uri_relation
#   @return [String]
#     A SKOS relationship that defines/describes the relationship between the concept identified by the URI and the concept defined in the definition.
#
class ControlledVocabularyTerm < ApplicationRecord
  # ControlledVocabularyTerms are NOT Taggable (with 'Tag')
  include Housekeeping
  include Shared::AlternateValues
  include Shared::HasPapertrail
  include Shared::IsData
  include SoftValidation

  acts_as_list scope: [:project_id, :type]

  ALTERNATE_VALUES_FOR = [:name, :definition].freeze

  validates_presence_of :name, :definition, :type
  validates_length_of :definition, minimum: 20

  validates_uniqueness_of :name, scope: [:type, :project_id]
  validates_uniqueness_of :definition, scope: [:project_id]

  validates_uniqueness_of :uri, scope: [:project_id, :uri_relation], allow_blank: true
  validates_presence_of :uri, unless: -> {uri_relation.blank?}, message: 'must be provided if uri_relation is provided'

  # TODO: DRY with Identifier::Global::Uri
  validate :form_of_uri
  validate :uri_relation_is_a_skos_relation

  has_many :observation_matrix_row_items, as: :observation_object, inverse_of: :observation_object,  class_name: 'ObservationMatrixRowItem::Dynamic::Tag', dependent: :destroy
  has_many :observation_matrix_column_items, inverse_of: :controlled_vocabulary_term, class_name: 'ObservationMatrixColumnItem::Dynamic::Tag', dependent: :destroy

  # TODO: this needs to come through columns rows
  has_many :observation_matrices, through: :observation_matrix_row_items

  scope :of_type, -> (type) { where(type: type.to_s.capitalize) } # TODO, capitalize is not the right method for things like `:foo_bar`

  protected

  def self.clone_from_project(from_id: nil, to_id: nil, klass: nil)
    return false if from_id.blank? or to_id.blank? or klass.blank?

    k = klass.safe_constantize
    k.where(project_id: from_id, type: klass).find_each do |cvt|
      begin
        i = cvt.dup
        i.project_id = to_id
        i.save!
      rescue ActiveRecord::RecordInvalid
      end
    end
    true
  end

  # def form_of_uri
  #   if uri.present?
  #     uris = URI.extract(uri)

  #     if uris.count == 0
  #       errors.add(:uri, 'More than a single URI present')
  #     else
  #       unless (uri.lenght == uris[0].length) && (uris.count == 1)
  #     end
  #   end
  # end

  def form_of_uri
    if uri.present?

      uris = URI.extract(uri)

      if uris.count == 0
        errors.add(:uri, 'URI provided by unparsable.')
      elsif uris.count > 1
        errors.add(:uri, 'More than a single URI present.')
      else
        begin
          u = URI(uri)
          scheme = u.scheme.upcase
          unless URI.scheme_list.keys.include?(scheme)
            errors.add(:uri, "#{scheme} is not in the URI schemes list.")
          end
        rescue
          errors.add(:uri, "Badly formed URI #{uri} detected.")
        end
      end
    end
  end

  # @return [Object]
  def uri_relation_is_a_skos_relation
    if uri.present? && uri_relation.present?
      errors.add(:uri_relation, 'is not a valid uri relation') if !SKOS_RELATIONS.keys.include?(uri_relation)
    end
  end

end

# require_dependency 'biocuration_class'
# require_dependency 'biological_property'
# require_dependency 'keyword'
# require_dependency 'predicate'
# require_dependency 'topic'
# require_dependency 'confidence_level'