Visualize your Rails schema

While doing some Ruby on Rails code refactoring, I realized I’d like to visualize the database schema of the application.

An easy possibility is to print out db/schema.rb. This seems a bit too linear and little visual to me. OK, I’d better keep thinking.

An enterprise approach would be to take a CASE machinery and feed it with the create DB scripts. That is solid and reliable, but a kind of overkill. What’s more, a Rails app with convention over configuration can do well without foreign keys and so it usually does. This means that relations between tables are mostly implied by column names rather than explicitly declared as DB constraints. Thus, hardly any CASE tool can derive such relations from a DB schema.

OK, let’s try to go the Rails way and put together existing ingredients, add a little cream and see what we can get:

  • there are many UML modeling tools out there, although few of the free ones can reverse-engineer a DB schema
  • there’s the SchemaDumper in ActiveRecord, which generates the schema.rb based on DB reflection
  • there’s this standard XMI format for data interchange between modeling tools

OK, so let’s try and tweak the SchemaDumper to generate XMI, then import it into a UML modeling tool and get the schema diagram from there.

So, I morphed SchemaDumper into UmlDumper, which generates XMI in the widely adopted Rose flavor. E.g. a Typo blog database will result in schema.xml like this:

xmi.gif

Then I import this XMI into a UML tool – StarUML in my case – to get the basic picture. Yellow boxes are DB tables, grey boxes are presumed “virtual” tables referenced by columns in other tables.

raw.gif

I play a little with the layout and incorporate the “virtual” tables into the hierarchy. For completeness, I also add a few model classes, which show up only in Rails code, not in the database (manual entries in blue color):

main.gif

I export the diagram from the tool to print it, share it and enjoy.

Now, that’s it! The approach is quite universal (not yet true for UmlDumper), I can quickly reuse it in my further Rails projects, and so can you.

Note: for one-time use I created a rake task.

namespace :uml do
  desc "Generate an XMI db/schema.xml file describing the current DB as seen by AR. Produces XMI 1.1 for UML 1.3 Rose Extended, viewable e.g. by StarUML"
  task :schema => :environment do
    require 'lib/uml_dumper.rb'
    File.open("db/schema.xml", "w") do |file|
      ActiveRecord::UmlDumper.dump(ActiveRecord::Base.connection, file)
    end 
    puts "Done. Schema XMI created as db/schema.xml."
  end
end

For frequent use (fine-tuning the export), it is better to start the Rails console and call UmlDumper from there to avoid re-loading the whole Rails stack all over again.

11 comments

  1. This looks similar to the Rails Application Visualizer plugin (which has Graphviz as a dependency instead of UMLDumper). RAV also allows you to visualize your controller structure and the associated methods.

    Overall, looks good, though it would be nice if it included all models automatically.

  2. good stuff. But I am kinda clumsy. How do I “tweak the SchemaDumper to generate XMI? ” Can you specify a bit more? Thanks! =)

  3. If you’re using PostgreSQL there are two more ways to visualize the schema –
    DBGraffle4 plugin for OmniGraffle Professional (available only on Mac)
    postgresql_autodoc (multiplatform, multioutput)

    OmniGraffle in combination with DBGraffle produces much more readable diagram than postgresql_autodoc, however, a little ordering of the boxes is needed.

  4. Thanks, Miroslav, for this useful tool. And thanks (多谢), cnruby, for packaging it as a simple plugin. Everything works (for me at least) exactly as advertised.

  5. Thank you very much Miroslav. I was using DBDesigner and reverse engineering to generate the database model of my application but your solution is 10x times cooler: UML & XMI are standards, associations are generated …

    One thing, I believe you made a small mistake regarding the direction of the association (the arrow)

    Take a look at
    http://www.agilemodeling.com/artifacts/classDiagram.htm#Associations
    if you want to check it.

    Therefore, I did the following change:
    def print_assoc(stream,asn,e1n,e2n,t1,t2)
    stream.puts <



    ASSOCS
    end

    I can also send you a patch if you prefer (just have to learn how to make patch before!)

    I’d love to contribute to your code. Would you like to create a rubyforge project? I could do for you if you like. Do you have some tests?

    Thanks again for sharing,

    Jean-Michel

  6. Really nice stuff. This is a great tutorial for our crossover developers who are building new database driven apps in Ruby and need tools. We’ve cross-tagged it in both so they can find. Let us know if you have more like it for the Ruby section on TekTag.com.

    TJ

  7. Hi Miroslav,

    This looks a cool tool .. but with Ruby so far I’m a fool …

    Ok enough already 🙂

    Just getting up to speed with R.O.R., I’ve programmed with a bunch of other languages.

    I stuck the uml_dumper.rb in my rails_apps\tasty\lib directory, but I have no clue on how to start it.

    I took a stab in the dark and copied script\about to script\uml and changed
    the script to :

    #require ‘commands/about’
    require ‘lib/uml_dumper.rb’

    but that doesn’t work.

    I get the error messages below.

    I’ll keep digging around, but maybe you’ll be bored and have pity on me and have some info for me before I find the answer 🙂

    Mike

    —————————–

    F:\ruby\InstantRails\rails_apps\tasty>ruby script\uml
    ./lib/uml_dumper.rb:16: undefined method `cattr_accessor’ for ActiveRecord::UmlD
    umper:Class (NoMethodError)
    from F:/ruby/InstantRails/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_re
    quire.rb:27:in `gem_original_require’
    from F:/ruby/InstantRails/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_re
    quire.rb:27:in `require’
    from script/uml:7

Comments are closed.