🔶

Rails アプリのER図をMermaid形式で出力してするgemとFigJamで表示するプラグインを作りました

2024/01/08に公開

こんにちは。 わこーです。
タイトルが全てですが、以下2つを作ったので紹介です。

  1. Rails アプリのER図をMermaid形式で出力してするgem
  2. FigJamでMermaidを表示するプラグイン

この2つを組み合わせると以下のように便利になります。

「Rails アプリのER図をMermaid形式で出力してするgem」は
https://github.com/funwarioisii/rails_erd_mermaid

「FigJamでMermaidを表示するプラグイン」は
https://github.com/funwarioisii/figjam-mermaid-erd

で公開しています。
FigJamプラグインの方も公開申請を出しているので、申請が通れば手元に clone せずにご利用いただけると思います。

開発中に困ったことなどを↓にも書いています。
https://zenn.dev/funwarioisii/scraps/b04a65ec746c39

動機

チームでRailsアプリを開発していたとき、FigJamにモデル図を起こして設計の議論に役立てている同僚がいました。このときの体験がよく、いまも同様に書き出して、ウンウン唸るみたいなことをしています。しかし、モデルが増えると書き出すだけで時間がかかってしまい、だんだん面倒になってきていました。

そこで、 Railsアプリを開発しながら、シュッとFigJamで図にするというのを目指します。

関連作品

rails-erd

https://github.com/voormedia/rails-erd

dot形式で出力するなら rails-erd が最も知られていそうです。
最近はNotionも対応していたりで、Mermaidを使う機会が増えていると思うので、Mermaid二対応したいと思いました。

rails-mermaid_erd

https://github.com/koedame/rails-mermaid_erd

これでいいじゃんと思ったのですが、Mermaid記法で書かれたER図を取得するには一旦ブラウザを経由する必要があります。
とりあえず標準出力で実行結果を確認できると、他にも使いまわせそうだと思い、新しく gem を作ることにしました。

どういう仕組みか

rails_erd_mermaid

Rails での表現から Mermaid での表現に変換するための中間表現として IntermediateRepresentation という module を用意しています。
このなかにModel, Relation を表現する Struct を置き、これらに追加しています。

ActiveRecord::Base.descendants で得られた各モデルについて、カラムを追加したり、model.reflect_on_all_associations(:has_many) model.reflect_on_all_associations(:has_one) model.reflect_on_all_associations(:belongs_to) を見て関係性を書き起こしています。

https://github.com/funwarioisii/rails_erd_mermaid/blob/249a062fe1b56bfdbec019ca8d2992ac36d065f3/lib/rails_erd_mermaid/schema_to_mermaid.rb

bundle add rails_erd_mermaid --github="funwarioisii/rails_erd_mermaid"
bundle exec erd_mermaid --filetype="stdout"

でお試しいただけると思います。

figjam-mermaid-erd

Mermaid を各行読み、モデルの関係を拾っています。
https://github.com/funwarioisii/figjam-mermaid-erd/blob/4c710177915ba37c61b923730381e46a9771186f/code.ts#L102

本当は mermaid.parse(text) のような形でJSONが得られるとうれしいのですが、そういったAPIは現在開発中のようです。
https://github.com/mermaid-js/mermaid/tree/next/packages/parser

表示についてはかなり手を抜いています。いいアイデア募集中…。
他から参照される数が低いものを先に表示し、参照される数が多いものを少し話して表示するようにしています。
https://github.com/funwarioisii/figjam-mermaid-erd/blob/4c710177915ba37c61b923730381e46a9771186f/code.ts#L64-L77

https://github.com/funwarioisii/figjam-mermaid-erd/blob/4c710177915ba37c61b923730381e46a9771186f/code.ts#L23-L37

モデルの数が多いとFigJam上でガチャガチャする必要があるので、しょっぱいフィルターがついています
https://github.com/funwarioisii/figjam-mermaid-erd/blob/4c710177915ba37c61b923730381e46a9771186f/code.ts#L10-L14

これもターゲットのモデルを決めて深さ3くらいまで関連を出すとかにするといいのかなぁと思いますが、すぐにUser みたいな関係が多そうなやつが破滅させに来る未来しか見えない。

git clone https://github.com/funwarioisii/figjam-mermaid-erd
cd figjam-mermaid-erd
tsc

してツールバーよりプラグイン > 開発 > マニフェストからプラグインをインポート で manifest.json を選択すると使えます。
いい感じになったらPR送ってください;;

使ってみての感想

想定通り手書きが減ってうれしい

目的を達成できてよかった。
コマンドをポチポチするだけでFigJamにモデルが書かれるのは本当に楽でうれしい。

忘れていたrelationが出てきた

「あーこのモデルとこのモデルって関連あったなー」が早速あぶり出されて、考慮漏れが減りました。

stdout に外部キーの追加が出てきて pbcopy しづらい

$ bundle exec erd-mermaid --filetype=stdout
-- foreign_keys("comments")
   -> 0.0001s
-- foreign_keys("users")
   -> 0.0000s
...(結果が流れる)

となり、 bundle exec erd-mermaid --filetype=stdout | pbcopy とすると foreign_keys が含まれてしまうのです。
普通にファイル出力するときは出ないので Rails のログレベルな気がする?
直します…。

さいごに

それぞれ個別で使えるものです。どうぞご利用ください。

Discussion