【Rails】sorcery - require_login
内容
Ruby on Rails のgem 'sorcery'
の
ライブラリーメソッドrequire_login
について
ソースコード追跡
def require_login return if logged_in? # ① ログインしている場合は処理中止(Guard節) if Config.save_return_to_url && request.get? && !request.xhr? && !request.format.json? # ② request session[:return_to_url] = request.url # ③ sessionのreturn_to_urlキーにリクエストURLを格納 end send(Config.not_authenticated_action) # ④ selfを省略している? # ⑤ not_authenticated_actionについて end
① return ifによるGuard節
logged_in?がtrueの場合、
require_loginメソッドは処理されません
② request
request
が
Sorceryのソースコードの中のどこにも定義されていないと思いきや
Railsでデフォルトで定義されていました
③sessionのrequest_to_urlキーにリクエストURLを格納する
session[:request_to_url]
がいつの間に出てきましたが、
sessionのキーの名前は自由につけれるんですね
④ selfを省略している?
self.send(Config.not_authenticated_action)
の略だと思いますが、
selfの要否の判別がいまいちできていないので、よくわかりません(= =;)
⑤ not_authenticated_actionについて
send(Config.not_authenticated_action)
のsendメソッドの引数Config.not_authenticated_action
については
Sorcery::Controller::Configに書いてあります。
module Sorcery module Controller module Config class << self ... # what controller action to call for non-authenticated users. attr_accessor :not_authenticated_action ... def init! @defaults = { ... :@not_authenticated_action => :not_authenticated, ... } end
@defaults
のキー@not_authenticated_action
の値として
:not_authenticated
が定義されています。
つまり、
require_login
の中身のsend(Config.not_authenticated_action)
が
実行されたとき、
Module: Sorcery::Controller::InstanceMethods#not_authenticatedが実行されます。
def not_authenticated redirect_to root_path end
まとめ
Ruby on Railsのgem 'sorcery'
で使うことのできる
require_login
メソッドについて
・ログインしていないユーザーに対して発火します
・require_loginメソッドが発火した後、not_authenticatedメソッドが発火します。
※
・内部処理でsession[:request_to_url]
として
リクエストしたURLが保存してあるので、
not_authenticatedでログインしていないとして弾かれた後も
ログインした後、リクエストした後のURLへ遷移させる
というような実装もできそうですね
Tips
require_loginメソッドが発火した後の処理として
not_authenticatedメソッド以外を指定することも可能です。
【Ruby】return if によるガード節
内容
Ruby, Ruby on Railsで使われる return if について
経緯
Module: Sorcery::Controller::InstanceMethods#require_loginで
return if
が使われており、調べてみたのでメモ・備忘録として
return if
はガード節
ガード(Guard)節とは、
不要な処理は予め判定し、後続に進ませない(ガードする)ものです。
実際のコードで使用されている例
例として、
Module: Sorcery::Controller::InstanceMethods#require_login
を見てみましょう
def require_login return if logged_in? ... end
require_login
メソッドでは
logged_in
がtrueの場合は処理を中止します
という意味のガード節が使われています。
参考
・Module: Sorcery::Controller::InstanceMethods — Documentation for sorcery (0.16.1)
・【Ruby】乱用厳禁!?後置ifで書くとかえって読みづらくなるケース - Qiita
・プログラム初心者脱却?ガード節って何?|ダルオ|note
【Rails】devise - パスワードなしでアカウント情報編集できるようにカスタマイズ
内容
Ruby on Railsのgem 'devise'
について
deviseの登録・認証を使用するモデルレコードのカラムデータの更新を
パスワードなしでできるようにカスタマイズする方法
前提
前提① : Userモデルレコードにdeviseの登録・認証機能を使用
$ rails g devise User
前提② : deviseのレコード登録コントローラのルーティング
Rails.application.routes.draw do devise_for :users, controllers: { registrations: 'registrations' } end
デフォルトの設定
devise本家のアカウント情報編集のデフォルト設定では
リソースのカラム更新には、パスワードを必要としています。(→ 詳細)
カスタマイズ方法
リソース更新時に発火する
Devise::RegistrationsController#update 内
で使用されている
update_resource
メソッド
をオーバライドします。
update_resource
メソッドをオーバーライド
class RegistrationsController < Devise::RegistrationsController def update_resource(resource, params) resource.update_without_current_password(params) # update_without_current_passwordメソッドは自分で新たに作成するメソッド end end
update_without_current_password
メソッドを新たに定義する
class User < ApplicationRecord def update_without_current_password(params, *options) if params[:password].blank? && params[:password_confirmation].blank? params.delete(:password) params.delete(:password_confirmation) end # if条件はpasswordとpassword_confirmationの入力フォームが # 空の場合のみに処理するのを明示するため result = update_attributes(params, *options) clean_up_passwords result end end
注意点
devise本家で定義されているupdate_without_password
メソッドを使ってオーバーライドするだけでは、
自身でパスワード変更できなくなってしまうので、
自分でメソッドを作成する必要があります。
上記の例では
update_without_current_password
メソッドという名前で作成しています。
devise本家のupdate_without_password
メソッドのソースコードからも、
フォームから送られるparamsからpasswordとpassword_confirmationを削除して
リソースを更新するのがupdate_without_password
メソッドのため、
入力フォームにパスワード・パスワード確認を入力しても
内部処理でparamsから除外されてしまうため
パスワードを更新することができません。
リソース編集画面からpassword/password_confirmation入力フォームを削除
編集画面から
・password入力フォーム
・password_confirmation入力フォーム
を削除し、
先ほど新たに作成し定義したupdate_without_current_password
メソッドの
「password/password_confirmationが空の場合のみ処理する」という
if条件を常に成り立つようにします
参考
・heartcombo/devise: Flexible authentication solution for Rails with Warden.
・Devise でユーザーがパスワードなしでアカウント情報を変更するのを許可 | EasyRamble
・【Rails】deviseでユーザー編集機能を現在のパスワードなしで更新してみる。|Yuya Abe|note
【Rails】devise - deviseのデフォルト設定(リソース更新時にパスワードが必要)
内容
devise本家では
deviseの登録・認証を使用するモデルレコードのカラム更新にはパスワードを必要としています。
これをdevise本家のソースコードから追ってみます。
ソースコード追跡
Devise::RegistrationsController#update
アカウント更新時に発火するアクションです。
中身を見てみましょう
class RegistrationsController < Devise::RegistrationsController def update self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key) prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email) resource_updated = update_resource(resource, account_update_params) # レコード更新 yield resource if block_given? ... end
update_resources
メソッドの返り値を
更新完了のリソース resources_updated
へ格納しています。
次はupdate_resources
について見てみます。
Devise::RegistrationsController#update_resources
class RegistrationsController < Devise::RegistrationsController def update_resource(resource, params) resource.update_with_password(params) end end
update_resouces(resource, params)
メソッドは
・第1引数resource
→ update_with_password
メソッドの使用対象オブジェクト
・第2引数params
→ update_with_password
メソッドに渡す引数
として、update_with_password
メソッドを発火させます。
Devise::Models::DatabaseAuthenticatable#update_with_password
update_with_password
メソッドは
メソッドの名前の通り、パスワードが正しければリソースを更新するものでした。
まとめ
deviseを適用するモデルレコード更新時に走るDevise::RegistrationsController#update
アクションの根幹に
Devise::Models::DatabaseAuthenticatable#update_with_password
メソッドがあるため、
デフォルトではリソース情報更新にパスワードが必要となっています。
【Ruby】deleteメソッドの注意
内容
Rubyのdeleteメソッドについて
deleteメソッドの使用対象のクラスの型によって
定義上、返り値が変わってしまうことに注意です。
deleteメソッドは色々なクラスに対して定義されている
・String#delete (Ruby 3.0.0 リファレンスマニュアル)
・Array#delete (Ruby 3.0.0 リファレンスマニュアル)
・Hash#delete(key) (Ruby 3.0.0 リファレンスマニュアル)
deleteメソッド(Ruby)の注意点
Rubyのdeleteメソッドは、使用対象のクラスによって
・削除する要素を返すか
・削除指定した要素を削除した後の残りを返すか
が異なります。
削除する要素を返す
# class_object : クラスのオブジェクト # delete_target : 削除する要素 class_object.delete(delete_target) # => delete_target # 削除された要素が返り値となる
削除指定した要素を削除した後の残りを返す
# class_object : クラスオブジェクト # remain_object : deleteメソッドで削除指定した要素の残り # delete_target : 削除する要素 # remain_object = class_object - delete_target class_object.delete(delete_target) #=> remain_object # 削除した後の残りが返り値となる
返り値の違い
使用対象のクラス | 返り値 |
---|---|
Stringクラス (String#delete) | 削除指定した要素を削除した後の残り |
Arrayクラス (Array#delete) | 削除された要素 |
Hashクラス (Hash#delete(key)) | 削除された要素 (削除指定したkeyに対するvalue) |
【Rails】Railsのassets周り(順次追加)
内容
Railsのassets管理
経緯
経緯① : assets周りの苦手意識
Railsのassets周りに関して、どうしても苦手意識があるんですよね。。。
・development環境・production環境問わず、最新のcssが反映されない
・Railsアプリのデプロイのとき、assets:precompile周りで高確率で詰まる
経緯② : どれがsprocketsでどれがwebpacker?
Rails 6 からwebpackerが標準となったようですが
調べてみると
sprockets→webpackerへ一部移行、sprocketsのまま一部管理、
のような記事もあり、
・asstes管理にsprocketsを使うか?webpackerを使うか? の選択
・既存コードのasstes管理にsprocketsを使っているか?webpackerを使っているか? を見分ける
などが必要になると思い
今後の記事作成予定
Railsのassets周りのテーマも大テーマであると思うので、
記事は順次作成しようと思います
・assets pipeline
・sprockets
・webpacker
・その他
・パッケージマネージャ(npm, yarn ..)
【Rails】devise - deviseに関する各記事
内容
私が今まで作成したdeviseに関する記事のリンクをまとめてます
小さな項目ごとに作成しているため、まとめ記事として
(devise関連の記事を追加しましたら順次更新していきます)
deviseに関する記事リスト
deviseの基本的実装
deviseのヘルパーメソッド
・【Rails】devise - authenticate_user! メソッド
・【Rails】devise - current_user
・【Rails】devise - user_signed_in?
deviseのカスタマイズ
deviseのデフォルト設定
カスタマイズオーバーライドする際に
deviseデフォルト設定の把握が必要になります
・【Rails】devise - deviseのデフォルト設定(リソース更新時にパスワードが必要)
オーバーライドによるカスタマイズ
# パスワード不要化
・【Rails】devise - パスワードなしでアカウント情報編集できるようにカスタマイズ
# リダイレクト遷移先パスのカスタマイズ
・【Rails】devise - ログイン・ログアウト後のリダイレクト先をカスタマイズする
・【Rails】devise - アカウント作成・更新後のリダイレクト遷移先をカスタマイズする