Ruby on Rails の 5.2 から標準で入った Active Storage。
Rails 5.2 が公式リリースされる前から本番登用していたので、 使い始めてからそろそろ使用してから1年が経つ。
現在仕事で関わっているサービスでは Rails は APIサーバーとして運用しているが、 Acitve Storage をファイルを中央集権的に管理するように使ったことでとても幸せになれているのでその知見を書いておきたい。
APIサーバーとして Rails を使っていて、Active Storage の導入を考えている方はぜひ一度この使い方を検討してみてほしい、
※ この使い方に関しては、Active Storage に限らず carrierwave とかでも活かせるかもしれない。
Active Storage とは
Active Storage とはどんなものかは公式のドキュメントを見るほうが早いと思う。
Active Storage Overview — Ruby on Rails Guides
中央集権管理とは
これは造語的に使っているので、どんなものなのかを説明する。
マニュアル通り使うときっとこうなる
画像などのファイルを紐づけたいモデルに対して、Active Storage によるアップロード機構を付けていくことになるはずである。 そうなると、違うモデルにまたファイルを紐づけたいときには、同じことをそのモデルに対しても行うことになる。
一方で中央集権管理的とは
中央集権管理的とは、このように Active Storage と紐づくだけのモデルを1つ作り、他のモデルからこのモデルを参照するイメージ。
こうすることで、追加的にファイルを使いたいモデルができたとしても、Acitve Storage のファイルを管理しているモデルへの参照をつけるだけ。
これは、いつも通りの Rails の外部参照なのでなんの問題もなくできるのがよいところ。
中央集権管理のメリット
まず、Active Storage 特有の処理が1つのモデルに集約されるので見通しがだいぶ良い。
さらに、ユーザーがアップするファイルがここに集まっているので、監視がしやすい。
規約違反のものなどをチェックする必要のあるサービスには大きなメリットかもしれない。
また、同じファイルを複数のモデル・レコードで使い回せるのはよい。参照先の id を変えればすぐに参照を切り替えられる手軽さは大きい。 (中央集権管理していないと同様のファイルをアップロードし直さないとファイルを張り替えられない)
データの更新とファイルアップロードのタイミングがわかりやすい
もう1つメリットとしては、データの更新とファイルのアップロードのタイミングがわかりやすいという点。
マニュアル通りの場合
以下のような更新の仕方だと、通常の update と画像の変更のタイミングが違ってくる。
class Api::UsersController def update image_file = params[:image] @user = User.find(params[:id]) @user.update!(user_params) # ↓ ここで例外発生した場合どうする? @user.image.attach(image_file) end end
Rollback をするのか、画像だけアップロードに失敗したということにするのか決めれば問題ないのだが、 全てのモデルで同じ挙動をするかは実装者によってしまうので意図せぬバグを埋めてしまいそう。
中央集権管理の場合
画像をアップロードする処理とその他の update を分けられるのでよい。
class Api::ImagesController def create image_file = params[:image] @image = Image .create!(images_params) @image.image.attach(image_file) end end
上の変更が成功してから id を入れて普通の update 処理をすれば見通しが良くなる。
class Api::UsersController def update image_id = params[:image_id] @user = User.find(params[:id]) @user.update!(image_id: image_id) end end
まとめ
APIサーバーとして Rails を使っている場合、中央集権管理にしたほうがだいぶ見通しが良くなると思っている。
Rails で html まで返す従来のアプリケーションであれば、 それぞれのモデルに Active Storage を紐づけたほうが一回のリクエストで更新処理が行う都合上いい気がする。
しかし、APIサーバーとして運用しているのであれば、その限りではないはず。 あまり見ない使い方ではあるが、ぜひ一度検討してみると良いかもしれない。