Module: Metasploit::Credential::EntityRelationshipDiagram
- Defined in:
- lib/metasploit/credential/entity_relationship_diagram.rb
Overview
Extract (along with MetasploitDataModel::EntityRelationshipDiagram), common ERD code and move to metasploit-documentation or metasploit-entity_relationship_diagram
Constant Summary collapse
- ATTRIBUTES =
Enable all attributes
[ :content, :foreign_keys, :primary_keys, :timestamps ]
- INDIRECT =
Only show direct relationships since the ERD is for use with SQL and there is no need to show has_many :through for those purposes.
false
- INHERITANCE =
Show inheritance for Single-Table Inheritance
true
- NOTATION =
Use crowsfoot notation since its what we use for manually drawn diagrams.
:crowsfoot
- DEFAULT_OPTIONS =
Default options for Diagram.
{ attributes: ATTRIBUTES, indirect: INDIRECT, inheritance: INHERITANCE, notation: NOTATION }
Class Method Summary collapse
-
.cluster(*classes) ⇒ Set<Class<ApplicationRecord>>
Cluster of classes that are reachable through belongs_to from ‘classes`.
-
.cluster_by_class ⇒ Hash{Class<ApplicationRecord> => Set<Class<ApplicationRecord>>}
All clusters of classes that are reachable through belongs_to from each ApplicationRecord descendant.
-
.create(options = {}) ⇒ String
Creates Graphviz diagram.
-
.domain ⇒ RailsERD::Domain
Domain containing all models in this gem.
-
.maximal_clusters ⇒ Array<Set<Class<ApplicationRecord>>>
Set of largest clusters from EntityRelationshipDiagram.cluster_by_class.
-
.polymorphic_classes(belongs_to_reflection) ⇒ Array<ApplicationRecord>
Calculates the target classes for a polymorphic ‘belongs_to`.
Class Method Details
.cluster(*classes) ⇒ Set<Class<ApplicationRecord>>
Cluster of classes that are reachable through belongs_to from ‘classes`.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/metasploit/credential/entity_relationship_diagram.rb', line 61 def self.cluster(*classes) class_queue = classes.dup visited_class_set = Set.new until class_queue.empty? klass = class_queue.pop # add immediately to visited set in case there are recursive associations visited_class_set.add klass # only iterate belongs_to as they need to be included so that foreign keys aren't let dangling in the ERD. reflections = klass.reflect_on_all_associations(:belongs_to) reflections.each do |reflection| if reflection.[:polymorphic] target_klasses = polymorphic_classes(reflection) else target_klasses = [reflection.klass] end target_klasses.each do |target_klass| unless visited_class_set.include? target_klass class_queue << target_klass end end end end visited_class_set end |
.cluster_by_class ⇒ Hash{Class<ApplicationRecord> => Set<Class<ApplicationRecord>>}
All clusters of classes that are reachable through belongs_to from each ApplicationRecord descendant
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/metasploit/credential/entity_relationship_diagram.rb', line 43 def self.cluster_by_class cluster_by_class = {} Metasploit::Credential::Engine.instance.eager_load! ApplicationRecord.descendants.each do |klass| klass_cluster = cluster(klass) cluster_by_class[klass] = klass_cluster end cluster_by_class end |
.create(options = {}) ⇒ String
Creates Graphviz diagram.
98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/metasploit/credential/entity_relationship_diagram.rb', line 98 def self.create(={}) domain = [:domain] domain ||= self.domain = .except(:domain) = DEFAULT_OPTIONS.merge() require 'rails_erd/domain' diagram = RailsERD::Diagram::Graphviz.new(domain, ) path = diagram.create path end |
.domain ⇒ RailsERD::Domain
Domain containing all models in this gem.
116 117 118 119 120 121 |
# File 'lib/metasploit/credential/entity_relationship_diagram.rb', line 116 def self.domain require_models require 'rails_erd/domain' RailsERD::Domain.generate end |
.maximal_clusters ⇒ Array<Set<Class<ApplicationRecord>>>
Set of largest clusters from cluster_by_class.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/metasploit/credential/entity_relationship_diagram.rb', line 126 def self.maximal_clusters clusters = cluster_by_class.values unique_clusters = clusters.uniq maximal_clusters = unique_clusters.dup cluster_queue = unique_clusters.dup until cluster_queue.empty? cluster = cluster_queue.pop proper_subset = false maximal_clusters.each do |maximal_cluster| if cluster.proper_subset? maximal_cluster proper_subset = true break end end if proper_subset maximal_clusters.delete(cluster) end end maximal_clusters end |
.polymorphic_classes(belongs_to_reflection) ⇒ Array<ApplicationRecord>
Calculates the target classes for a polymorphic ‘belongs_to`.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/metasploit/credential/entity_relationship_diagram.rb', line 156 def self.polymorphic_classes(belongs_to_reflection) name = belongs_to_reflection.name ApplicationRecord.descendants.each_with_object([]) { |descendant, target_classes| has_many_reflections = descendant.reflect_on_all_associations(:has_many) has_many_reflections.each do |has_many_reflection| as = has_many_reflection.[:as] if as == name target_classes << descendant end end } end |