Skip to content

Commit

Permalink
homotypic synonyms
Browse files Browse the repository at this point in the history
  • Loading branch information
proceps committed Feb 6, 2014
1 parent 846be4e commit a611fb5
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 27 deletions.
57 changes: 50 additions & 7 deletions app/models/protonym.rb
Expand Up @@ -13,7 +13,7 @@ class Protonym < TaxonName
where("taxon_name_relationships.type LIKE 'TaxonNameRelationship::OriginalCombination::%'")
}, class_name: 'TaxonNameRelationship', foreign_key: :object_taxon_name_id

has_many :type_material
has_many :type_materials, class_name: 'TypeMaterial'

# subject object
# Aus original_genus of bus
Expand Down Expand Up @@ -64,10 +64,13 @@ class Protonym < TaxonName
scope :without_taxon_name_classification, -> (taxon_name_class_name) { where('id not in (SELECT taxon_name_id FROM taxon_name_classifications WHERE type LIKE ?)', "#{taxon_name_class_name}")}
scope :without_taxon_name_classification_array, -> (taxon_name_class_name_array) { where('id not in (SELECT taxon_name_id FROM taxon_name_classifications WHERE type in (?))', taxon_name_class_name_array) }
scope :without_taxon_name_classifications, -> { includes(:taxon_name_classifications).where(taxon_name_classifications: {taxon_name_id: nil}) }
scope :with_type_material_array, -> (type_material_array) { joins('LEFT OUTER JOIN "type_materials" ON "type_materials"."protonym_id" = "taxon_names"."id"').where("type_materials.biological_object_id in (?) AND type_materials.type_type in ('holotype', 'neotype', 'lectotype', 'syntype', 'syntypes')", type_material_array) }
scope :with_type_of_taxon_names, -> (type_id) { includes(:related_taxon_name_relationships).where("taxon_name_relationships.type LIKE 'TaxonNameRelationship::Typification%' AND taxon_name_relationships.subject_taxon_name_id = ?", type_id).references(:related_taxon_name_relationships) }
scope :not_self, -> (id) {where('taxon_names.id <> ?', id )}

scope :that_is_valid, -> {
joins('LEFT OUTER JOIN taxon_name_relationships tnr ON taxon_names.id = tnr.subject_taxon_name_id').
where('taxon_names.id NOT IN (SELECT subject_taxon_name_id FROM taxon_name_relationships WHERE type LIKE "TaxonNameRelationship::Iczn::Invalidating%" OR type LIKE "TaxonNameRelationship::Icn::Unaccepting%")')
where("taxon_names.id NOT IN (SELECT subject_taxon_name_id FROM taxon_name_relationships WHERE type LIKE 'TaxonNameRelationship::Iczn::Invalidating%' OR type LIKE 'TaxonNameRelationship::Icn::Unaccepting%')")
}

soft_validate(:sv_validate_parent_rank, set: :validate_parent_rank)
Expand All @@ -77,6 +80,8 @@ class Protonym < TaxonName
soft_validate(:sv_validate_coordinated_names, set: :validate_coordinated_names)
soft_validate(:sv_single_sub_taxon, set: :single_sub_taxon)
soft_validate(:sv_parent_priority, set: :parent_priority)
soft_validate(:sv_homotypic_synonyms, set: :homotypic_synonyms)
soft_validate(:sv_potential_homonyms, set: :potential_homonyms)

before_validation :check_format_of_name,
:validate_rank_class_class,
Expand Down Expand Up @@ -140,8 +145,8 @@ def self.family_group_base(name_string)

def get_primary_type
return [] unless self.rank_class.parent.to_s =~ /Species/
s = self.type_material.syntypes
p = self.type_material.primary
s = self.type_materials.syntypes
p = self.type_materials.primary
if s.empty? && p.count == 1
p
elsif p.empty? && s.empty?
Expand Down Expand Up @@ -289,7 +294,7 @@ def sv_fix_coordinated_names
types2.each do |t|
new_type_material.push({type_type: t.type_type, protonym_id: t.protonym_id, biological_object_id: t.biological_object_id, source_id: t.source_id})
end
self.type_material.build(new_type_material)
self.type_materials.build(new_type_material)
fixed = true
end

