class Onoma::Item
An item of a nomenclature is the core data.
Attributes
aliases[R]
attributes[RW]
depth[R]
left[R]
name[RW]
nomenclature[R]
parent_name[R]
properties[RW]
right[R]
Public Class Methods
new(nomenclature, name, options = {})
click to toggle source
New item
# File lib/onoma/item.rb, line 12 def initialize(nomenclature, name, options = {}) @nomenclature = nomenclature @name = name.to_s @left, @right = @nomenclature.new_boundaries @depth = 0 @parent = nil @parent_name = nil parent = options.delete(:parent) if parent.is_a?(Symbol) || parent.is_a?(String) @parent_name = parent.to_s else self.parent = parent end @attributes = {}.with_indifferent_access @children = Set.new options.each do |k, v| set(k, v) end end
Public Instance Methods
<(other)
click to toggle source
# File lib/onoma/item.rb, line 224 def <(other) other = item_for_comparison(other) (other.left < @left && @right < other.right) end
<=(other)
click to toggle source
# File lib/onoma/item.rb, line 234 def <=(other) other = item_for_comparison(other) (other.left <= @left && @right <= other.right) end
<=>(other)
click to toggle source
# File lib/onoma/item.rb, line 219 def <=>(other) other = item_for_comparison(other) nomenclature.name <=> other.nomenclature.name && name <=> other.name end
==(other)
click to toggle source
# File lib/onoma/item.rb, line 214 def ==(other) other = item_for_comparison(other) nomenclature == other.nomenclature && name == other.name end
>(other)
click to toggle source
# File lib/onoma/item.rb, line 229 def >(other) other = item_for_comparison(other) (@left < other.left && other.right < @right) end
>=(other)
click to toggle source
# File lib/onoma/item.rb, line 239 def >=(other) other = item_for_comparison(other) (@left <= other.left && other.right <= @right) end
add_child(item)
click to toggle source
# File lib/onoma/item.rb, line 63 def add_child(item) @children << item end
children(options = {})
click to toggle source
Returns children recursively by default
# File lib/onoma/item.rb, line 117 def children(options = {}) if options[:index].is_a?(FalseClass) if options[:recursively].is_a?(FalseClass) @children.to_a else children(index: false, recursive: false).each_with_object([]) do |item, list| list << item list += item.children(index: false, recursive: true) list end end elsif options[:recursively].is_a?(FalseClass) nomenclature.list.select do |item| @left < item.left && item.right < @right && item.depth == @depth + 1 end else # @children ||= nomenclature.list.select do |item| @left < item.left && item.right < @right end end end
degree_of_kinship_with(other)
click to toggle source
# File lib/onoma/item.rb, line 95 def degree_of_kinship_with(other) other_item = item_for_comparison(other) a = self_and_parents.reverse b = other_item.self_and_parents.reverse return nil if a.first != b.first common_lineage = 0 a.size.times do |index| break if a[index].nil? || b[index].nil? || a[index] != b[index] common_lineage += 1 end a.size + b.size - 2 * common_lineage end
delete_child(item)
click to toggle source
# File lib/onoma/item.rb, line 67 def delete_child(item) @children.delete(item) end
find_parent()
click to toggle source
# File lib/onoma/item.rb, line 91 def find_parent @nomenclature.find(@parent_name) end
has_property?(name)
click to toggle source
Checks if item has property with given name
# File lib/onoma/item.rb, line 313 def has_property?(name) !@nomenclature.properties[name].nil? end
human_name(options = {})
click to toggle source
Return human name of item
# File lib/onoma/item.rb, line 188 def human_name(options = {}) scope = options.delete(:scope) no_attribute_translation = "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(name)}" if scope scope_attribute = scope other_attributes = attributes.except(scope_attribute) scope_translation = "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(scope_attribute)}.#{Onoma.escape_key(name)}" other_translations = other_attributes.map { |attr_name, _value| "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(attr_name)}.#{Onoma.escape_key(name)}" } root = scope_translation defaults = [no_attribute_translation, *other_translations] else scoped_by_attributes = attributes.map { |attr_name, _value| "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(attr_name)}.#{Onoma.escape_key(name)}" } root = "nomenclatures.#{Onoma.escape_key(nomenclature.name)}.items.#{Onoma.escape_key(name)}" defaults = scoped_by_attributes end I18n.t(root, options.merge(default: [*defaults.map(&:to_sym), "items.#{Onoma.escape_key(name)}".to_sym, "enumerize.#{Onoma.escape_key(nomenclature.name)}.#{Onoma.escape_key(name)}".to_sym, "labels.#{Onoma.escape_key(name)}".to_sym, name.humanize])) end
human_notion_name(notion_name, options = {})
click to toggle source
# File lib/onoma/item.rb, line 210 def human_notion_name(notion_name, options = {}) I18n.t("nomenclatures.#{nomenclature.name}.notions.#{notion_name}.#{name}", options.merge(default: ["labels.#{name}".to_sym])) end
include?(other)
click to toggle source
Returns true if the given item name match the current item or its children
# File lib/onoma/item.rb, line 183 def include?(other) self >= other end
inspect()
click to toggle source
# File lib/onoma/item.rb, line 244 def inspect "#{@nomenclature.name}-#{@name}(#{@left}-#{@right})" end
method_missing(method_name, *args)
click to toggle source
Returns property descriptor
Calls superclass method
# File lib/onoma/item.rb, line 318 def method_missing(method_name, *args) return property(method_name) if has_property?(method_name) super end
original_nomenclature_name()
click to toggle source
# File lib/onoma/item.rb, line 110 def original_nomenclature_name return parent.name.to_sym unless root? nil end
parent()
click to toggle source
# File lib/onoma/item.rb, line 81 def parent return @parent if @parent @parent = find_parent @parent.add_child(self) if @parent @parent end
Also aliased as: fetch_parent
parent=(item)
click to toggle source
# File lib/onoma/item.rb, line 36 def parent=(item) old_parent_name = @parent_name old_parent = @parent if item.nil? @parent = nil @parent_name = nil else if item.is_a?(Symbol) || item.is_a?(String) item = nomenclature.find!(item.to_s) end if item.nomenclature != nomenclature raise 'Item must come from same nomenclature' end if item.parents.any? { |p| self == p } || self == item raise 'Circular dependency. Item can be parent of itself.' end @parent = item @parent_name = @parent.name.to_s end if old_parent_name != @parent_name old_parent.delete_child(self) if old_parent @parent.add_child(self) if @parent @nomenclature.rebuild_tree! end end
parent?()
click to toggle source
# File lib/onoma/item.rb, line 77 def parent? parent.present? end
parent_name=(name)
click to toggle source
Changes parent without rebuilding
# File lib/onoma/item.rb, line 72 def parent_name=(name) @parent = nil @parent_name = name.to_s end
parents()
click to toggle source
Returns direct parents from the closest to the farthest
# File lib/onoma/item.rb, line 145 def parents @parents ||= (parent.nil? ? [] : [parent] + parent.parents) end
property(name)
click to toggle source
Returns property value
# File lib/onoma/item.rb, line 274 def property(name) return @name.to_sym if name == :name property = @nomenclature.properties[name] value = @attributes[name] if property if value.nil? && property.fallbacks property.fallbacks.each do |fallback| value ||= @name if fallback == :name value ||= @attributes[fallback] break if value end end value = cast_property(name, property.default) if property.default && value.nil? end value end
rebuild_tree(left = 0, depth = 0)
click to toggle source
Computes left/right value for nested set Returns right index
# File lib/onoma/item.rb, line 172 def rebuild_tree(left = 0, depth = 0) @depth = depth @left = left @right = @left + 1 children(index: false, recursively: false).each do |child| @right = child.rebuild_tree(@right, @depth + 1) + 1 end @right end
rebuild_tree!()
click to toggle source
Computes left/right value for nested set Returns right index
# File lib/onoma/item.rb, line 166 def rebuild_tree! @nomenclature.forest_right = rebuild_tree(@nomenclature.forest_right + 1) end
rise() { |self| ... }
click to toggle source
# File lib/onoma/item.rb, line 157 def rise(&block) result = yield(self) return result if result parent ? parent.rise(&block) : nil end
root()
click to toggle source
# File lib/onoma/item.rb, line 140 def root parent? ? parent.root : self end
root?()
click to toggle source
# File lib/onoma/item.rb, line 32 def root? !parent end
selection(name)
click to toggle source
# File lib/onoma/item.rb, line 292 def selection(name) property = @nomenclature.properties[name] if property.list? return property(name).collect do |i| ["nomenclatures.#{@nomenclature.name}.item_lists.#{self.name}.#{name}.#{i}".t, i] end elsif property.nomenclature? target_nomenclature = Onoma.find(property(name).to_sym) unless target_nomenclature raise "Cannot find nomenclature: for #{property(name).inspect}" end return target_nomenclature.list.collect do |i| [i.human_name, i.name] end else raise StandardError.new('Cannot call selection for a non-list property') end end
self_and_children(options = {})
click to toggle source
# File lib/onoma/item.rb, line 149 def self_and_children(options = {}) [self] + children(options) end
self_and_parents()
click to toggle source
# File lib/onoma/item.rb, line 153 def self_and_parents [self] + parents end
set(name, value)
click to toggle source
# File lib/onoma/item.rb, line 324 def set(name, value) raise "Invalid property: #{name.inspect}" if %i[name parent].include?(name.to_sym) # # TODO: check format # if property = nomenclature.properties[name] # value ||= [] if property.list? # end if value.nil? @attributes.delete(name) else @attributes[name] = value end end
to_xml_attrs()
click to toggle source
# File lib/onoma/item.rb, line 256 def to_xml_attrs attrs = {} attrs[:name] = name attrs[:parent] = @parent_name if parent? properties.each do |pname, pvalue| if p = nomenclature.properties[pname.to_s] if p.type == :decimal pvalue = pvalue.to_s.to_f elsif p.list? pvalue = pvalue.join(', ') end end attrs[pname] = pvalue.to_s end attrs end
tree(depth = 0)
click to toggle source
# File lib/onoma/item.rb, line 248 def tree(depth = 0) text = "#{left.to_s.rjust(4)}-#{right.to_s.ljust(4)} #{' ' * depth}#{@name}:\n" text << children(index: false, recursively: false).collect do |c| c.tree(depth + 1) end.join("\n") text end
Private Instance Methods
cast_property(name, value)
click to toggle source
# File lib/onoma/item.rb, line 340 def cast_property(name, value) @nomenclature.cast_property(name, value) end
item_for_comparison(other)
click to toggle source
# File lib/onoma/item.rb, line 344 def item_for_comparison(other) item = nomenclature[other.is_a?(Item) ? other.name : other] unless item raise StandardError.new("Invalid operand to compare: #{other.inspect} not in #{nomenclature.name}") end item end