Railsで作ったシステムのER図を日本語で出してほしいと言われたときにやったこと

Ruby on Railsを使った開発をしていると「システムのER図が欲しい」といったお願いされることがあります。

Railsを使っているのであれば、[rails-erd](https://github.com/voormedia/rails-erd/tree/master) というRubyGemを使うことで簡単にER図を出力できます。

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

rails-erdで出力されるER図はEntityもAttributeも全て英語です。

![erd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60996/96fe287e-0c02-5af4-4c64-d9bc974b1f7e.png)

提出先がエンジニアである場合や、普段からモデル名を使ったコミュニケーションをしている場合であればこのままでもなんとかなるかもしれません。

一方、相手がビジネスサイドのメンバーである場合や、普段はモデルを日本語変換してコミュニケーションしている相手の場合はこのER図をそのまま出しても困惑されてしまいます。

そこで、今回はなんとかしてEntity・Attributeを日本語化できないか検討しました。結論とそこに至った過程をメモしておきます。

## 結論

結論としては、`rails-erd` の下記ファイルを直接編集することで日本語化することができました。

![erd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60996/877468bc-0439-ac22-28c7-826ba13cb800.png)

Railsのi18nに対応して、モデル名やカラム名の日本語化に対応していることが前提ですのでご注意ください。

### 変更ファイル

https://github.com/voormedia/rails-erd/blob/master/lib/rails_erd/diagram/templates/node.html.erb

### 変更点

```diff
 <% if options.orientation == :horizontal %>{<% end %>
 <table border="0" align="center" cellspacing="0.5" cellpadding="0" width="<%= NODE_WIDTH + 4 %>">
-  <tr><td align="center" valign="bottom" width="<%= NODE_WIDTH %>"><font face="<%= FONTS[:bold] %>" point-size="11"><%= entity.name %></font></td></tr>
+  <tr><td align="center" valign="bottom" width="<%= NODE_WIDTH %>"><font face="<%= FONTS[:bold] %>" point-size="11"><%= entity.model.model_name.human %></font></td></tr>
 </table>
 <% if attributes.any? %>
 |
 <table border="0" align="left" cellspacing="2" cellpadding="0" width="<%= NODE_WIDTH + 4 %>">
 <%   attributes.each do |attribute| %>
-  <tr><td align="left" width="<%= NODE_WIDTH %>" port="<%= attribute %>"><%= attribute.name %> <font face="<%= FONTS[:italic] %>" color="grey60"><%= attribute.type_description %></font></td></tr>
+  <tr><td align="left" width="<%= NODE_WIDTH %>" port="<%= attribute %>"><%= entity.model.human_attribute_name(attribute.name) %> <font face="<%= FONTS[:italic] %>" color="grey60"><%= attribute.type_description %></font></td></tr>
 <%   end %>
 </table>
 <% else %>
```

## 結論に至るまでの過程

### rails-erd以外の既存ツールを検討

DBスキーマを出力するツールは `rails-erd` に限らずいくつか存在します。それらのツールを使うことで簡単に解決ができないか検討しました。

しかし、多くのツールにおいて、日本語化をするためにはDBスキーマの物理名と論理名(日本語)の対応付けを別途行う必要があります。

Railsで作られたアプリであれば大抵の場合、i18nで既に日本語定義を終えているはずなので、日本語のER図を出すためだけに再度対応付けを行うのは避けたいところです。

このため、やはり `rails-erd` を用いてER図を出力する方向で検討することにしました。

### rails-erdにおいてER図のEntity・Attributeに該当する箇所を探す

ファイル名からあたりを付けつつ、適宜 `binding.debugger` を埋め込んでコマンドを実行してみることで、出力を行っているファイルを見つけ出します。

今回の場合は、前述の通り `rails_erd/diagram/templates/node.html.erb
` というERBファイルにたどり着きました。

https://github.com/voormedia/rails-erd/blob/master/lib/rails_erd/diagram/templates/node.html.erb

### ERBファイル内で参照できる変数・その変数メソッドを探る

このERBファイルを読んで、使えそうな変数を見つけます。 `entity` や `attribute` という変数が存在するので、これらは使えそうということがわかります。

このERBファイル内に `<%= binding.debugger %>` を埋め込んで、 `entity` や `attribute` がどのクラスのオブジェクトなのか確認します。

```ruby
entity.class.name #=> "RailsERD::Domain::Entity"

attributes.class.name #=> "Array"
attributes.first.class.name #=> "RailsERD::Domain::Attribute"
```

namescopeをたどると、EntityとAttributeは次のファイルに定義されているクラスのインスタンスであることがわかります。

https://github.com/voormedia/rails-erd/blob/master/lib/rails_erd/domain/entity.rb

https://github.com/voormedia/rails-erd/blob/master/lib/rails_erd/domain/attribute.rb

このうち、 `entity.rb` には `model` という `attr_reader` が定義されているので、これがおそらくActiveRecordのインスタンスだろうと推測しました。実際に試してみます。

```ruby
entity.model #=> ActiveStorage::Attachment(id: integer, name: string, record_type: string, record_id: integer, blob_id: integer, created_at: datetime)

# 何回かcontinueして再度実施
entity.model #=> Announcement(id: integer, title: string, body: text, created_at: datetime, updated_at: datetime)
```

たまたま最初のクラスが `ActiveStorage::Attachment` だったので、何回かcontinueすることで `entity` に入るオブジェクトがActiveRecordのインスタンスとなることを確認できました。

あとはRailsのi18n機能のメソッドを使うことで日本語化できます。

## おわりに

今回は、RubyGemの中身を読み解いてソースコードを一部変更することで目的を達成しました。

できればPull Requestを出して、コマンドオプション等で簡単に出力モードを切り替えられるようにできるとより便利なのですが、それは時間のある時に対応したいと思います。