【Vuex】Rails(devise_token_auth)+Vue.jsのSPAでサインアウトするサンプルコード


はじめに

Rails + Vue.jsのSPAでdevise_token_authを使ってサインアウトするサンプルコードを残します。

リクエストヘッダ情報の保存にVuexを活用しました。

環境

OS: macOS Catalina 10.15.1
Ruby: 2.6.5
Rails: 6.0.2.1
Vue: 2.6.10
vuex: 3.1.2
axios: 0.19.0

考え方

devise_token_authの公式ドキュメントの、sign_outのくだりにはこう書かれています。

Use this route to end the user's current session. This route will invalidate the user's authentication token. You must pass in uid, client, and access-token in the request headers.

リクエストヘッダにuid, client, access-tokenを含めて、DELETEリクエストを投げる必要があります。

このヘッダ情報を保管するためにVuexを使用します。

コード

store.js
import 'babel-polyfill'
import Vue from 'vue'
import Vuex from 'vuex'

import axios from 'axios'

Vue.use(Vuex)

const store = new Vuex.Store({

  state: {
//ヘッダの入れ物を用意。
    headers: null,
  },

  mutations: {

//サインイン時のレスポンスヘッダから情報を抜き出して保存しておく。
    signIn(state, payload) {
      state.headers = {
        "access-token": payload["access-token"],
        "client": payload["client"],
        "uid": payload["uid"],
      };
    },

//サインアウトしたらヘッダを空にしておく。
    signOut(state) {
      state.headers = null;
    },
  },

  actions: {
//paramsはemailなどのユーザー情報が入っていると思って下さい。
//(paramsへの情報の入れ方は今回割愛。)
    signIn(context, params) {
      axios
        .post('/api/v1/auth/sign_in', params)
        .then(function (response) {
//ここでレスポンスヘッダを受け取る。
          context.commit('signIn', response.headers);
      })
    },
    signOut(context) {
      axios
//ここでヘッダ情報を呼び出してDELETEリクエストに含める
        .delete('/api/v1/auth/sign_out', { headers: context.state.headers })
        .then(function () {
          context.commit('signOut');
      })
    },
  },
})

export default store

※本来はcurrentUserのようなstateも用意してすべきかと思いますが、話を超シンプルにするためにカットしています。

呼び出し方

Webpackのエントリーポイントとなるファイルで先程のstore.jsを読み込みます。

main.js
import Vue from 'vue'
import App from '../App.vue' 
import store from './store.js' //こちら

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    store, //こちら
    render: h => h(App)
  }).$mount()
  document.body.appendChild(app.$el)
})


store.jsを読み込めば任意の単一ファイルコンポーネント内にて、以下のようにしてsignOutを呼び出せます。

Anything.vue
<template>
  <div>
    <button @click="signOut">ログアウト</button>
  </div>
</template>

<script>

  export default {
    methods: {
      signOut() {
        this.$store.dispatch('signOut')
      }
    }
  }
</script>

※例では超シンプルに、サインアウトに必要な箇所のみ抜き出しています。

おわりに

最後まで読んで頂きありがとうございました

どなたかの参考になれば幸いです

参考にさせて頂いたサイト(いつもありがとうございます)