yield @variable if block_given? ってなに?

こんにちは!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

引用: devise_token_auth/token_validations_controller.rb at master · lynndylanhurley/devise_token_auth · GitHub


順番に紐解いてみます。


まず、block_given?は、メソッドを実行する時にブロックが渡されていればtrueを返し、渡されていない時はfalseを返します。
Rubyではどのメソッドでも何の宣言も無しにブロック引数を渡すことができます。
block_given?メソッドの定義元もkarnelモジュールなので、どこでも使うことができます。

参考
www.sejuku.net

次に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」

と書いてあるようです。



yieldは使いどころが難しい印象を覚えてしまいますが、読めるようにはなっておきたいところです、、、




参考にさせていただいた記事

Kernel.#block_given? (Ruby 2.7.0 リファレンスマニュアル)
devise_token_auth/token_validations_controller.rb at master · lynndylanhurley/devise_token_auth · GitHub
【Ruby入門】yieldの使い方まとめ | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト
【Ruby】yield に引数を渡す - Qiita
Rubyのyieldって結局何なの?|よしだあ|note