Creating Entity Relationship diagrams with Sinatra/ActiveRecord
One of the first ruby gems I add to new Rails projects is Rails ERD.
However in my personal website and blog, I've opted for the simplicity that Sinatra provides. As my project has grown in complexity by adding more models, I've missed the simple visualization that rails-erd
 provides.
Setting up rails-erd
 in Sinatra.
This assumes you've already set up ActiveRecord with Sinatra.
First step is to add rails-erd to your gem file:
# Gemfile
gem 'rails-erd', '~> 1.6' , group: :development
Running the default task $ bundle exec rake erd
  will fail because the default task is trying to load the rails environment. The solution is to do the loading yourself.
looking at the rails-erd project, you can see the tasks in /lib/rails_erd/tasks.rake
. The problem here is that the generate task runs this task as a prerequisite, but it depends on the Rails environment.
  task :load_models do
    say "Loading application environment..."
    Rake::Task[:environment].invoke
    say "Loading code in search of Active Record models..."
    begin
      Rails.application.eager_load!
      if Rails.application.respond_to?(:config) && !Rails.application.config.nil?
        Rails.application.config.eager_load_namespaces.each(&:eager_load!) if Rails.application.config.respond_to?(:eager_load_namespaces)
      end
    rescue Exception => err
      if Rake.application.options.trace
        raise
      else
        trace = Rails.backtrace_cleaner.clean(err.backtrace)
        error = (["Loading models failed!\nError occurred while loading application: #{err} (#{err.class})"] + trace).join("\n    ")
        raise error
      end
    end
    raise "Active Record was not loaded." unless defined? ActiveRecord
  end
Creating your own ERD task
The solution is to create our own task which loads the files and runs the :erd task.
To load the Sinatra application, create a file called boot.rb
. It's pretty simple, it just requires the gems and loads the Sinatra application.
# boot.rb
require "sinatra/base"
# ... other dependencies ...
require 'bundler'
Bundler.require(:default, ENV.fetch('APP_ENV', 'development').to_sym)
$LOAD_PATH.unshift(File.join(__dir__))
require 'application.rb' # the Sinatra application
# ... local libs ...
Next, create an :environment
 rake task to load the boot file. This allows other tasks which don't rely on the environment to run without bloat in the same way rails works.
# Rakefile
task :environment do
  require './boot'
  environment = ENV.fetch('APP_ENV', 'development') # or RACK_ENV, whichever you use
  if environment == 'development'
    load "rails_erd/tasks.rake"
  end
end
Now, we can create the ERD task. This task should mimic the erd:generate task within the rails-erd gem, but do the loading of our environment and models.
I split this into 2 parts:
- load the environment
 - generate the diagram
 
desc "Generate ERD"
task :erd => :environment do
  Rake::Task[:erd_generate].invoke
end
task :erd_generate => ["erd:check_dependencies", "erd:options"] do
  Dir['models/*.rb'].each { |m| require m }
  puts "Generating Entity-Relationship Diagram for #{ActiveRecord::Base.descendants.length} models..."
  require "rails_erd/diagram/graphviz"
  file = RailsERD::Diagram::Graphviz.create
  puts "Done! Saved diagram to #{file}."
  `open #{file}` # I found that I almost always open the file after running rake erd. (xdg-open on linux)
end
Now we can bundle exec rake erd
 to generate and open our entity relationship diagram.
$ bundle exec rake erd
Generating Entity-Relationship Diagram for 6 models...
Done! Saved diagram to erd.pdf.
Done!