Deviseのインストール
Gemのインストール
gem 'devise'
bundle install
rails g devise:install
ユーザーモデルの作成(migrationファイルも含まれる)
rails g model hogehogeではなく、devise用のコマンドを利用する。
rails g devise user
$ rails g devise user
invoke active_record
create db/migrate/20190719114302_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
ここでroute,rbに自動的に追記されるdevise_forはログイン関係に必要なルーティングを一気に生成してくれるdeviseのヘルパーメソッド。
テーブルの作成
migrationファイルを編集して必要な情報を足す。
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
## Database authenticatable
t.string :name, null: false, unique: true, index: true
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
db作成。rails db:migrateでOK
bundle exec rake db:migrate
サーバーの再起動
$ rails s
必要ならテーブルに必要な入力項目を足す。
rails g migration AddNameToUser name:string
bundle exec rake db:migrate
routesを通す。
TechReviewSite::Application.routes.draw do
devise_for :users
resources :users, only: :show
resources :products, only: :show do
resources:reviews, only:[:new, :create]
collection do
get 'search'
end
end
root 'products#index'
end
ビューファイルの作成
通常のままだとviewフォルダ内にusers関係のファルダがないため変更可能にします。
rails g devise:views
app/views/users/sessions/new.html.erb
サインインページ等の編集をする。
これだけだと動かないのでconfigファイルを編集して以下をtrueへ変更。
config/initializers/divise.rb
#config.scoped_views = false
↓
config.scoped_views = true
ログインを強制する
コントローラに以下を追記してアクションを制限する。
before_action :authenticate_user!, only: :search
deviseのストロングパラメーターを追加する
通常、入力した情報はパラメーターとして受け取り、コントローラーのストロングパラメーターで制御できる。
deviseでログイン機能を実装した場合、ログイン時に送られてくるパラメーターを制限するストロングパラメーターは、deviseのGem内に記述されているため編集できない。
configure_permitted_parametersメソッドを用いて追加したいキーを指定する。
application_controller.rbにbefore_actionで記述する。
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:ストロングパラメーターを追加したいアクション名, keys: [:追加するキー])
end
具体例
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
end
end
controllerの作成
rails g controller users
デフォルトのコントローラーをオーバーライドする場合、
rails g devise:controllers users
+routesにも追記が必要
Deviseで使えるメソッド
after_sign_out_path_forメソッド
deviseでサインアウトしたあとのリダイレクト先を指定するメソッドとしてafter_sign_out_path_forがあります。このメソッドでは返り値にサインアウト後のリダイレクト先URLを指定します。deiviseのメソッドを上書きしている関係上resourceを引数に渡さなけらばならないので、resourceを引数に渡します。
def after_sign_out_path_for(resource)
'/users/sign_in' # サインアウト後のリダイレクト先URL
end
authenticate_user!
deviseをインストールすると、ログイン画面とサインアップ画面を自動で用意してくれます。authenticate_user!はdeviseをインストールすることで使えるメソッドです。ユーザーがログインしているかどうかを確認し、ログインしていない場合はログインページにリダイレクトします。通常、before_actionを合わせて使用します。before_actionのexceptやonlyオプションを組み合わせると特定のアクションを指定することもできます。
before_action :authenticate_user!, only: :new
devise_parameter_sanitizer
devise_parameter_sanitizerメソッドを使うとdeviseで設定されているstrong_parametersに対してパラメーターを追加できる。
devise_parameter_sanitizerメソッドはbefore_actionに設定する。
これはdeviseの処理なので、Deviseのコントローラを継承したコントローラかもしくはApplicationControllerに記述する。この際に直接before action内にdevise_parameter_sanitizerを書いてはいけない(なぜ?)
devise_parameter_sanitizer.permit(追加したいメソッドの種類, keys: [追加したいパラメーター名])
指定する引数は2つ。1つ目が「StrongParametersを追加したい処理の種類」
引数の値 | 処理 |
---|---|
:sign_up | 新規登録時 |
:sign_in | ログイン時 |
:account_update | レコードの更新時 |
2つ目の引数には追加したいパラメーター名を渡す。
複数の場合は,(カンマ)区切りで渡す。
devise_parameter_sanitizer.permit(追加したいメソッドの種類, keys: [:パラメーター1, :パラメーター2,..])
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters if: :devise_controller?
def after_sign_out_path_for(resource)
'/users/sign_in' # サインアウト後のリダイレクト先URL
end
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up,keys: [:avatar, :nickname])
end
end
devise_parameter_sanitizerメソッドはdeviseで追加されたメソッドなので、Deviseのコントローラ以外で呼び出せない。よって、before_actionを適応するコントローラを指定する。
before_action :メソッド名, if: :コントローラ名?
user_signed_in?
サインインしていればtrueを、していなければfalseを返す。
before_action等で制御するときになどによく使う。
unless user_signed_in?
puts 'ログインをしてください'
end
ユーザーをサインインさせる。
sign_inにインスタンスを渡すとサインインできる。
ウィザード形式のフォームの場合などに事後でサインインさせる時に使う。
sign_in User.find(session[:id]) unless user_signed_in?
controllerのoverride
registrationsをオーバーライドするには以下のように記載し、
devise/registrations -> users/registrationsへ参照先を変更する。
devise_for :users, controllers: {
registrations: 'users/registrations'
}
scopeを設定することでアクションを追加できる。
devise_scope :user do
post '/users/sign_up/payment_confirmation', to: 'users/registrations#payment_confirmation'
get '/users/sign_up/complete', to: 'devise/registrations#complete'
get '/users/logout', to: 'devise/registrations#user_logout'
end
メモ書き
ユーザーページの実装
ユーザー個別のページは/users/1 ~ /users/99などと振られるIDによりページ名が異なる。
Rails.application.routes.draw do
devise_for :users
get 'users/:id' => 'users#show'
end
users/:idとすることでパラメーターにハッシュ形式で値を持たせることができる。
params[:id]とすればコントローラーがidを取り出せる。
errors
user exists
空のデータベースに対して登録しようとした時、下記のエラーが出る。
エラー名と実態が一致していないケースで、validationエラーの可能性が高い。
多いのはdeviseの標準のpassword8文字以上を満たしていないケース。
User Exists (0.5ms)[0m [1mSELECT 1 AS one FROM "users" WHERE "users"."email" = 'hoge@mst.com' LIMIT 1
Undefined method users_url
deviseもコントローラーをオーバーライドした際に、sign_up後の遷移先に移る際にこのエラーがでた。
after_sign_up_path_forを書き換えてもエラーが消えなかったため、createアクションをオーバーライドして、redirectするように変更して解消した。
エラーの原因や解決方法がよくわからない。
Active Storage
画像アップロード用のgemであるActive Storageを使う。
ImageMagick
ImageMagickという画像変換ツールと、それをRailsから使うためのmini_magickというgem
brew install imagemagick
gemfile
gem 'mini_magick'
bundle install
インストールが終わったらサーバーの再起動
Active Storageのインストール
rails active_storage:install
rails db:migrate
Userモデルに設定を追加
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
has_one_attached :avatar
end
画像の出力
ユーザー登録に画像を登録させる際に使う。
登録された画像を利用する際には下記のようにする。
<%= image_tag current_user.avatar %></div>
bcrypt
パスワード暗号化してくれる。Deviseでも使われている。
以下を記載してbundle install
gem 'bcrypt'
暗号化パスワードを利用したいモデルに以下のように記述する。
class Hoge < ApplicationRecord
has_secure_password
end
hoge.saveする際にはformでpasswordとpassword_confirmationの2つを渡せば自動的にエンコードしてくれる。エンコードされたパスワードはpassword_digestに格納される。
migrateファイルに以下カラムを足す。
t.string :password_digest
deviseでbcryptを利用する場合にはpassword_digestではなく、encrypted_passwordという名称になる。
パスワードの認証 authenticate()
引数にパスワードを渡して、インスタンスに適応すると、パスワードが一致していればtrue、違えばfalseを返す。
@hoge.authenticate("hogehoge")
コメント