①sorceryをインストール。
gem 'sorcery'
$ bundle exec rails g sorcery:install
class SorceryCore < ActiveRecord::Migration[6.0] def change create_table :users do |t| t.string :name, null: false t.string :email, null: false t.string :crypted_password t.string :salt t.timestamps null: false end add_index :users, :email, unique: true end end
$ bundle exec rails db:migrate
②APIのルーティングを設定。
Rails.application.routes.draw do root to: 'home#index' namespace :api, format: 'json' do resources :tasks resources :users end get '*path', to: 'home#index' end
③モデルを設定。
class User < ApplicationRecord authenticates_with_sorcery! has_many :tasks, dependent: :destroy validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] } validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] } validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] } validates :name, presence: true validates :email, uniqueness: true, presence: true end
④コントローラーを設定。
class Api::UsersController < ApplicationController def create user = User.new(user_params) if user.save render json: user else render json: user.errors, status: :bad_request end end private def user_params params.require(:user).permit(:email, :password, :password_confirmation, :name) end end
⑤vue-routerに登録画面のルーティングを設定してヘッダーにリンクを付ける。
import Vue from 'vue'; import Router from 'vue-router'; import store from '../store'; import TopIndex from '../pages/top/index'; import TaskIndex from '../pages/task/index'; import RegisterIndex from '../pages/register/index'; Vue.use(Router) const router = new Router({ mode: 'history', routes: [ { path: '/', component: TopIndex, name: 'TopIndex', }, { path: '/tasks', component: TaskIndex, name: 'TaskIndex', meta: { requiredAuth: true }, }, { path: '/register', component: RegisterIndex, name: 'RegisterIndex', }, ] }) export default router
<template> <header> <nav class="navbar navbar-expand navbar-dark bg-dark justify-content-between"> <span class="navbar-brand mb-0 h1">タスク管理アプリ</span> <ul class="navbar-nav"> <li class="nav-item active"> <router-link :to="{ name: 'RegisterIndex' }" class="nav-link" > ユーザー登録 </router-link> </li> </ul> </nav> </header> </template> <script> export default { name: "TheHeader", } </script> <style scoped> </style>
⑥登録画面を実装。
app/javascript/pages/register/index.vue
<template> <div id="register-form" class="container w-50 text-center" > <div class="h3 mb-3"> ユーザー登録 </div> <div class="form-group text-left"> <label for="name">ユーザー名</label> <input id="name" v-model="user.name" name="ユーザー名" type="text" placeholder="username" class="form-control" > </div> <div class="form-group text-left"> <label for="email">メールアドレス</label> <input id="email" v-model="user.email" name="メールアドレス" type="email" placeholder="test@example.com" class="form-control" > </div> <div class="form-group text-left"> <label for="password">パスワード</label> <input id="password" v-model="user.password" name="パスワード" type="password" placeholder="password" class="form-control" > </div> <div class="form-group text-left"> <label for="password_confirmation">パスワード(確認)</label> <input id="password_confirmation" v-model="user.password_confirmation" name="パスワード(確認)" type="password" placeholder="password" class="form-control" > </div> <button type="submit" class="btn btn-primary" @click="register" > 登録 </button> </div> </template> <script> export default { name: 'RegisterIndex', data() { return { user: { name: '', email: '', password: '', password_confirmation: '' } } }, methods: { register() { this.$axios.post('users', this.user) .then(res => { this.$router.push('/login') }) .catch(err => { console.log(err) }) } } } </script> <style scoped> </style>