Published on

ワタシ的Next.js、Rails間のAPI通信ベストプラクティス

Authors

未完。日々メモを足してます。フルスタックな視点で最適なライブラリ選定、シリアライザーの責務、型の運用方法、ファイル構成を考察します。

前提としてJSON:APIを使っています。

1モデルにつきシリアライザーと型も1つずつ。テーブルとモデル自体の分化に注力することで、シリアライザーの分化を避ける

API毎に同じモデルでもシリアライザーを複数作って、それぞれのニーズ毎に最低限必要なattributesを都度用意する案に反対しています。

仮に通信料さえ莫大になる大規模サービスなら、attribuets最適化のメリットは大きいですが、それであっても、フロントからattributesを絞るリクエストを付与して動的に制御する形で対応するべきであり、やはりモデルに対し存在するシリアライザーと対応する型は常に1つにすべきと思っています。

というのも、ニーズ毎にattributesが違うときは、そもそもテーブル設計が適切でない結果であることが多く、そもそもテーブル設計の見直しで解消すべきだからです。例としてブログサービスで考えます。

記事一覧(index)を表示したいときと、本文(contentカラム)は不要です。title, descriptionカラムだけで十分であり、contentが必要なのは記事個別ページです。ここで提案したいのは、そもそもarticlesテーブルにcontentカラムを含むのではなく、ariticle_contentsテーブルを別に作って、そこにcontentを格納するべき、ということです。

というのも、シリアライザーで絞ったところでcontentカラムがarticlesテーブルに含まれていると、DBとサーバーの通信では容量の大きいcontentカラムがロードされてしまうので、ここに無駄が生じています。

selectで絞ればよい、という論はその通りですが、少なくともRailsではクエリ次第でカラムが無いかもしれない、という状況は開発時の認知負荷が大きすぎます。

テーブル分化のtips

articles/Article(テーブル名/モデル名)を分化したい場合、article_detail_contents/AritcleDetail::Contentやarticle_detail_hashtags/AritcleDetail::Hashtagという風にdetailという単語をよく使って、ネームスペースの衝突を防いでいます。(※Aritcleモデルが存在すると、Aritcle::Contentが作れないことを言っています。)

シリアライザー内でアソシエーションに干渉するようなattributeを実装しない

relashinshipsで繋いでアクセスするよりも、シリアライザー内のattributeとしてアソシエーションを参照する形で、attribuetsをリッチにしてrelationshipsを設けない実装を見ます。

この方法自体に反対ではありませんが、「1モデルにつき1シリアライザー案」では、シリアライザーが不特定多数のコントローラーから使い回され、アソシエーションへの参照が任意になるため、attributeに設けると該当アソシエーションへのクエリの発火が強制になるので、避けるべきと考えます。

一方で、目的の数だけシリアライザーを作る場合は、常にattributesを最適化できる・するべきであると思います。

参考文献