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