I wanted to develop the front-end server and the back-end server separately. I wrote CRUD processing with login function in Vue.js and Rails (API mode).
Ruby: 2.6.5 Ruby on Rails 6.0.3
rails _6.0.3_ new devise_token_auth_api --api -d postgresql
cd devise_token_auth_api
rails db:create
Gemfile
gem "devise"
gem "devise_token_auth"
gem "rack-cors"
bundle install
rails g devise:install
rails g devise_token_auth:install User auth
config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'localhost:8080'
    resource '*',
      headers: :any,
      expose: ['access-token', 'expiry', 'token-type', 'uid', 'client'],
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
config/initializers/devise_token_auth.rb
DeviseTokenAuth.setup do |config|
  config.change_headers_on_each_request = false
  config.token_lifespan = 2.weeks
  config.token_cost = Rails.env.test? ? 4 : 10
end
app/models/user.rb
class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  include DeviseTokenAuth::Concerns::User
end
rails db:migrate
config/routes.rb
Rails.application.routes.draw do
  namespace :v1 do
    mount_devise_token_auth_for "User", at: "auth"
  end
end
This time I will use Postman. Please refer to the following URL for how to use Devise_token_auth. https://devise-token-auth.gitbook.io/devise-token-auth/usage
HTTP method: POST
URL: http://localhost:3000/v1/auth/
Body: email, password

HTTP method: POST
URL: http://localhost:3000/v1/auth/sign_in
Body: email, password

HTTP method: DELETE
URL: http://localhost:3000/v1/auth/sign_in
Body: uid, access-token, client
During the sign-in process, you can see the required parameters in the Headers tab.

vue create frontend
*Default ([Vue 2] babel, eslint)choose
cd frontend
yarn add axios
cd ..
cd frontend
yarn serve
frontend/src/App.vue
<template>
  <div id="app">
    <h3>Post to the bulletin board</h3>
    <div v-if="client === ''">
      <div>
        <h1>SignUp</h1>
        <label for="email">email</label>
        <input id="email" type="email" v-model="email" />
        <label for="password">password</label>
        <input id="password" type="password" v-model="password" />
        <button @click="signup">sign up</button>
      </div>
      <div>
        <h1>SignIn</h1>
        <label for="email">email</label>
        <input id="email" type="email" v-model="email" />
        <label for="password">password</label>
        <input id="password" type="password" v-model="password" />
        <button @click="signin">SignIn</button>
      </div>
    </div>
  </div>
</template>
<script>
import axios from "axios";
export default {
  data() {
    return {
      name: "",
      email: "",
      password: "",
      uid: "",
      access_token: "",
      client: "",
      title: "",
      content: "",
      tasks: [],
      comment: "",
      posts: [],
    };
  },
  methods: {
    signup() {
      axios
        .post("http://localhost:3000/v1/auth", {
          email: this.email,
          password: this.password,
        })
        .then((response) => {
          localStorage.setItem(
            "access-token",
            response.headers["access-token"]
          );
          localStorage.setItem("client", response.headers["client"]);
          localStorage.setItem("uid", response.headers["uid"]);
          this.access_token = response.headers["access-token"];
          this.client = response.headers["client"];
          this.uid = response.headers["uid"];
        });
    },
    signin() {
      console.log(this.email);
      console.log(this.password);
      axios
        .post("http://localhost:3000/v1/auth/sign_in", {
          email: this.email,
          password: this.password,
        })
        .then((response) => {
          console.log(response);
          localStorage.setItem(
            "access-token",
            response.headers["access-token"]
          );
          localStorage.setItem("client", response.headers["client"]);
          localStorage.setItem("uid", response.headers["uid"]);
          this.access_token = response.headers["access-token"];
          this.client = response.headers["client"];
          this.uid = response.headers["uid"];
        });
    },
    signout() {
      console.log(this.uid);
      console.log(this.access_token);
      console.log(this.client);
      axios
        .delete("http://localhost:3000/v1/auth/sign_out", {
          test: { test: "test" },
          headers: {
            uid: this.uid,
            "access-token": this.access_token,
            client: this.client,
          },
        })
        .then((response) => {
          console.log(response);
          this.access_token = "";
          this.client = "";
          this.uid = "";
          localStorage.removeItem("uid");
          localStorage.removeItem("access-token");
          localStorage.removeItem("client");
        });
    },
  },
};
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

rails g controller v1/tasks
rails g model Task
db/migrate/YYYYMMDD_create_tasks.rb
class CreateTasks < ActiveRecord::Migration[6.0]
  def change
    create_table :tasks do |t|
      t.string :title
      t.text :content
      t.references :user
      t.timestamps
    end
  end
end
rails db:migrate
config/routes.rb
Rails.application.routes.draw do
  namespace :v1 do
    resources :tasks
    mount_devise_token_auth_for 'User', at: 'auth'
  end
end
app/controllers/v1/tasks_controller.rb
class V1::TasksController < ApplicationController
  
  before_action :set_task, only: [:show]
  before_action :authenticate_v1_user!
  def index
    tasks = Task.where(user_id: @current_v1_user.id)
    render json: tasks
  end
  def create
    user = User.find_by(email: params[:uid])
    task = Task.new(title: params[:title], content: params[:content], user_id: user.id)
    task.save
  end
  def show
    render json: @task
  end
  def update
  end
  def destroy
    task = Task.find(params[:id])
    task.destroy
    render json: true
  end
  private
  def set_task
    @task = Task.find(params[:id])
  end
