- やること
- deviseを使う準備
- viewファイルの作成
- Userモデルを作成する
- 現時点でのルーティングを確認
- コントローラーを作成
- DBをのぞいてみる
- リポジトリ
- 次はFacebook認証を実装する
- 参考
やること
- devise gemを使ってRailsアプリに簡単なログイン認証を実装してみる
開発環境
deviseを使う準備
rails new
でRailsアプリの雛形を作成する。
データベースを指定していないので、デフォルトではsqlite3が使われる。
rails new omniauth-test
(今後、omniauthというgemを使ったSNS認証機能も実装する予定のため、ここではomniauth-testという名前にしている)
アプリが作成されたら移動。
cd omniauth-test
deviseをインストールするため、Gemfileの一番下に以下を追記。
gem 'devise'
bundle installする。(bundleと書いてもbunlde installが実行される)
bundle
deviseをGemfileに記述してインストールしたものの、まだこれでは使えない。 以下のコマンドで、deviseの基本機能をRailsアプリにインストールする。
bin/rails g devise:install
するとこんな画面が現れる。
Running via Spring preloader in process 99124 create config/initializers/devise.rb create config/locales/devise.en.yml =============================================================================== Some setup you must do manually if you haven't yet: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> 4. You can copy Devise views (for customization) to your app by running: rails g devise:views ===============================================================================
上からみていくと、まずdeviseの設定ファイルとロケールファイルが作成されている。
create config/initializers/devise.rb create config/locales/devise.en.yml
それ以下には、「初期設定はこうしてよね」と書いてるので、とりあえず言われるがままにやる。
config/environments/development.rb
# 以下を追記 config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
config/routes.rb
# 追記 root to: 'home#index'
※後でコントローラーとメソッドを実装します。
app/views/layouts/application.html.erb
<body> # 追記 <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <%= yield %> </body>
前準備が終わったので、一旦gitでコミットしておく。
git add . git commit -m "deviseを使う前準備完了"
viewファイルの作成
deviseが提供するコマンドで、ユーザー登録に関するviewファイルたちが生成される。ユーザー登録画面や、「パスワードを忘れましたか?」的な画面など、いろんなWEBアプリでよく見かけるやつ。
bin/rails g devise:views
実は、このコマンドを実行しなくても、deviseでログイン認証画面は表示される。 しかし、実際は登録画面をカスタマイズする場合がほとんどなので、上記コマンドを実行し、いろいろいじる。
Userモデルを作成する
ログインしてきたユーザーを保存するため、deviseの機能を持ったUserモデルを作成する。
bin/rails g devise User
通常のモデルを作成する場合は、rails g model User
などとするが、deviseの機能を受け継ぎたいので、deviseコマンドを入れている。
実行後、こんな画面が表示される。
invoke active_record create db/migrate/20200222031348_devise_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml insert app/models/user.rb route devise_for :users
作成されたapp/models/user.rb
を見てみると、deviseの機能(モジュール)が記述されているのがわかる。これは、deviseのコマンドでUserモデルを作成したため。
class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable end
デフォルトで有効になっているのは、次のモジュールたち。
モジュール | 機能 |
---|---|
database_authenticatable | ユーザー情報を保存するのにDBを使う |
registerable | ユーザーを登録、編集、削除できる |
recoverable | パスワードをリセットできる |
rememberable | Cookieにログイン情報を保存する |
validatable | メールアドレスとパスワードをバリデーションする |
コメントアウトされているこちらの部分は、デフォルトでは無効になっている。
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
モジュール | 機能 |
---|---|
confirmable | 登録されたemailに送信する |
lockable | ログインを数回したらロックする |
timeoutable | 一定期間でタイムアウトさせる |
trackable | ログイン時の情報を保存 |
omniauthable | OmniAuth gemと連携する |
たとえば、Facebook認証を実装したい場合、omniauthable を有効にする必要がある。
テーブルに保存される内容をチェック
マイグレーションファイルを見て、どんなカラムが作成されるか見てみる。
# frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[6.0] def change 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 ## 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 ## Confirmable # t.string :confirmation_token # t.datetime :confirmed_at # t.datetime :confirmation_sent_at # t.string :unconfirmed_email # Only if using reconfirmable ## 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 t.timestamps null: false end add_index :users, :email, unique: true add_index :users, :reset_password_token, unique: true # add_index :users, :confirmation_token, unique: true # add_index :users, :unlock_token, unique: true end end
emailアドレスや、暗号化されたパスワードが保存されている。
## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: ""
マイグレーションを実行
マイグレーションを実行する。
bin/rails db:migrate
データベースがsqlite3の場合、rails newをした時点でデータベースは作成されているので、マイグレーションだけでいい。
データベースとしてPostgresqlやMysqlなどを使用しているなら、db:create
でデータベースを作成する。
bin/rails db:create
現時点でのルーティングを確認
routes.rb
を見てみる。
Rails.application.routes.draw do devise_for :users root to: "home#index" end
devise_for
はこれまたdeviseが勝手に書いてくれてるもの。具体的にはbin/rails g devise User
をしたときに追記されている。
ここでは、ユーザー登録や編集に関係するページへのルーティングを自動で定義してくれている。
bin/rails routes
でルーティングを確認すると
Prefix Verb URI Pattern Controller#Action new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit user_password PATCH /users/password(.:format) devise/passwords#update PUT /users/password(.:format) devise/passwords#update POST /users/password(.:format) devise/passwords#create cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit user_registration PATCH /users(.:format) devise/registrations#update PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroy POST /users(.:format) devise/registrations#create
Devise::SesstionsController
という専用のコントローラーは作成していないが、devise/sessions#new
などと記述されている。
これは、deviseが定義しているもの。
一旦コミットする
Userモデルを作ったので、ここで一旦コミットしておく。
git add . git commit -m "モデル作成"
コントローラーを作成
いよいよ、ページを表示させるためコントローラーとビューファイルを作成する。
bin/rails g controller home index
homeコントローラーを作成し、indexアクションを定義している。 これは、ルーティングで設定したとおりにコントローラーとアクションを作っているだけ。
# routes.rb root to: "home#index"
「ルートパス(localhost:3000)にアクセスしたら、homeコントローラーのindexアクションが実行される」という意味。
作成されたapp/controllers/home_controller.rb
を次のように修正する。
class HomeController < ApplicationController #追記 before_action :authenticate_user!, only: :index def index end end
authenticate_user!
はdeviseが提供するメソッド。ログインしていない場合にアクセスしたら、ログイン画面にリダイレクトされる。「ログインしてからまた来てねー」みたいな感じ。
app/views/home/index.html.erb
に追記
<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> #追記 <%= current_user.email %>
current_user
は、deivseを入れると使えるようになるメソッド。
current_user.email
とすることで、ログインしているユーザーの、DBに保存された情報が参照できる。
参照するときには、カラム名を記述すればいい。current_user.name
など。
ビュー側だけではなく、コントローラーなどでも使用できる。
ちなみに、作成したモデル名がMemberモデルだったら、current_member
となる。
ここでは、ログインできたことがわかりやすくなるように、ログイン後は自分のemailを表示させるようにしている。
app/views/layouts/application.html.erb
を修正
共通のレイアウトに追記。
<body> # ここから <header> <nav> <% if user_signed_in? %> <%= link_to "logout", destroy_user_session_path, method: :delete %> <% else %> <%= link_to "sign up", new_user_registration_path %> <%= link_to "login", new_user_session_path %> <% end %> </nav> </header> # ここまで <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <%= yield %> </body>
if user_signed_in?
はdeviseが提供しているメソッドで、「あなた、ログインしてんの?」とif文で判断している。
ログインしていればtrueを返すため、if~elseまでのコードを実行する。
つまり、ログインしていると、logoutへのリンクが表示される。
ログインしていなければ、signupとloginへのリンクが表示される。
サーバーを起動して画面を確認
サーバーを起動すると
bin/rails s
こんな画面が表示される。
sign_up画面へいき、「example@example.com」で登録すると、
ビューファイルで記述したcurrent_user.email
が表示されているのがわかる。
ちなみに、登録したパスワードはdeviseが自動で暗号化してくれるので安心。
簡易的だが、これでdeviseを使ったログイン認証が実装できた。
DBをのぞいてみる
サインアップ時に入力したデータが、ちゃんとUsersテーブルに保存されているかチェックしてみる。 コンソールを開く。
rails c
以下コマンドを入力。
User.first
User.first
で、Userモデルの先頭のユーザーを参照できる。
=> #<User id: 1, email: "example@example.com", created_at: "2020-02-22 03:54:34", updated_at: "2020-02-22 03:54:34"> irb(main):002:0>
登録に使ったメールアドレス、example@example.comがしっかり保存されている。
リポジトリ
今回書いたコードはこちらです。
https://github.com/kotakanazawa/omniauth-test
次はFacebook認証を実装する
続き