Expand Down Expand Up @@ -330,9 +335,9 @@ def sv_type_placement

def sv_primary_types
if self.rank_class.parent.to_s =~ /Species/
if self.type_material.primary.empty? && self.type_material.syntypes.empty?
if self.type_materials.primary.empty? && self.type_materials.syntypes.empty?
soft_validations.add(:base, 'Primary type is not selected')
elsif self.type_material.primary.count > 1 || (!self.type_material.primary.empty? && !self.type_material.syntypes.empty?)
elsif self.type_materials.primary.count > 1 || (!self.type_materials.primary.empty? && !self.type_materials.syntypes.empty?)
soft_validations.add(:base, 'More than one primary type are selected')
end
end
Expand Down Expand Up @@ -406,6 +411,44 @@ def sv_parent_priority
end
end

def sv_homotypic_synonyms
unless self.unavailable_or_invalid?
if self.id == self.lowest_rank_coordinated_taxon.id
possible_synonyms = []
if self.rank_class.to_s =~ /Species/
primary_types = self.get_primary_type
unless primary_types.empty?
p = primary_types.collect!{|t| t.biological_object_id}
possible_synonyms = Protonym.with_type_material_array(p).that_is_valid.not_self(self.id)
end
else
type = self.type_taxon_name
unless type.nil?
possible_synonyms = Protonym.with_type_of_taxon_names(type.id).that_is_valid.not_self(self.id)
end
end
unless possible_synonyms.empty?
possible_synonyms.select!{|s| s.id == s.lowest_rank_coordinated_taxon.id}
end
date1 = self.nomenclature_date unless possible_synonyms.empty?
possible_synonyms.each do |s|
date2 = s.nomenclature_date
if date1.nil? || date2.nil? || (not date1 < date2)
soft_validations.add(:base, "Taxon should be a synonym of #{s.cached_name + ' ' + s.cached_author_year} since they share the same type")
end
end
end
end
end

def sv_potential_homonyms
if self.id == self.lowest_rank_coordinated_taxon
if self.rank_class.to_s =~ /Species/
else
end
end
end

#endregion

end
24 changes: 22 additions & 2 deletions app/models/taxon_name.rb
Expand Up @@ -616,7 +616,7 @@ def sv_fix_parent_is_valid_name
def sv_cached_names
# if updated, update also set_cached_names
cached = true
if self.cached_name.blank?
if self.primary_homonym.blank?
cached = false
elsif self.cached_author_year != get_author_and_year
cached = false
Expand All @@ -635,10 +635,21 @@ def sv_cached_names
end
unless cached
soft_validations.add(:base, 'Cached values should be updated',
fix: :set_cached_names, success_message: 'Cached values were updated')
fix: :sv_fix_cached_names, success_message: 'Cached values were updated')
end
end

def sv_fix_cached_names
begin
TaxonName.transaction do
self.save
return true
end
rescue
end
false
end

def sv_validate_parent_rank
true # see validation in Protonym.rb
end
Expand Down Expand Up @@ -667,6 +678,15 @@ def sv_parent_priority
true # see validation in Protonym.rb
end

def sv_homotypic_synonyms
true # see validation in Protonym.rb
end

def sv_potential_homonyms
true # see validation in Protonym.rb
end


#endregion

end
Expand Down
69 changes: 51 additions & 18 deletions spec/models/protonym_spec.rb
Expand Up @@ -265,30 +265,30 @@

