タイトルでほぼ完結していますw
Devise を使った認証動作にログイン後に動作するフックを追加したのですが、フック内でリクエストが必要になり、どうやれば取得できるのかわからずハマったんですが、タイトルの方法で取得できたという話です。
状況が限定的であまり汎用性はないかもしれませんが、もしかしたら世の中には一人くらい私と似たようなハマり方をする人もいるかもしれないと思い記事にするだけしてみました。よろしければお付き合いください。
動作環境
- Ruby 2.4.2
- Rails 5.2.0
- Devise 4.4.3
背景など
仕事でとある rails アプリケーションの開発を行っています。その際に「ログインするたびに○○をさせる」という処理を追加することになりました。
ログインまわりは Devise を使って実装していましたので、下記の参考記事を見て、 Warden の callbacks を使えば前述動作を実現できそうと思いその方向で進めました。
参考記事
コード概要
認証後に毎回動くフックは after_authentication のようです。なのでこれを使いました。
initializers 配下にさえあればなんでも良さそうですが、別ファイルにするほどでもないので今回は devise.rb の一番下に追加しています。これでログインのたびに下記ブロック内の処理が実行されます。
Devise.setup do |config|
# 諸々やってますがここでは省略
# ログイン後のフック
Warden::Manager.after_authentication do |user, auth, _opts|
# ここでいろいろやるよ
end
end
本題
で、ここからが今回の記事の話です。
とある理由からここで request の取得が必要になりました。(まあ、ヘッダ見たりIP見たりとかそんなところです)
しかし、initializers でどうやれば request の取得ができるのかわからずけっこうハマりました。
で、いろいろ調べてみたところ、このフックの2番目の引数である auth
から request が取得できることがわかりました。
コールバックの2つめの引数に来ている auth
は、Warden::Proxy
のインスタンスです。さらに、ここに include されている Warden::Mixins::Common
を追ってみると request
といういかにもリクエストが取得できそうなメソッドを発見しました。
# Convenience method to access the rack request.
# :api: public
def request
@request ||= Rack::Request.new(@env)
end # request
よさげですね。
Rack概要
こちらがわかりやすかったです。
https://route477.net/d/?date=20080716
Rackの理解は筆者もまだ怪しいのでもうちょっと勉強が必要そうです
使ってみました
下記のとおり試してみたところ、期待していたリクエストのインスタンスが取れました。あとはどうとでもできそうです。やったね
pry(main)> auth.request.class
=> ActionDispatch::Request
雑感
確認はしてませんが、after_authentication
以外のフック内でも使えると思います。もし似たような内容でお困りの方は試してみてください。
Warden Callbacks
公式リポジトリの Wiki です。
https://github.com/wardencommunity/warden/wiki/Callbacks