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
-
.expand(compact) ⇒ Hash{Symbol => Hash,nil}
Expands a
compact
association into an expanded association tree. -
.merge(first_expanded, second_expanded) ⇒ nil, Hash{Symbol => nil,Hash}
Merges two expanded association trees.
-
.operators(expanded, options = {}) ⇒ Array<Metasploit::Model::Search::Operator::Association>
Calculates association operators for the
expanded
association tree. -
.reflect_on_association_on_class(association, klass) ⇒ #klass
private
Return the association reflection for
association
onklass
.
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.(compact) case compact when Array compact.reduce({}) { |hash, association| hash.merge((association)) } when Hash child_by_parent = compact child_by_parent.each_with_object({}) { |(parent, child), hash| hash[parent] = (child) } when Symbol association = compact {association => nil} end end |
.merge(first_expanded, second_expanded) ⇒ nil, Hash{Symbol => nil,Hash}
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#key
s' 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(, ) if .nil? && .nil? nil elsif !.nil? && .nil? elsif .nil? && !.nil? else first_keys = .keys key_set = Set.new(first_keys) second_keys = .keys key_set.merge(second_keys) key_set.each_with_object({}) do |key, merged| first_child = [key] second_child = [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.
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(, ={}) ||= {} .assert_valid_keys(:class) klass = .fetch(:class) .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
.
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 |