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.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/metasploit/model/association/tree.rb', line 13 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.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/metasploit/model/association/tree.rb', line 41 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.
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 96 97 98 |
# File 'lib/metasploit/model/association/tree.rb', line 71 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
.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/metasploit/model/association/tree.rb', line 109 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 |