SpeciesFileGroup/taxonworks

View on GitHub
app/models/concerns/shared/biological_associations.rb

Summary

Maintainability
A
0 mins
Test Coverage
# Shared code for extending data classes to be referencable in a BiologicalAssociation
module Shared::BiologicalAssociations
  extend ActiveSupport::Concern

  included do
    related_class = self.name
    klass = related_class.tableize.singularize.safe_constantize

    has_many :biological_associations, as: :biological_association_subject, inverse_of: :biological_association_subject, dependent: :restrict_with_error
    has_many :related_biological_associations, as: :biological_association_object, inverse_of: :biological_association_object, class_name: 'BiologicalAssociation', dependent: :restrict_with_error

    define_singleton_method :with_biological_associations do
      joins("LEFT OUTER JOIN biological_associations tnr1 ON otus.id = tnr1.biological_association_subject_id AND tnr1.biological_association_object_type = '#{related_class }'"). # Otu
        joins("LEFT OUTER JOIN biological_associations tnr2 ON otus.id = tnr2.biological_association_object_id AND tnr2.biological_association_object_type = '#{related_class}'").
        where('tnr1.biological_association_object_id IS NOT NULL OR tnr2.biological_association_object_id IS NOT NULL')
    end
  end

  # @return [Array]
  #   all bilogical associations this Otu is part of
  # !! If self relationships are ever made possible this needs a DISTINCT clause
  def all_biological_associations
    BiologicalAssociation.find_by_sql(
      "SELECT biological_associations.*
        FROM biological_associations
        WHERE biological_associations.biological_association_subject_id = #{id}
          AND biological_associations.biological_association_subject_type = '#{self.class.base_class.name}'
      UNION
      SELECT biological_associations.*
        FROM biological_associations
        WHERE biological_associations.biological_association_object_id = #{id}
          AND biological_associations.biological_association_object_type = '#{self.class.base_class.name}'")
  end

  # scope :with_biological_associations, -> {
  #   joins("LEFT OUTER JOIN biological_associations tnr1 ON otus.id = tnr1.biological_association_subject_id AND tnr1.biological_association_object_type = 'Otu'").
  #   joins("LEFT OUTER JOIN biological_associations tnr2 ON otus.id = tnr2.biological_association_object_id AND tnr2.biological_association_object_type = 'Otu'").
  #   where('tnr1.biological_association_object_id IS NOT NULL OR tnr2.biological_association_object_id IS NOT NULL')
  # }

  module ClassMethods

    # @param relationship [Array, String]
    def with_biological_relationship_id(biological_relationship_ids)
      a = joins(:biological_associations).where(biological_associations: {biological_relationship_id: biological_relationship_ids})
      b = joins(:related_biological_associations).where(biological_associations: {biological_relationship_id: biological_relationship_ids})

      from("((#{a.to_sql}) UNION (#{b.to_sql})) as #{base_class.table_name}")
    end

    # @param biological_relationship_ids [Array]
    # def self.with_biological_relationship_id(biological_relationship_ids)
    #   a = TaxonName.joins(:taxon_name_relationships).where(taxon_name_relationships: {type: relationship})
    #   b = TaxonName.joins(:related_taxon_name_relationships).where(taxon_name_relationships: {type: relationship})
    #   TaxonName.from("((#{a.to_sql}) UNION (#{b.to_sql})) as taxon_names")
    # end

  end
end