はじめに
この記事ではdevise token authでのjsonの出力をactive_model_serializer
gemを使って整形する手順を解説するわ。実際の開発中に少し詰まったことを元にしているからゴールとして"ユーザーのログイン成功時に返されるjsonをserializerで整形する"を設定するわ。他のアクション後に返されるjsonにも応用できるように心掛けるから安心しなさい。
devise関連の導入まで含めちゃうと長くなるからそこは割愛するわ、ごめんなさいね。
準備するわよの巻
まずはgemのインストールから始めるわ。
gem 'active_model_serializers'
bundle install
これでactive_model_serializersのインストールが完了したわ。
このgem自体の説明は他の記事に譲るとしてまずは設定をするわ。
設定用のconfig/initializers/ams.rb
ファイルを手動で追加しなさい。
ActiveModel::Serializer.config.adapter = :json_api
この部分では出力するjsonのフォーマットを指定しているわ。オプションの詳しい説明についてはこちらの記事に詳しいわ。
Railsのactive_model_serializerについて学ぶ_100DaysOfCodeチャレンジ10日目(Day_10:#100DaysOfCode)
ここではjson_api
を指定したけど、あなたの好きなように設定しなさい。
さて、次はいよいよserializerのファイルを作っていくわよ。
rails generate serializer User
最後のUser
の部分は整形したいモデル名を指定することね。このコマンドでapp/serializers/user_serializer.rb
ファイルが作成されたわ、早速いじいじしちゃいましょう。
class UserSerializer < ActiveModel::Serializer
attributes :id, :name, :nickname, :image, :confirmed_at, :updated_at
end
ここではjsonで返すモデルのカラムを指定しているわ。他にも色々設定できるけど適宜自分で調べなさい、頑張ることね。
本題に入るわよの巻
ここまでで準備は完了よ、configに追加した設定を読み込ませるためにこのあたりで一旦サーバを再起動しておくことね、ん?もうやった? 良い子ね、クマちゃんのビスケットをあげるわ。
さて、まず見て欲しいものがあるの、serializerで整形をしない場合のログイン成功時に返されるjson(ログインに成功したユーザーの情報)よ。
続いて同じjsonをserializerで整形した場合よ。
データが構造化されているのと設定したカラムのみが出力されていることが分かるわね。
ちなみに下は
class Api::V1::UsersController < ApplicationController
def show
@user = User.find(params[:id])
render json: @user, serializer: UserSerializer
end
end
こんな感じのコードよ。
見ての通り、deviseの方のjsonも整形しないとアプリケーション全体として返すjsonのフォーマットに統一性が取れないことが分かるわ。これはフロント側としても混乱するしメンテナンス性も大きく損なうわ。
でも、自分で一から書くアクションなら上のコードみたいに簡単に実装できるんだけどdeviseは内部で勝手にやってくれるから分かりづらいわよね。
そこで今回は
- コントローラを継承する
- そこで各アクションごとのレンダリングメソッドをオーバーライドしてjsonをserializerで整形する
という手順でdeviseで返されるjsonの整形をするわ。
コントローラの継承をするわよ編
今回はログイン時のjsonを整形したいということで、ログイン時に呼ばれるアクションは
devise_token_auth/sessions#create
よ。ということで
devise_token_auth/sessions
コントローラを継承するわ。
class Api::V1::Auth::SessionsController < DeviseTokenAuth::SessionsController
end
新しく作ったコントローラが参照されるようにルーティングも変更よ。
私の場合は
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :users, only: [:show]
mount_devise_token_auth_for 'User', at: 'auth', controllers: {
registrations: 'api/v1/auth/registrations',
# ここの部分ね
sessions: 'api/v1/auth/sessions'
}
end
end
end
さて、準備が整ったところでさっきの手順の2の太字になっている各アクションごとのレンダリングメソッドの説明をするわ。出力を制御する、と聞いて最初に対象のアクションをそのままオーバーライドすることを考えた子も多いと思うの。でも、出力だけを変えたいのにいちいち大元のアクションメソッドをオーバーライドするのは面倒じゃない?deviseちゃんでは特定のアクションで成功、失敗した時にjsonをレンダリングするメソッドが個別で用意されてるの。要は必要に応じてそこをいじればいいってわけね。
このメソッドちゃんたちの存在は公式ドキュメントに載ってるの。この記事で日本語訳してくださってる方がいるので貼っておくわ。
【翻訳】devise-auth-token公式ドキュメント
表を見れば分かる通り、今回私が整形したいのはログインの成功時のjsonよ。つまりレンダリングメソッドで言うとrender_create_success
ね。早速オーバーライドしちゃいましょう。
class Api::V1::Auth::SessionsController < DeviseTokenAuth::SessionsController
def render_create_success
render json: @resource, serializer: UserSerializer
end
end
ログインが成功した時のリソース、つまりuserの情報は@resourceで取得できるわ。これをserializerで整形すると...
この通り!jsonが構造化されてカラムも設定したものしか返されていないわ!
参考文献
情報が比較的少ない中で有益な記事の存在に助けられました。心よりの感謝を申し上げます。