🍔

packwerk下のModelでアノテーションを表示する

2024/05/08に公開

はじめに

こんにちは。春から担当チームが変更となりクリニックDX支援チームからバックエンド基盤チームに移動した山本です。前回の力作ブログ「packs-rails + packwerkでファットモデルを安全に分割する」は読んでいただけましたでしょうか?バックエンド基盤チームでは「プロダクト間のコード依存を解消し、プロダクトチームの生産効率向上に貢献する」をミッションに掲げ packwerkを使ったRailsアプリケーションのモジュラーモノリス化の推進を行っています。

annotationを使いたい

弊社のrailsプロジェクトでは annotate.gemを使ってModelにTableの項目名を表示しています。
アノテーションの例
アノテーションの例
このgemを利用することで、DBマイグレーション後にコメント形式でModelの先頭にカラム名が挿入されます。
しかし、packwerkで管理されているパッケージ下のModelではこの機能がうまく動作しない問題がありました。

調査

設定ファイルを確認する

annotate.gem をインストール後、 rails g annotate:install を行うことで、 lib/tasks/auto_annotate_models.rake が作成されます。デフォルトの設定項目を眺めていると model_dirroot_dir という項目が見つかりました。このあたりの設定を変更すれば対応できそうな匂いがします。

コードの調査と実験

コードを追っていくと、どうやら model_dirroot_dir はカンマ区切りに対応しているようです。
https://github.com/ctran/annotate_models/blob/v3.2.0/lib/annotate/annotate_models.rb#L632-L641
試しに、reservationパッケージを指定してみます。

# NOTE: only doing this in development as some production environments (Heroku)
# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
# NOTE: to have a dev-mode tool do its thing in production.
if Rails.env.development?
  require 'annotate'
  task :set_annotation_options do
    # You can override any of these by setting an environment variable of the
    # same name.
    Annotate.set_defaults(
      ()
      'model_dir' => 'app/models,packs/reservation/app/models',
      'root_dir'  => ',packs/reservation',
      ()
    )
  end

  Annotate.load_tasks
end

rake db:migrate を実行するとパッケージ下のModelやrspecにもアノテーションが設定されました🎉

汎用的に利用できるように改修

今のままだとパッケージが追加されるたびにrakeファイルの修正が必要となります。以下のようにコードを修正して自動的にパッケージ化のモデルを認識するようにしてみました。

# NOTE: only doing this in development as some production environments (Heroku)
# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
# NOTE: to have a dev-mode tool do its thing in production.
if Rails.env.development?
  require 'annotate'
  task :set_annotation_options do
    # You can override any of these by setting an environment variable of the
    # same name.
    defaults = {
      ()
      'model_dir' => 'app/models',
      'root_dir'  => '',
      ()
    }

    # パッケージ下のファイルにもアノテーションが効くよう調整する
    Packs.all.each do |pack|
      model_dir_path = "#{pack.name}/app/models"
      defaults['model_dir'] += ",#{model_dir_path}" if Dir.exist?(Rails.root.join(model_dir_path))
      defaults['root_dir'] += ",#{pack.name}"
    end

    Annotate.set_defaults(defaults)
  end

  Annotate.load_tasks
end

パッケージの一覧はPackwerkの機能を使うと Packs.all で取得できます。この内容を元に model_dirroot_dir に追加してみました。これで、パッケージの追加を意識すること無く自動でアノテーションが記載されます。

まとめ

  • packwerkを使うと、そのままではパッケージ下のファイルにannotate.gemが適用されない。
  • lib/tasks/auto_annotate_models.rake に書かれている設定を動的に作成することで対応できた。

annotate.gemはRailsプロジェクトで広く使われているGemだと認識しています。モジュラーモノリス化に合わせて設定してみてくださいね。

Linc'well, inc.

Discussion