[rails]既存のdevise を入れた後にdevise_token_authを追加、API化する時


deviseでCustomerモデルをすでに作っており、RailsもAPIモードで作っていないところから
devise_token_authを入れて、APIにも対応できるように奮闘した記録です。

まず最初にGemを追加

Gemfile
gem 'devise_token_auth'

インストール

僕はcustomerモデルで行っていたので

ターミナル
rails generate devise_token_auth:install Customer auth

※これでファイル生成がうまくいかなかった人は,

Gemfile
gem 'devise_token_auth', github: 'lynndylanhurley/devise_token_auth'

これで試してください

すでにdeviseでモデルを作っており、APIにも対応させる状況です

次に、マイグレーションファイルをいじります
このファイルを消します。deviseですでにcustomerモデルがあるので、これでマイグレーションをかけると怒られます

db/migrate/~_devise_token_auth_create_users.rb
# このマイグレーションファイルを消す
class DeviseTokenAuthCreateCistomers < ActiveRecord::Migration[6.0]
  def change
   ...
   ...
 end
end

既存のCustomerモデルにauthの分の追加を行います

rails g migration AddTokensToCustomers provider:string uid:string tokens:text

できたを次のように変更

db/migrate/20201212131408_add_tokens_to_customers.rb
class AddTokensToCustomers < ActiveRecord::Migration[6.0]
  def up
    add_column :customers, :provider, :string, null: false, default: 'email'
    add_column :customers, :uid, :string, null: false, default: ''
    add_column :customers, :tokens, :text
    Customer.reset_column_information
    Customer.find_each do |customer|
      customer.uid = user.email
      customer.provider = 'email'
      customer.save!
    end
    add_index :customers, [:uid, :provider], unique: true
  end

  def down
    remove_columns :customers, :provider, :uid, :tokens
  end
end

次にモデル(注意)

model/customer.rb
class Customer < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable
  # これがあるとconfirmableの新規登録確認メールが送られてこない
  #  これがないとAPIを叩いてもエラーが出る
  include DeviseTokenAuth::Concerns::User
...
 # include DeviseTokenAuth::Concerns::Userの対策
  # メールを送らせるための関数
  after_create :send_confirmation_email, if: -> { !Rails.env.test? && Customer.devise_modules.include?(:confirmable) }
  private
  def send_confirmation_email
    self.send_confirmation_instructions
  end
end

ルーティング設定

config/routes.rb
Rails.application.routes.draw do
  devise_for :customers, controllers: {
    sessions: 'customers/sessions'
  }
  resources :companies, only: [:show] do
    devise_for :customers, controllers: {
      registrations: 'customers/registrations'
    }
  end
  # 以下を追加
 # devise_for :customers よりも後に書くこと
  namespace :api do
    scope :v1 do
      mount_devise_token_auth_for 'Customer', at: 'auth'
    end
  end
  .....
  .....
end
config/initializers/devise_token_auth.rb

DeviseTokenAuth.setup do |config|
  config.enable_standard_devise_support = true
  config.default_confirm_success_url = "confirmed"

  config.change_headers_on_each_request = false
  config.token_lifespan = 1.month

  config.headers_names = {:'access-token' => 'access-token',
                          :'client' => 'client',
                          :'expiry' => 'expiry',
                          :'uid' => 'uid',
                          :'token-type' => 'token-type' }
end

最後に

app/controller/application_controller.rb
# コメントアウトする
# include DeviseTokenAuth::Concerns::SetUserByToken

完成