ActiveRecord ERDの代わりを求めて

いろいろ言われることはあるけれど、何はともあれ ActiveRecord はエコシステムの強力さが魅力。最近はあんまりやってなかったけど動くコードでモデリングするという方法を採用することがあって、その際に使えるのがコレ。

amatsuda/erd: A Rails engine for drawing your app's ER diagram

今回は ActiveRecord 以外の環境でこれに近いことができないかと思い探してみたところ、以下の組合せでそれなりに実現できそうということが分かった。

  1. PostgreSQL + schema dump + sql_graphviz ( Python )
  2. rom-sql + rom_sql_graph ( Ruby )

あくまでそれなりではあるけど。Rails + ActiveRecord から距離を置くことは実現できている。

sql_graphviz ( Python )

rm-hull/sql_graphviz: Generates graphviz commands to graphically display tables and show foreign key links.

SQL を dot 言語に変換するアプローチ。要 Python. これなら DDL としての SQL があればなんとかなるので、ORM にも開発言語にも依存しない。

本当は Graphviz 本家に Java で動くものがあるんだけど、

Sql2Dot

これはどうにも思ったような動作をしなかった。対応している SQL にいろいろ制限があるのかもしれない。

sql_graphviz を手元で試したところ、SQLite 3 の .schema で出力した SQL では table 情報は出力できるが relation を追うことができなかったため、目的を果たすことができなかった(table 情報を出力したかったわけではない)。

PostgreSQL の schema dump の場合は意図通りに relation を辿って graph を生成することができたが、生成された dot の label に各 column の詳細な情報が含まれてなかなかゴツイ graph になってしまうので、entity が多くなると ER 図としては結構きつそうに見える。

とは言えシンプルな Python スクリプトなので、label に生成される HTML をカスタマイズすればよいだけとも言える。例えば以下のような感じ。

  def field_act(s, loc, tok):
      fieldName = tok[0].replace('"', '')
-     fieldSpec = html.escape(' '.join(tok[1::]).replace('"', '\\"'))
+     fieldSpec = html.escape(tok[1].replace('"', '\\"'))

cf.

rom-sql + rom_sql_graph ( Ruby )

rom-sql は ROM.rb の SQL Adapter のことで、Hanami::Model の実質的な正体。つまりこの組み合わせは Hanami::Model に対しても使える。

気をつけないといけなのは 2020-12-12 時点で GitHub 上の README は master 時点のものでリリース済みの 0.2.0 のものとは異なり、

# First: create rom repository object
repo = UserRepository.new

# Next: create Rom::Sql::Graph object
graph = RomSqlGraph.generate(repo)

# Generate image or html file with your db associations
graph.generate_image
graph.generate_html

として ROM::Container ではなく Repository を RomSqlGraph に与えないといけない。

また、出力は entity 名だけになってしまうので、前述の sql_graphviz とは反対に情報量が減りすぎてしまうという問題がある。これも中を覗いて直していってもよいが多すぎる情報を削っていくより存在しない情報を追加していく方がつらそうではある。

ちなみに ROM.rb には Rails 向けのプロジェクトもある

Rails を ActiveRecord ではなく ROM.rb と組み合わせて Repository パターンを基本に実装することもできるようだ。多少コード量が増えても Rails で影響範囲の小さなコードを実現したいという場合に利用できるかもしれない。(もっとも、今なら新規に立ち上げられるなら素直に Hanami を使った方がよさそうだとは思うが。)

cf.

More