why
Kotlin で API を作った時、ログイン機能まで作らなかった。Rails では作って、認証認可に強くなりたい。
ライブラリ選定
devise という gem を使う。
一通り機能が揃っているらしい。
新規登録でお礼メールや、パスワードリセットなど。
https://github.com/heartcombo/devise#getting-started
devise 活用
devise をプロジェクトに入れる
https://github.com/heartcombo/devise#getting-started
bundle add devise
bundle add で Gemfile に書き込み
devise の設定を書き込む
rails generate devise:install
rails generate で設定を開始する。
設定値がデフォルトで、設定ファイルが生成される。
- config/initializers/devise.rb
- config/environments/development.rb
- config/locales/devise.en.yml
- config/routes.rb
など。
パスワードリセットのメールのリンク先などが設定できる。
User モデルと Migration ファイルの生成
devise を使って簡単に Model が作成できる。
rails generate devise User
invoke active_record
create db/migrate/20230813062406_devise_create_users.rb
create app/models/user.rb
invoke rspec
Migrations are pending. To resolve this issue, run:
bin/rails db:migrate RAILS_ENV=development
これで models/user.rb ができる
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
また、migration ファイルもできる
class AddDeviseToUsers < ActiveRecord::Migration[7.0]
def self.up
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
migration ファイルにはコメントアウトされている行もある
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
これらのコメントアウトを外すと、最後のログインの情報を保存したり、頻繁なログイン失敗をロックしたりできる。
schema
同様に schema.rb をみると users が追加されている
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
既存の bankTransaction コントローラーの Rspec にログインを導入する
bankTransaction でログインを入れる
rails_helper.rb に device の読み込み設定を記載
rspec を動かす時には、rails_helper が先に動く。
なので、rails_helper に設定を書いておけば、rspec で動いてくれる。
config.include FactoryBot::Syntax::Methods
config.include Devise::Test::IntegrationHelpers, type: :controller
config.include Devise::Test::ControllerHelpers, type: :controller
https://github.com/heartcombo/devise#test-helpers
実際に動かす
rspec --fail-fast を使うと、落ちたところで止まってくれるので便利。
class BankTransactionsController < ApplicationController
before_action :authenticate_user!
実装のコントローラーに認証がなかったので、コントローラーが動く前に、ログインしていなければリダイレクトに飛ばす処理を入れる
context 'ログインしているとき' do
before do
user_email = "kaede0902@gmail.com"
user = User.find_by(email: user_email) ||
FactoryBot.create(:user, email: user_email)
sign_in user
# spec/factories/bank_tranksactions.rb の内容が実行される
FactoryBot.create(:bank_transaction)
end
get リクエストの前に、指定のメールアドレスでユーザーを検索。
ユーザーがあればそのユーザーのインスタンスを取得。
ユーザーがなければそのユーザーを登録。
そしてそのユーザーでログイン。
ログインしている状態でコントローラーを叩く。
kaede0902@V bank_transactions_api % rspec --fail-fast
BankTransactionsController
ログインしているとき
GET #index
取引明細の口座番号が正しく取得できること
取引明細の金額が正しく取得できること
取引明細の明細名が正しく取得できること
POST #create
取引データが作成できること
Finished in 0.11026 seconds (files took 1.74 seconds to load)
4 examples, 0 failures
これでログイン認証した上で、API UT を動かせた!
伸び代
ログインしていない時の挙動をテストする。
API なのでリダイレクトにはしないほうが自然
Top comments (0)