3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

devise token authのjsonをserializerで整形するわよの巻

Last updated at Posted at 2020-02-24

はじめに

この記事ではdevise token authでのjsonの出力をactive_model_serializer gemを使って整形する手順を解説するわ。実際の開発中に少し詰まったことを元にしているからゴールとして"ユーザーのログイン成功時に返されるjsonをserializerで整形する"を設定するわ。他のアクション後に返されるjsonにも応用できるように心掛けるから安心しなさい。
devise関連の導入まで含めちゃうと長くなるからそこは割愛するわ、ごめんなさいね。

準備するわよの巻

まずはgemのインストールから始めるわ。

Gemfile.
gem 'active_model_serializers'
bundle install

これでactive_model_serializersのインストールが完了したわ。
このgem自体の説明は他の記事に譲るとしてまずは設定をするわ。
設定用のconfig/initializers/ams.rb ファイルを手動で追加しなさい。

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ファイルが作成されたわ、早速いじいじしちゃいましょう。

app/serializers/user_serializer.rb
class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :nickname, :image, :confirmed_at, :updated_at
end

ここではjsonで返すモデルのカラムを指定しているわ。他にも色々設定できるけど適宜自分で調べなさい、頑張ることね。

本題に入るわよの巻

ここまでで準備は完了よ、configに追加した設定を読み込ませるためにこのあたりで一旦サーバを再起動しておくことね、ん?もうやった? 良い子ね、クマちゃんのビスケットをあげるわ。

さて、まず見て欲しいものがあるの、serializerで整形をしない場合のログイン成功時に返されるjson(ログインに成功したユーザーの情報)よ。

スクリーンショット 2020-02-24 16.16.37.png

続いて同じjsonをserializerで整形した場合よ。

スクリーンショット 2020-02-24 16.22.57.png

データが構造化されているのと設定したカラムのみが出力されていることが分かるわね。
ちなみに下は

app/controllers/api/v1/user_controller.rb
class Api::V1::UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    render json: @user, serializer: UserSerializer
  end
end

こんな感じのコードよ。
見ての通り、deviseの方のjsonも整形しないとアプリケーション全体として返すjsonのフォーマットに統一性が取れないことが分かるわ。これはフロント側としても混乱するしメンテナンス性も大きく損なうわ。
でも、自分で一から書くアクションなら上のコードみたいに簡単に実装できるんだけどdeviseは内部で勝手にやってくれるから分かりづらいわよね。
そこで今回は

  1. コントローラを継承する
  2. そこで各アクションごとのレンダリングメソッドをオーバーライドしてjsonをserializerで整形する

という手順でdeviseで返されるjsonの整形をするわ。

コントローラの継承をするわよ編

今回はログイン時のjsonを整形したいということで、ログイン時に呼ばれるアクションは
devise_token_auth/sessions#createよ。ということで
devise_token_auth/sessionsコントローラを継承するわ。

app/controllers/api/v1/auth/sessions_controller.rb
class Api::V1::Auth::SessionsController < DeviseTokenAuth::SessionsController 
  
end 

新しく作ったコントローラが参照されるようにルーティングも変更よ。
私の場合は

config/routes.rb
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ね。早速オーバーライドしちゃいましょう。

app/api/v1/auth/session_controller.rb
class Api::V1::Auth::SessionsController < DeviseTokenAuth::SessionsController 

  def render_create_success 
   render json: @resource, serializer: UserSerializer
  end 

end 

ログインが成功した時のリソース、つまりuserの情報は@resourceで取得できるわ。これをserializerで整形すると...

スクリーンショット 2020-02-24 16.48.03.png

この通り!jsonが構造化されてカラムも設定したものしか返されていないわ!

参考文献

情報が比較的少ない中で有益な記事の存在に助けられました。心よりの感謝を申し上げます。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?