こんにちは!kossyです!
さて、今回は、トークンベースの認証の仕組みを提供するgemであるdevise_token_authの
コードリーディングをしていた時に書かれていたある構文について、ブログに残してみたいと思います。
yield @variable if block_given?
なんだこれ?と思ったコードは以下です。
def validate_token # @resource will have been set by set_user_by_token concern if @resource yield @resource if block_given? render_validate_token_success else render_validate_token_error end end
順番に紐解いてみます。
まず、block_given?は、メソッドを実行する時にブロックが渡されていればtrueを返し、渡されていない時はfalseを返します。
Rubyではどのメソッドでも何の宣言も無しにブロック引数を渡すことができます。
block_given?メソッドの定義元もkarnelモジュールなので、どこでも使うことができます。
次にyield @resource ですが、yieldは渡されたブロックをメソッド内で呼び出すことができます。
また、引数を渡すことが可能で、@resourceを渡されたブロック内で使うこともできます。
もう一度当該コードを確認すると、
def validate_token # @resource will have been set by set_user_by_token concern if @resource yield @resource if block_given? render_validate_token_success else render_validate_token_error end end
「もしvalidate_tokenメソッドの呼び出し時に@resourceがtrueの場合でブロックが渡されていれば、渡されたブロック内で@resourceを使って処理をした後に、render_validate_token_successを呼び出す」
「@resourceがnilまたはfalseの場合はrender_validate_token_error」
と書いてあるようです。
validate_tokenメソッドをブロック引数付きで呼び出すユースケースとしては、認証後にユーザーのプロフィール情報に基づいて特定のアクションを実行するケースが考えられます。
例えば、最後に tokenの確認を行なった日時を更新したい場合、以下のような書き方が可能です。
# user = @resource です validate_token do |user| user.update(token_last_validated_at: Time.zone.now) end
yield @resource if block_given? という記述を行うことで、メソッドに柔軟性を与えることが可能になると思います。
勉強になりました。
参考にさせていただいた記事
Kernel.#block_given? (Ruby 3.3 リファレンスマニュアル)
devise_token_auth/app/controllers/devise_token_auth/token_validations_controller.rb at master · lynndylanhurley/devise_token_auth · GitHub
【Ruby入門】yieldの使い方まとめ | 侍エンジニアブログ
https://qiita.com/tsubasakat/items/0de47f8814b0848f1d16
Rubyのyieldって結局何なの?|よしだ