Class: Eco::API::Organization::TagTree

Inherits:
Object
  • Object
show all
Defined in:
lib/eco/api/organization/tag_tree.rb

Overview

Provides helpers to deal with tagtrees.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tagtree = [], depth: -1,, path: [], enviro: nil) ⇒ TagTree

Returns a new instance of TagTree.

Examples:

Node format:

{"tag": "NODE NAME", "nodes": subtree}

Tree/subtree format:

[[Node], ...]

Input format example:

tree = [{"tag" => "AUSTRALIA", "nodes" => [
    {"tag" => "SYDNEY", "nodes" => []}
]}]
tree = TagTree.new(tree.to_json)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/eco/api/organization/tag_tree.rb', line 21

def initialize(tagtree = [], depth: -1, path: [], enviro: nil)
  case tagtree
  when String
    @source = JSON.parse(tagtree)
  else
    @source = tagtree
  end
  fatal("You are trying to initialize a TagTree with a null tagtree") if !@source
  fatal("Expecting Environment object. Given: #{enviro}") if enviro && !enviro.is_a?(API::Common::Session::Environment)
  @enviro = enviro

  @depth = depth
  @tag = @source.is_a?(Array) ? nil : @source.dig('tag')&.upcase

  @path  = path || []
  @path.push(@tag) unless !@tag

  nodes = @source.is_a?(Array) ? @source : @source.dig('nodes') || []
  @nodes = nodes.map {|cnode| TagTree.new(cnode, depth: @depth + 1, path: @path.dup, enviro: @enviro)}

  init_hashes
end

Instance Attribute Details

#depthObject (readonly)

Returns the value of attribute depth.



8
9
10
# File 'lib/eco/api/organization/tag_tree.rb', line 8

def depth
  @depth
end

#enviroObject (readonly)

Returns the value of attribute enviro.



9
10
11
# File 'lib/eco/api/organization/tag_tree.rb', line 9

def enviro
  @enviro
end

#nodesObject (readonly)

Returns the value of attribute nodes.



7
8
9
# File 'lib/eco/api/organization/tag_tree.rb', line 7

def nodes
  @nodes
end

#path(key = nil) ⇒ Array<String> (readonly)

Note:

the path is not relative to the subtree, but absolute to the entire tree.

Finds the path from a node key to its root node in the tree. If key is not specified, returns the path from current node to root.



89
90
91
# File 'lib/eco/api/organization/tag_tree.rb', line 89

def path
  @path
end

#tagObject (readonly)

Returns the value of attribute tag.



7
8
9
# File 'lib/eco/api/organization/tag_tree.rb', line 7

def tag
  @tag
end

Instance Method Details

#default_tag(*values) ⇒ String

Helper to decide which among the tags will be the default.

  • take the deepest tag (the one that is further down in the tree)
  • if there are different options (several nodes at the same depth):
    • take the common node between them (i.e. you have Hamilton and Auckland -> take New Zealand)
    • if there's no common node between them, take the first (unless they are at top level of the tree)


136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/eco/api/organization/tag_tree.rb', line 136

def default_tag(*values)
  values = filter_tags(values)
  nodes = []; depth = -1
  values.each do |tag|
    raise("Couldn't find the node of #{tag} in the tag-tree definition") unless cnode = node(tag)

    if cnode.depth > depth
      nodes = [cnode]
      depth = cnode.depth
    elsif cnode.depth == depth
      nodes.push(cnode)
    end
  end

  default_tag = nil
  if nodes.length > 1
    common      = nodes.reduce(self.tags.reverse) {|com, cnode| com & cnode.path.reverse}
    default_tag = common.first if common.length > 0 && depth > 0
  end
  default_tag = nodes.first&.tag if !default_tag && depth > 0
  default_tag
end

#empty?Boolean



45
46
47
# File 'lib/eco/api/organization/tag_tree.rb', line 45

def empty?
  @has_tags.empty?
end

#filter_tags(list) ⇒ Array<String>

Filters tags out that do not belong to the tree



79
80
81
82
# File 'lib/eco/api/organization/tag_tree.rb', line 79

def filter_tags(list)
  return [] unless list && list.is_a?(Array)
  list.select {|str| tag?(str)}
end

#node(key) ⇒ TagTree?

Finds a subtree node.



71
72
73
74
# File 'lib/eco/api/organization/tag_tree.rb', line 71

def node(key)
  return nil unless tag?(key)
  @hash_tags[key.upcase]
end

#tag?(key) ⇒ Boolean

Verifies if a tag exists in the tree.



64
65
66
# File 'lib/eco/api/organization/tag_tree.rb', line 64

def tag?(key)
  @hash_tags.key?(key.upcase)
end

#tags(depth: nil) ⇒ Array<String>



51
52
53
54
55
56
57
58
59
# File 'lib/eco/api/organization/tag_tree.rb', line 51

def tags(depth: nil)
  if !depth || depth < 0
    @hash_tags.keys
  else
    @hash_tags.select do |t, n|
      n.depth == depth
    end.keys
  end
end

#user_tags(initial: [], final: [], preserve_custom: true, add_custom: false) ⇒ Array<String>

Helper to assign tags to a person account.

  • It preserves the :initial order, in case the :final tags are the same

Examples:

Usage example:

tree = [{"tag" => "Australia", "nodes" => [
     {"tag" => "SYDNEY", "nodes" => []},
     {"tag" => "MELBOURNE", "nodes" => []}
]}]

tree = TagTree.new(tree.to_json)
original = ["SYDNEY", "RISK"]
final    = ["MELBOURNE", "EVENT"]

tree.user_tags(initial: original, final: final) # out: ["MELBOURNE", "RISK"]
tree.user_tags(initial: original, final: final, preserve_custom: false) # out: ["MELBOURNE"]
tree.user_tags(initial: original, final: final, add_custom: true) # out: ["MELBOURNE", "RISK", "EVENT"]
tree.user_tags(initial: original, final: final, preserve_custom: false, add_custom: true) # out: ["MELBOURNE", "EVENT"]


117
118
119
120
121
122
123
124
125
126
127
# File 'lib/eco/api/organization/tag_tree.rb', line 117

def user_tags(initial: [], final: [], preserve_custom: true, add_custom: false)
  initial = [initial].flatten.compact
  final   = [final].flatten.compact
  raise "Expected Array for initial: and final:" unless initial.is_a?(Array) && final.is_a?(Array)
  final    = filter_tags(final) unless add_custom
  custom   = initial - filter_tags(initial)
  final    = final + custom     if preserve_custom
  new_tags = final - initial
  # keep same order as they where

  (initial & final) + new_tags
end