context 'missing_fields' do
specify "source author, year are missing" do
@species.soft_validate(:missing_fields)
expect(@species.soft_validations.messages_on(:source_id).empty?).to be_true
expect(@species.soft_validations.messages_on(:verbatim_author).empty?).to be_true
expect(@species.soft_validations.messages_on(:year_of_publication).empty?).to be_true
end
@species.soft_validate(:missing_fields)
expect(@species.soft_validations.messages_on(:source_id).empty?).to be_true
expect(@species.soft_validations.messages_on(:verbatim_author).empty?).to be_true
expect(@species.soft_validations.messages_on(:year_of_publication).empty?).to be_true
end
specify 'author and year are missing' do
@kingdom.soft_validate(:missing_fields)
expect(@kingdom.soft_validations.messages_on(:verbatim_author).empty?).to be_false
expect(@kingdom.soft_validations.messages_on(:year_of_publication).empty?).to be_false
end
specify 'fix author and year from the source' do
@source.update(year: 1758, author: 'Linnaeus')
@source.save
@kingdom.source = @source
@kingdom.soft_validate(:missing_fields)
expect(@kingdom.soft_validations.messages_on(:verbatim_author).empty?).to be_false
expect(@kingdom.soft_validations.messages_on(:year_of_publication).empty?).to be_false
@kingdom.fix_soft_validations # get author and year from the source
@kingdom.soft_validate(:missing_fields)
expect(@kingdom.soft_validations.messages_on(:verbatim_author).empty?).to be_true
expect(@kingdom.soft_validations.messages_on(:year_of_publication).empty?).to be_true
expect(@kingdom.verbatim_author).to eq('Linnaeus')
expect(@kingdom.year_of_publication).to eq(1758)
end
@source.update(year: 1758, author: 'Linnaeus')
@source.save
@kingdom.source = @source
@kingdom.soft_validate(:missing_fields)
expect(@kingdom.soft_validations.messages_on(:verbatim_author).empty?).to be_false
expect(@kingdom.soft_validations.messages_on(:year_of_publication).empty?).to be_false
@kingdom.fix_soft_validations # get author and year from the source
@kingdom.soft_validate(:missing_fields)
expect(@kingdom.soft_validations.messages_on(:verbatim_author).empty?).to be_true
expect(@kingdom.soft_validations.messages_on(:year_of_publication).empty?).to be_true
expect(@kingdom.verbatim_author).to eq('Linnaeus')
expect(@kingdom.year_of_publication).to eq(1758)
end
end

context 'coordinated taxa' do
Expand Down Expand Up @@ -381,6 +381,7 @@
expect(@subfamily.soft_validations.messages_on(:base).empty?).to be_false
@subfamily.fix_soft_validations
@subfamily.reload
expect(@subfamily.valid?).to be_true
@subfamily.soft_validate
expect(@subfamily.soft_validations.messages_on(:base).empty?).to be_true
end
Expand Down Expand Up @@ -495,6 +496,38 @@
expect(@subgenus.soft_validations.messages_on(:base).count).to eq(1)
end
end

context 'missing synonym relationship' do
specify 'same type species' do
g1 = FactoryGirl.create(:relationship_genus, name: 'Aus', parent: @family)
g2 = FactoryGirl.create(:relationship_genus, name: 'Bus', parent: @family)
s1 = FactoryGirl.create(:relationship_species, name: 'cus', parent: g1)
g1.type_species = s1
g2.type_species = s1
expect(g1.save).to be_true
expect(g2.save).to be_true
g1.soft_validate(:homotypic_synonyms)
expect(g1.soft_validations.messages_on(:base).count).to eq(1)
g1.iczn_set_as_unnecessary_replaced_name = g2
expect(g1.save).to be_true
g1.soft_validate(:homotypic_synonyms)
expect(g1.soft_validations.messages_on(:base).empty?).to be_true
end
specify 'same type specimen' do
s1 = FactoryGirl.create(:relationship_species, name: 'bus', parent: @genus)
s2 = FactoryGirl.create(:relationship_species, name: 'cus', parent: @genus)
t1 = FactoryGirl.create(:valid_type_material, protonym: s1, type_type: 'holotype')
t2 = FactoryGirl.create(:valid_type_material, protonym: s2, type_type: 'neotype', biological_object_id: t1.biological_object_id)
expect(s1.save).to be_true
expect(s2.save).to be_true
s1.soft_validate(:homotypic_synonyms)
expect(s1.soft_validations.messages_on(:base).count).to eq(1)
s1.iczn_set_as_unjustified_emendation_of = s2
expect(s1.save).to be_true
s1.soft_validate(:homotypic_synonyms)
expect(s1.soft_validations.messages_on(:base).empty?).to be_true
end
end
end

context 'scopes' do
Expand Down

0 comments on commit a611fb5

Please sign in to comment.