end
frontend/src/App.vue
<template>
  <div id="app">
    <div v-if="client === ''">
      <div>
        <h1>SignUp</h1>
        <label for="email">email</label>
        <input id="email" type="email" v-model="email" />
        <label for="password">password</label>
        <input id="password" type="password" v-model="password" />
        <button @click="signup">SignUp</button>
      </div>
      <div>
        <h1>SignIn</h1>
        <label for="email">email</label>
        <input id="email" type="email" v-model="email" />
        <label for="password">password</label>
        <input id="password" type="password" v-model="password" />
        <button @click="signin">SignIn</button>
      </div>
    </div>
    <div v-if="client !== ''">
      <div>
        <h1>Task</h1>
        <button @click="signout">SignOut</button>
        <div v-for="task in tasks" :key="task.id">
          Task:{{ task.id }}, {{ task.title }}, {{ task.content }}
          <button @click="find_task(task.id)">task_find</button>
          <button @click="delete_task(task.id)">Delete</button>
        </div>
      </div>
      <div>
        <h3>Task</h3>
        <label for="task">task</label>
        <input id="task" type="text" v-model="title" />
        <label for="content">content</label>
        <input id="content" type="text" v-model="content" />
        <button @click="create_task">Create_Task</button>
      </div>
    </div>
  </div>
</template>
<script>
import axios from "axios";
export default {
  data() {
    return {
      name: "",
      email: "",
      password: "",
      uid: "",
      access_token: "",
      client: "",
      title: "",
      content: "",
      tasks: [],
      comment: "",
      posts: [],
    };
  },
  methods: {
    signup() {
      axios
        .post("http://localhost:3000/v1/auth", {
          email: this.email,
          password: this.password,
        })
        .then((response) => {
          localStorage.setItem(
            "access-token",
            response.headers["access-token"]
          );
          localStorage.setItem("client", response.headers["client"]);
          localStorage.setItem("uid", response.headers["uid"]);
          this.access_token = response.headers["access-token"];
          this.client = response.headers["client"];
          this.uid = response.headers["uid"];
          this.all_tasks();
        });
    },
    signin() {
      console.log(this.email);
      console.log(this.password);
      axios
        .post("http://localhost:3000/v1/auth/sign_in", {
          email: this.email,
          password: this.password,
        })
        .then((response) => {
          console.log(response);
          localStorage.setItem(
            "access-token",
            response.headers["access-token"]
          );
          localStorage.setItem("client", response.headers["client"]);
          localStorage.setItem("uid", response.headers["uid"]);
          this.access_token = response.headers["access-token"];
          this.client = response.headers["client"];
          this.uid = response.headers["uid"];
          this.all_tasks();
        });
    },
    signout() {
      console.log(this.uid);
      console.log(this.access_token);
      console.log(this.client);
      axios
        .delete("http://localhost:3000/v1/auth/sign_out", {
          test: { test: "test" },
          headers: {
            uid: this.uid,
            "access-token": this.access_token,
            client: this.client,
          },
        })
        .then((response) => {
          console.log(response);
          this.access_token = "";
          this.client = "";
          this.uid = "";
          localStorage.removeItem("uid");
          localStorage.removeItem("access-token");
          localStorage.removeItem("client");
        });
      this.tasks = [];
    },
    all_tasks() {
      axios
        .get("http://localhost:3000/v1/tasks", {
          headers: {
            uid: this.uid,
            "access-token": this.access_token,
            client: this.client,
          },
        })
        .then((response) => {
          console.log(response.data);
          this.tasks = response.data;
        });
    },
    find_task(task_id) {
      axios
        .get(`http://localhost:3000/v1/tasks/${task_id}`, {
          headers: {
            uid: this.uid,
            "access-token": this.access_token,
            client: this.client,
          },
        })
        .then((response) => {
          console.log(response);
          this.task = response.data;
        });
    },
    create_task() {
      console.log(this.uid);
      console.log(this.access_token);
      console.log(this.client);
      axios
        .post("http://localhost:3000/v1/tasks", {
          uid: this.uid,
          "access-token": this.access_token,
          client: this.client,
          title: this.title,
          content: this.content,
        })
        .then((response) => {
          console.log(response);
          this.all_tasks();
        });
    },
    delete_task(task_id) {
      axios
        .delete(`http://localhost:3000/v1/tasks/${task_id}`, {
          headers: {
            uid: this.uid,
            "access-token": this.access_token,
            client: this.client,
          },
        })
        .then((response) => {
          console.log(response);
          this.all_tasks();
        });
    },
  },
};
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
GitHub
https://github.com/yodev21/devise_token_auth_app
Try implementing CRUD with login function when front end and back end are separated There were many addictive points and it was an opportunity to learn.
There are still many improvements and things I would like to try, so I would like to focus on the following in the future. ・ Data acquisition function across multiple tables ・ Introduction of Vue Router ・ Introduction of Vuex
[Rails] use devise token auth devise-token-auth
Recommended Posts