Module: Specify::Model::TreeQueryable
Overview
TreeQueryable is a mixin that provides methods to query trees such as Specify::Model::Taxnoomy and Specify::Model::Geography.
Trees are nested hierarchies that are represented by three classes
-
an item class, holding information about the items to be classified in
a tree, such as taxonomic or geographic names.
-
a rank class, which designates items as belonging to a formal rank or
level within the tree
-
the tree class itself, which identifies all items and ranks belonging
to one tree.
For taxonomies, the tree class is Specify::Model::Taxonomy, the item class is Specify::Model::Taxon, the rank class is Specify::Model::Rank.
For geographies, the tree class is Specify::Model::Geography, the item class is Specify::Model::GeographicName, the rank class is Specify::Model::AdministrativeDivision.
Constant Summary collapse
- AMBIGUOUS_MATCH_ERROR =
'Ambiguous results during tree search'
Instance Method Summary collapse
-
#rank(rank_name) ⇒ Object
Returns the rank instance in a tree for
rank_name(a String). -
#search_tree(hash) ⇒ Object
Preforms a tree search, traversing a hierarchy from highest to lowest rank.
Instance Method Details
#rank(rank_name) ⇒ Object
Returns the rank instance in a tree for rank_name (a String).
rank classes are Specify::Model::AdministrativeDivision (for Specify::Model::Geography), and Specify::Model::Rank (for Specify::Model::Taxonomy).
31 32 33 |
# File 'lib/specify/models/tree_queryable.rb', line 31 def rank(rank_name) ranks_dataset.first(Name: rank_name.capitalize) end |
#search_tree(hash) ⇒ Object
Preforms a tree search, traversing a hierarchy from highest to lowest rank. hash is a Hash with the structure { 'rank' => 'name' } where rank is an existing rank name, name an existing item name with that rank. Give key value paris in descencing order of rank:
{ 'rank 1' => 'name',
'rank 2' => 'name'
'rank n' => 'name' }
43 44 45 46 47 48 49 50 51 52 |
# File 'lib/specify/models/tree_queryable.rb', line 43 def search_tree(hash) hash.reduce(nil) do |item, (rank_name, name)| searchset = item&.children_dataset || names_dataset item = searchset.where(Name: name, rank: rank(rank_name)) next item.first unless item.count > 1 raise AMBIGUOUS_MATCH_ERROR + " for #{name}: #{item.to_a.map(&:FullName)}" end end |