-
Notifications
You must be signed in to change notification settings - Fork 25
/
nomenclatural_rank.rb
133 lines (114 loc) · 3.72 KB
/
nomenclatural_rank.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# A {NomenclaturalRank} is used to assert the (organizational) position of a
# taxon name within a nomenclatural hierarchy, according to the governed (or not) levels
# described in a corresponding nomenclatural code.
#
# See /lib/ranks.rb for related constants and hooks.
#
class NomenclaturalRank
# self.descendants gets all descendant classes
# self.subclasses gets immediate descendants
# @return [ordered Array of NomenclaturalRank]
# for all direct descendants of this Class.
# Used to build constants in config/initializers/constants/ranks.rb.
#
# !! Further code should reference those constants rather than call this method.
#
def self.ordered_ranks
return false if self.name == 'NomenclaturalRank' # || (rank.class.name =~ /NomenclaturalRank/)
ordered = []
bottom = bottom_rank
top = top_rank
ordered.push(bottom)
ordered << ordered.last.parent_rank while ordered.last != top
ordered.reverse!
return ordered
end
# @return [NomenclaturalRank]
# the "top" rank for the nomenclatural group (e.g. ICZN species, genus, family) that this rank belongs to.
def self.top_rank
all = self.descendants
all.select!{|r| !r.parent_rank.nil?}
all.detect{|r| !all.include?(r.parent_rank)} # returns the first value found
end
# @return [NomenclaturalRank]
# the lowest assignable rank within the nomenclatural group (e.g. ICZN species, genus, family) that this class is part of
def self.bottom_rank
all = self.descendants
all.select!{|r| !r.parent_rank.nil?}
all_parents = all.collect{|i| i.parent_rank}
all.detect{|r| !all_parents.include?(r)}
end
# @return [String]
# the "common" name for this rank
def self.rank_name
n = self.name.demodulize.underscore.humanize.downcase
if n == 'potentially_validating rank'
n = 'root'
elsif n == 'class rank'
n = 'class'
end
n
end
# @return [Symbol, nil]
# the name of the nomenclatural code, as a short symbol (:iczn, :icn), or nil
def self.nomenclatural_code
return :iczn if self.name.to_s =~ /Iczn/
return :icnb if self.name.to_s =~ /Icnb/
return :icn if self.name.to_s =~ /Icn/
nil
end
# @return [NomenclaturalRank, nil]
# the parent class ({NomenclaturalRank::Iczn} or {NomenclaturalRank::Icn}) that this rank descends from
def self.nomenclatural_code_class
case self.nomenclatural_code
when :iczn
NomenclaturalRank::Iczn
when :icnb
NomenclaturalRank::Icnb
when :icn
NomenclaturalRank::Icn
else
nil
end
end
# The following attributes are stubbed here and over-ridden in subclasses.
# @return [Boolean]
# should the rank be displayed in "typical" use?
def self.typical_use
true
end
# @return [NomenclaturalRank, nil]
# the immediate parent {NomenclaturalRank} of this class, nil if a "root" level (e.g. {NomenclaturalRank::Iczn}, {NomenclaturalRank::Icn})
#
# All subclasses must override this method.
# nil returning classes can not be assigned as a {NomenclaturalRank} to a {TaxonName}!
def self.parent_rank
nil
end
# @return [String, nil]
# a TW preferred abbreviated name for this rank, e.g. "fam."
def self.abbreviation
nil
end
# @return [Array of NomenclaturalRank]
# the TaxonName assignable {NomenclaturalRank}s that this rank descend from
def self.valid_parents
[]
end
def valid_name_ending
''
end
private
# TODO: move this to string method
def self.collect_to_s(*args)
args.collect{|arg| arg.to_s}
end
# TODO: move this to lib/application_ennumeration
def self.collect_descendants_to_s(*classes)
ans = []
classes.each do |klass|
ans += klass.descendants.collect{|k| k.to_s}
end
ans
end
end