目的
Ruby on Railsでよく使われている認証周りのgemライブラリーであるdeviseをつかってログイン機能を用いる。 deviseの標準ではemailに基づいてユーザを区別しているが、usernameでユーザを区別できるようにする。
環境
% lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic
% ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
% gem -v
2.7.7
% rails -v
Rails 5.2.1
新しいプロジェクトの生成
% rails new prac_devise --skip-bundle
% cd prac_devise
% cp -p Gemfile Gemfile.org
% vi Gemfile
Gemfileの中身を以下のように変更する。
% diff Gemfile.org Gemfile
17c17
< # gem 'mini_racer', platforms: :ruby
---
> gem 'mini_racer', platforms: :ruby
62c62
< gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
---
> #gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
63a64
> gem 'devise'
bundleを実行する。
% bundle install --path vendor/bundle
ダミーモデルの作成
今回はHomeコントローラーを作成し、indexにアクセスする際にはログインなし、showにアクセスする場合はログインありに設定する。このためにHomeコントローラーを作成する。
% rails g controller Home index show
このアプリケーションのトップページをHome#indexとする。
% vi config/routes.rb
中身に以下を加える。
root to: "home#index"
Deviseのインストール
このアプリケーションでdeviseが使えるように設定する。
% rails g devise:install
今回はUserモデルを認証対象のモデルとする。
% rails g devise User
devise用のviewを app/views/devise 以下にコピーする。
% rails g devise:views
% ls app/views/devise/
confirmations/ passwords/ sessions/ unlocks/
mailer/ registrations/ shared/
メールに記述するURLの設定
config/environments/development.rb に以下を加える。
# mailer setting
config.action_mailer.default_url_options = {host: 'localhost', port: 3000}
エラーメッセージを表示できるようにする。
app/views/layouts/application.html.erbに以下を加える。
〜省略〜
<body>
<p class="notice"><%= notice %></p> #この行を追加
<p class="alert"><%= alert %></p> #この行を追加
<%= yield %>
</body>
〜省略〜
User#showへのアクセスをログインした場合のみにする
app/controllers/home_controller.rb にフィルターをかける。
class HomeController < ApplicationController
before_action :authenticate_user!, only: :show #この行を追加
def index
end
〜省略〜
試してみる
% rails db:migrate
% rails s
(終了させるときは Ctrl + c)
識別キーをusernameに変更する
まず、usersテーブルにusernameを追加する。
% rails g migration add_username_to_users username:string
db/migrate/xxxxxxxxx_add_username_to_users.rb を編集し、usernameをインデックスとして使えるように以下を追加する。
class AddUsernameToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :username, :string
add_index :users, :username, unique: true #この行を追加
end
end
上記の変更を反映させる。
% rails db:migrate
識別キーをusernameに変更する。 config/initializers/devise.rbに以下の行を加える。
〜 省略 〜
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
# config.authentication_keys = [:email]
config.authentication_keys = [:username] #この行を追加
〜 省略 〜
ログイン(sign in)、ユーザ登録(sign up)、情報変更のページでusernameを入力できるように変更する。
ログインページ(app/views/devise/sessions/new.html.erb)の編集。
変更前
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
変更後
<%= f.label :username %><br />
<%= f.email_field :username, autofocus: true %>
ユーザ登録ページ(app/views/devise/registrations/new.html.erb) の編集。
変更前
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
変更後
<%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %>
情報変更のページ(app/views/devise/registrations/edit.html.erb)の編集。
変更前
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
変更後
<%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %>
usernameにvalidateを設定およびemailを利用しないことを設定する。
app/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
# この行以下を追加する
# usernameの制約
validates :username,
uniqueness: {case_sensitive: :false},
length: {minimum: 4, maximum: 20},
format: {with: /\A[a-z0-9]+\z/, message: "ユーザ名は半角英数字です"}
# emailを識別キーとして使わない場合の処理
def email_required?
false
end
def email_changed?
false
end
def will_save_changed_to_email?
false
end
# 追加ここまで
end
strong_parameterの設定
Ruby on Rails4よりStrong Parameterという仕組みが導入されている。これの設定が必要。 app/controllers/application_controller.rb に以下を加える。
# deviceのコントローラーのときに、下記のメソッドを呼ぶ
before_action :configure_permitted_parameters, if: :devise_controller?
protected
# usernameを追加する 参考:https://github.com/plataformatec/devise#strong-parameters
def configure_permitted_parameters
devise_parameter_sanitizer.permit :sign_up, keys: [:usrname]
devise_parameter_sanitizer.permit :account_update, keys: [:username]
end
試してみる
% rails db:migrate
% rails s
(終了させるときは Ctrl + c)