The Decider said over 2 years ago permalink Comment? (0)
Tagged: model relationships rails

finding relationships

I haven’t found a better way to discover all relationships between models other than loading in all models from the app/models directory and trying to instantiate them and then looking to see if they are a kind of ActiveRecord:Base. If they are then we can run reflect_on_all_associations.

In doing this I modified some code I found on the web to draw a .svg image of the relationships. Code looks like:

#!/usr/bin/env ruby
require "config/environment"
Dir.glob("app/models/*rb") { |f|
    require f
}

puts %{digraph x \{ 
  has_many1 [shape=point]
  has_many2 [shape=point]
  has_many1 -> has_many2 [label="Has many", color=red]
  belongs_to1 [shape=point]
  belongs_to2 [shape=point]
  belongs_to1 -> belongs_to2 [label="Belongs to", color=blue]
  has_and_belongs_to_many1 [shape=point]
  has_and_belongs_to_many2 [shape=point]
  has_and_belongs_to_many1 -> has_and_belongs_to_many2 [label="HaBtM", color=green]
  has_one1  [shape=point]
  has_one2  [shape=point]
  has_one1 -> has_one2 [label="Has one", color=gray]
  node [shape=box, style=filled, fillcolor=lightgray, width=2.5] 
}
Dir.glob("app/models/*rb") { |f|
    f.match(/\/([a-z_]+).rb/)
    classname = $1.camelize
    classname = $1 + 'QR' if classname =~ /(\w+)Qr$/ # total hack for question response models
    klass = Kernel.const_get classname
    obj = klass.new rescue next
    if obj.kind_of? ActiveRecord::Base
        puts classname
        klass.reflect_on_all_associations.each { |a|
          att = case a.macro
                  when :has_many : 'color=red, '# label="#{a.macro.to_s.humanize}"
                  when :belongs_to : 'color=blue, '
                  when :has_and_belongs_to_many : 'color=green, '
                  when :has_one : 'color=gray, '
                  else 'color=black, '
                  end
          puts %{ #{classname} -> #{a.name.to_s.camelize.singularize} [ #{att} fontsize="8"]}
        }
    end
}
puts "}"
  1. Install Graphviz
  2. Save that code in your lib or bin directory of your rails root. I called it rails_visual.rb then try:

PNG output
ruby bin/rails_visual.rb > surveil.dot; dot -Tpng -osurveil.png surveil.dot

SVG output
@ruby bin/rails_visual.rb > surveil.dot; dot -Tsvg -osurveil.svg surveil.dot @

Follow the image link to flickr to see the original (7959 × 1364) image
surveil