deviseでログイン前にapiリクエストしたときにカスタマイズjsonを返したいときのカスタマイズ方法です。
CustomFailureクラスを作成
Devise::FailureApp
を継承したCustomFailure
を作成します。respondメソッドをオーバーライドしてcontent typeがapplication/jsonだったらjson返すように設定しました。
lib/custom_failure.rb
class CustomFailure < Devise::FailureApp def respond if request.content_type == "application/json" self.status = 401 self.content_type = "application/json" self.response_body = { result: false, message: I18n.t('devise.failure.unauthenticated'), error_code: Constant::ApiErrorCode::UNAUTHENTICATED }.to_json elsif http_auth? http_auth elsif warden_options[:recall] recall else redirect end end end
respondメソッドにelsifでrequestのcontent_typeがapplication/jsonだったらという条件分岐を加えればOKですね!
devise/failure_app.rb at master · plataformatec/devise · GitHub
libの読み込み設定
libをはじめに読み込まれるように設定します。
config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
確認方法です。
deviseの設定に加える
deviseの設定に加えればOKです!
config/initializers/devise.rb
config.warden do |manager| manager.failure_app = CustomFailure end
Rspec
テストも追加してみました!libのテストをするときは
rails_helper.rb
require File.expand_path('../../config/environment', __FILE__)
が記述されているか確認してください!
また該当specファイルでrequireしましょう!
spec/lib/custom_failure_spec.rb
require 'rails_helper' require 'custom_failure' RSpec.describe 'lib/CustomFailure', type: :request do describe 'POST /api/v1/users/update_setting.json' do let(:request_header) do { 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' } end let(:user) do '{"user_email": "test@test.com", "user_token": "dammy", "email": "change@test.com"}' end before do @user = create(:user, email: "test@test.com", authentication_token: "dammy") end context "認証前にリクエスト" do before do post api_v1_users_update_setting_path(format: :json), user, request_header end it "401を返す" do expect(response).to have_http_status(401) end it "application/jsonで返す" do expect(response.content_type).to eq('application/json') end it "JSONに含まれるキーが適切である" do result = JSON.parse(response.body) expect(result).to have_key('result') expect(result).to have_key('message') expect(result).to have_key('error_code') end it "レスポンスパラメータが適切である" do body = JSON.parse(response.body) expect(body["result"]).to eq false expect(body["message"]).to eq I18n.t('devise.failure.unauthenticated') expect(body["error_code"]).to eq 1 end end end end
コメントを残す