背景
- こちらの記事を読んで Rails で response を返した後の処理が実行されるのかが気になった
- アクションの中のrender(), redirect_to()の後の処理は実行される
- 書かれたのが10年以上前だったので最近だとどうなのかを調べたい
- 先に response を返せると何が嬉しいか?
- タイムアウトまでの時間制限が厳しいシステムや機能と連携する際に非同期処理にしなくてもよくなる
- 例えば Slack とか
- https://api.slack.com/interactivity/slash-commands#responding_to_commands
This confirmation must be received by Slack within 3000 milliseconds of the original request being sent, otherwise a Timeout was reached will be displayed to the user.
環境
➜ ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]
➜ rails -v
Rails 6.0.2.2
調べた結果
- 普通にタイムアウトした
-
render
head
などのレスポンス系のメソッドの後に書かれた処理も実行される - ただ、アクションの中で書かれたすべての処理が実行された後に response を返すっぽい
- 処理の順番が逆になるわけではないので最後に render するのが自然
class HelloController < ApplicationController
def hello
render status: 200
sleep 3.0
slack_client = Slack::Web::Client.new(
token: ENV['SLACK_TOKEN']
)
res = slack_client.chat_postMessage(
channel: params[:channel_id],
text: 'hello world'
)
end
end
-
after_action
系を使っても同じ挙動
class HelloController < ApplicationController
after_action :slack_post
def hello
render status: 200
end
def slack_post
sleep 3.0
slack_client = Slack::Web::Client.new(
token: ENV['SLACK_TOKEN']
)
res = slack_client.chat_postMessage(
channel: params[:channel_id],
text: 'hello world'
)
end
end
- ただ
before_action
で render すると処理がそこで終わる
class HelloController < ApplicationController
before_action :before_render
def before_render
render status: 200
end
def hello
# ここは実行されない
sleep 3.0
slack_client = Slack::Web::Client.new(
token: ENV['SLACK_TOKEN']
)
res = slack_client.chat_postMessage(
channel: params[:channel_id],
text: 'hello world'
)
end
end