Module: Metasploit::Model::Association::Tree

Defined in:
lib/metasploit/model/association/tree.rb

Overview

Functions for turning a compact tree of compact as passed to Search::Association::ClassMethods#search_associations into an expanded Search::Association::ClassMethods#search_association_tree.

Class Method Summary collapse

Class Method Details

.expand(compact) ⇒ Hash{Symbol => Hash,nil}

Expands a compact association into an expanded association tree.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/metasploit/model/association/tree.rb', line 10

def self.expand(compact)
  case compact
    when Array
      compact.reduce({}) { |hash, association|
        hash.merge(expand(association))
      }
    when Hash
      child_by_parent = compact

      child_by_parent.each_with_object({}) { |(parent, child), hash|
        hash[parent] = expand(child)
      }
    when Symbol
      association = compact

      {association => nil}
  end
end

.merge(first_expanded, second_expanded) ⇒ nil, Hash{Symbol => nil,Hash}

Note:

Unlike Hash#deep_merge, second_expanded's values aren't favored over first's values. Instead whichever side is present is used and if both first and second_expanded are present, then their Hash#keys' values are recursively merged.

Merges two expanded association trees.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/metasploit/model/association/tree.rb', line 38

def self.merge(first_expanded, second_expanded)
  if first_expanded.nil? && second_expanded.nil?
    nil
  elsif !first_expanded.nil? && second_expanded.nil?
    first_expanded
  elsif first_expanded.nil? && !second_expanded.nil?
    second_expanded
  else
    first_keys = first_expanded.keys
    key_set = Set.new(first_keys)

    second_keys = second_expanded.keys
    key_set.merge(second_keys)

    key_set.each_with_object({}) do |key, merged|
      first_child = first_expanded[key]
      second_child = second_expanded[key]

      merged[key] = merge(first_child, second_child)
    end
  end
end

.operators(expanded, options = {}) ⇒ Array<Metasploit::Model::Search::Operator::Association>

Calculates association operators for the expanded association tree.

Options Hash (options):

  • :class (Class, #reflect_on_association)

    The Class on which the top-level key associations in expanded are declared.



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
# File 'lib/metasploit/model/association/tree.rb', line 68

def self.operators(expanded, options={})
  expanded ||= {}

  options.assert_valid_keys(:class)
  klass = options.fetch(:class)

  expanded.flat_map { |parent_association, child_tree|
    reflection = reflect_on_association_on_class(parent_association, klass)
    association_class = reflection.klass

    association_search_with_operators = association_class.search_with_operator_by_name.each_value

    child_tree_operators = operators(
        child_tree,
        class: reflection.klass
    )

    [association_search_with_operators, child_tree_operators].flat_map { |enumerator|
      enumerator.map { |source_operator|
        Metasploit::Model::Search::Operator::Association.new(
            association: parent_association,
            klass: klass,
            source_operator: source_operator
        )
      }
    }
  }
end

.reflect_on_association_on_class(association, klass) ⇒ #klass (private)

Return the association reflection for association on klass.

Raises:



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/metasploit/model/association/tree.rb', line 106

def self.reflect_on_association_on_class(association, klass)
  begin
    reflection = klass.reflect_on_association(association)
  rescue NameError
    raise NameError,
          "#{self} does not respond to reflect_on_association.  " \
                    "It can be added to ActiveModels by including Metasploit::Model::Association into the class."
  end

  unless reflection
    raise Metasploit::Model::Association::Error.new(
              model: klass,
              name: association
          )
  end

  reflection
end