kaede
Posted on August 13, 2023
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 なのでリダイレクトにはしないほうが自然
Posted on August 13, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.