diff --git a/app/models/taxon_name.rb b/app/models/taxon_name.rb index 8b66fd031a..e8061c9b95 100644 --- a/app/models/taxon_name.rb +++ b/app/models/taxon_name.rb @@ -22,7 +22,6 @@ class TaxonName < ActiveRecord::Base has_many :taxon_name_authors, through: :taxon_name_author_roles, source: :person soft_validate(:sv_missing_fields, set: :missing_fields) - soft_validate(:sv_validate_disjoint_relationships, set: :disjoint) soft_validate(:sv_validate_disjoint_classes, set: :disjoint) soft_validate(:sv_validate_disjoint_objects, set: :disjoint) soft_validate(:sv_validate_disjoint_subjects, set: :disjoint) @@ -346,15 +345,7 @@ def sv_fix_missing_year false end - def sv_validate_disjoint_relationships - relationships = self.taxon_name_relationships - relationship_names = relationships.map{|i| i.type_name} - disjoint_relationships = relationships.map{|i| i.type_class.disjoint_taxon_name_relationships}.flatten - compare = disjoint_relationships & relationship_names - compare.each do |i| - soft_validations.add(:base, "Taxon has a conflicting relationship: '#{i.constantize.subject_relationship_name}'") - end - end + def sv_validate_disjoint_classes classifications = self.taxon_name_classifications diff --git a/app/models/taxon_name_relationship.rb b/app/models/taxon_name_relationship.rb index a6e230de27..195a7263c6 100644 --- a/app/models/taxon_name_relationship.rb +++ b/app/models/taxon_name_relationship.rb @@ -2,11 +2,14 @@ class TaxonNameRelationship < ActiveRecord::Base include Housekeeping include Shared::Citable + include SoftValidation belongs_to :subject_taxon_name, class_name: 'TaxonName', foreign_key: :subject_taxon_name_id # left side belongs_to :object_taxon_name, class_name: 'TaxonName', foreign_key: :object_taxon_name_id # right side belongs_to :source + soft_validate(:sv_validate_disjoint_relationships, set: :disjoint) + validates_presence_of :type, message: 'Relationship type should be specified' validates_presence_of :subject_taxon_name_id, message: 'Taxon is not selected' validates_presence_of :object_taxon_name_id, message: 'Taxon is not selected' @@ -27,7 +30,7 @@ class TaxonNameRelationship < ActiveRecord::Base scope :with_type_base, -> (base_string) {where('type LIKE ?', "#{base_string}%" ) } scope :with_type_array, -> (base_array) {where('type IN (?)', base_array ) } scope :with_type_contains, -> (base_string) {where('type LIKE ?', "%#{base_string}%" ) } - scope :not_self, -> (id) {where('id != ?', id )} + scope :not_self, -> (id) {where('id <> ?', id )} def is_combination? !!/TaxonNameRelationship::(OriginalCombination|Combination|SourceClassifiedAs)/.match(self.type.to_s) @@ -104,6 +107,7 @@ def assign_houskeeping_if_possible end end + #region Validation # TODO: Flesh this out vs. TaxonName#rank_class. Ensure that FactoryGirl type can be set in postgres branch. def validate_type @@ -157,5 +161,17 @@ def validate_uniqueness_of_typification_object end end + #endregion + + #region Soft Validation + + def sv_validate_disjoint_relationships + relationships = TaxonNameRelationship.where_subject_is_taxon_name(self.subject_taxon_name).not_self(self) + relationships.each do |i| + soft_validations.add(:type, "Conflicts with other relationship: '#{i.type_class.subject_relationship_name}'") if self.type_class.disjoint_taxon_name_relationships.include?(i.type_name) + end + end + + #endregion end diff --git a/spec/models/taxon_name_relationship_spec.rb b/spec/models/taxon_name_relationship_spec.rb index 08165f4085..9dbaeeac0f 100644 --- a/spec/models/taxon_name_relationship_spec.rb +++ b/spec/models/taxon_name_relationship_spec.rb @@ -3,31 +3,33 @@ describe TaxonNameRelationship do context 'Taxon Name relationships' do - context 'requires' do - before(:all) do - TaxonName.delete_all - TaxonNameRelationship.delete_all - @taxon_name_relationship = FactoryGirl.build(:taxon_name_relationship) - @taxon_name_relationship.valid? - @species = FactoryGirl.create(:relationship_species) - @genus = @species.ancestor_at_rank('genus') - end + before(:all) do + TaxonName.delete_all + TaxonNameRelationship.delete_all + @taxon_name_relationship = FactoryGirl.build(:taxon_name_relationship) + @taxon_name_relationship.valid? + @subspecies = FactoryGirl.create(:iczn_subspecies) + @species = @subspecies.ancestor_at_rank('species') + @genus = @subspecies.ancestor_at_rank('genus') + @family = @subspecies.ancestor_at_rank('family') + end - after(:all) do - TaxonName.delete_all - TaxonNameRelationship.delete_all - end + after(:all) do + TaxonName.delete_all + TaxonNameRelationship.delete_all + end + context 'requires' do context 'associations' do specify 'subject (TaxonName)' do - expect(@taxon_name_relationship).to respond_to (:subject_taxon_name) - end + expect(@taxon_name_relationship).to respond_to (:subject_taxon_name) + end specify 'object (TaxonName)' do - expect(@taxon_name_relationship).to respond_to (:object_taxon_name) - end + expect(@taxon_name_relationship).to respond_to (:object_taxon_name) + end specify 'type' do - expect(@taxon_name_relationship).to respond_to (:type) - end + expect(@taxon_name_relationship).to respond_to (:type) + end end context 'validate' do @@ -113,10 +115,26 @@ r2.valid? expect(r2.errors.include?(:object_taxon_name_id)).to be_true end - end end end + + context 'soft validation' do + specify 'disjoint relationships' do + g = FactoryGirl.create(:iczn_genus, parent: @family) + s = FactoryGirl.create(:iczn_species, parent: g) + r1 = FactoryGirl.create(:taxon_name_relationship, subject_taxon_name: s, object_taxon_name: @species, type: TaxonNameRelationship::Iczn::Validating::ConservedName) + r1.soft_validate(:disjoint) + expect(r1.soft_validations.messages_on(:type).empty?).to be_true + r2 = FactoryGirl.create(:taxon_name_relationship, subject_taxon_name: s, object_taxon_name: @species, type: TaxonNameRelationship::Iczn::Invalidating::Synonym) + r1.soft_validate(:disjoint) + expect(r1.soft_validations.messages_on(:type).count).to eq(1) + r2.soft_validate(:disjoint) + expect(r2.soft_validations.messages_on(:type).count).to eq(1) + end + + + end end diff --git a/spec/models/taxon_name_spec.rb b/spec/models/taxon_name_spec.rb index e5de624a42..bf0b8258ec 100644 --- a/spec/models/taxon_name_spec.rb +++ b/spec/models/taxon_name_spec.rb @@ -308,26 +308,6 @@ end context 'relationships' do - specify 'disjoint relationships' do - g = FactoryGirl.create(:iczn_genus, parent: @family) - s = FactoryGirl.create(:iczn_species, parent: g) - r1 = FactoryGirl.create(:taxon_name_relationship, subject_taxon_name: g, object_taxon_name: s, type: TaxonNameRelationship::OriginalCombination::OriginalGenus) - r2 = FactoryGirl.create(:taxon_name_relationship, subject_taxon_name: s, object_taxon_name: g, type: TaxonNameRelationship::Typification::Genus) - r3 = FactoryGirl.create(:taxon_name_relationship, subject_taxon_name: s, object_taxon_name: @species, type: TaxonNameRelationship::Iczn::Validating::ConservedName) - expect(r1.save).to be_true - expect(r2.save).to be_true - expect(r3.save).to be_true - expect(s.taxon_name_relationships.count).to eq(2) - s.soft_validate(:disjoint) - expect(s.soft_validations.messages_on(:base).empty?).to be_true - r4 = FactoryGirl.create(:taxon_name_relationship, subject_taxon_name: s, object_taxon_name: @species, type: TaxonNameRelationship::Iczn::Invalidating::Synonym) - expect(r4.save).to be_true - s.reload - expect(s.taxon_name_relationships.count).to eq(3) - s.soft_validate(:disjoint) - expect(s.soft_validations.messages_on(:base).count).to eq(2) - expect(r3.valid?).to be_true - end specify 'disjoint classes' do g = FactoryGirl.create(:iczn_genus, parent: @family) s = FactoryGirl.create(:iczn_species, parent: g)