< We're launched Liam ERD!

Learn More

schema.rb (Ruby on Rails)

If you’re using Ruby on Rails with ActiveRecord, in most cases you can automatically generate a useful ER diagram with Liam ERD. This page provides instructions and tips for generating an ER diagram in a Rails project.

ActiveRecord and db/schema.rb

When a Rails application manages migrations using ActiveRecord, the latest database structure is typically described in db/schema.rb.
Since db/schema.rb is recommended to be kept under version control, most projects will have it in their Git repository.

When using Liam CLI, specify --format schemarb and --input db/schema.rb as follows:

npx @liam-hq/cli erd build --format schemarb --input db/schema.rb

If the above command runs without issue, you should see an ER diagram generated.

Under the Hood

  • Liam CLI does not run an internal Ruby or Rails runtime. In other words, there is no Ruby process running under the hood.
  • Instead, it analyzes the content of db/schema.rb using the ruby/prism parser.

Trouble Shooting

If You Don’t Have db/schema.rb but Use db/structure.sql

If your Rails app doesn’t have db/schema.rb and instead uses db/structure.sql, here’s what you need to know.

For Rails 7.0 or Later

Somewhere under config (most commonly config/application.rb), you may have config.active_record.schema_format = :sql.
In such cases, running the dump command rails db:schema:dump will generate db/structure.sql.

If you want to obtain db/schema.rb, run the following in an environment with database access:

  • Change config.active_record.schema_format to :ruby and run rails db:schema:dump.
  • Alternatively, set the environment variable SCHEMA_FORMAT=ruby and run rails db:schema:dump.
    • For example: SCHEMA_FORMAT=ruby rails db:schema:dump

You can find sample implementations for this case on GitHub:

For Rails 6.1 or Earlier

To generate db/schema.rb in an environment with database access, set the environment variable SCHEMA_FORMAT=ruby and run rails db:schema:dump.

Using db/structure.sql Directly

If you’re using PostgreSQL, you can hand db/structure.sql directly to Liam CLI, and it should be parsed correctly.

In that case, the usage is the same as --format=postgres:

npx @liam-hq/cli erd build --format postgres --input db/structure.sql

When Associations Don’t Appear in the ER Diagram

warn

Please note that this approach can be somewhat complicated or may not work as expected.

Liam ERD’s Rails support is specialized for analyzing a standalone db/schema.rb file. It does not load the entire Rails project to read associations (such as has_many or belongs_to) directly from model files.

As a result, logical relationships (associations) not backed by foreign keys may not be reflected in the ER diagram.

In some Rails projects, associations are declared in models without foreign keys in the database. In this situation, you won’t see relationships in the ER diagram.

A potential workaround—though it requires additional setup—is to manually add add_foreign_key statements to db/schema.rb in your CI/CD process, then run Liam CLI. This way, the diagram will reflect those associations.

Below is a conceptual example code snippet showing how you might gather table names from models with belongs_to associations and add foreign keys manually (note: this example is illustrative and may need adjustments for production use):

# Prerequisite: The database must be accessible.
Rails.application.eager_load!
 
# Filter out models that have valid table_name
models_with_table = ActiveRecord::Base.descendants.select do |model|
  model.table_exists? && model.table_name.present?
end
# Map belongs_to associations to the corresponding referenced tables
assoc_map = models_with_table.map do |model|
  target_tables = model.reflect_on_all_associations(:belongs_to).map do |assoc|
    {
      table_name: assoc.class_name.safe_constantize&.table_name,
      column_name: "#{assoc.name}_id",
    }
  end.compact
  [model.table_name, target_tables]
end.to_h
# Generate add_foreign_key statements from the mapped relationships
# This is a simple example, so in practice you’d need to handle duplicates carefully
content = assoc_map.flat_map do |from_table, to_tables|
  to_tables.map { |to_table| %(add_foreign_key "#{from_table}", "#{to_table[:table_name]}", column: "#{to_table[:column_name]}") }
end.join("\n")
 
# Write or append this content to db/schema.rb in some way
File.open("db/schema.rb", "a") do |file|
  file.puts(content) if content.present?
end

By taking these steps to define foreign keys, you can produce an ER diagram closer to your expectations.

You can find sample implementations for this case on GitHub:

Pro Tips: Using Schemafile Instead of db/schema.rb

warn

Please note that this approach can be somewhat complicated or may not work as expected.

If your project uses a tool called Ridgepole, you might have a Schemafile instead of a db/schema.rb.

A Schemafile uses a DSL similar to what appears in db/schema.rb, so handing Schemafile directly to Liam CLI might work in some cases.

However, because users can write arbitrary Ruby code in a Schemafile, there may be scenarios where it isn’t fully compatible. If the output is not what you expect, consider generating a db/schema.rb using the methods described above (e.g., rails db:schema:dump) and then parsing that file.