Rails: URLヘルパーをビューやコントローラ以外の場所で使う(翻訳)
アプリケーションへのURLをビューやコントローラの外で生成する必要が生じることがたまにありますが、そのような場所でもURLヘルパーを利用できます。これらのヘルパーメソッドはルーティングから生成されます(user_books_path(user)
など)。
以下のように書くのではなく
URLを直に書く。
class RequestUserCallBackJob < ApplicationJob
def perform(user)
Net::HTTP.post(
"http://userinfoapi.com/",
body: {callback_to: "https://myapp.com/user/#{user.id}"})
end
end
以下のように書く
Railsのコントローラで自動的にinclude
されているルーティング用ヘルパーを使う。
class RequestUserCallBackJob < ApplicationJob
include Rails.application.routes.url_helpers
def perform(user)
Net::HTTP.post(
"http://userinfoapi.com/",
body: {callback_to: user_url(user, host: "myapp.com")})
end
end
URLヘルパーが使われるのは、Webリクエストのコンテキスト、つまりビューやコントローラの中です。この場合、リクエストのhost
やドメインはアプリケーションが自動的に提供してくれます。このコンテキストの外では、_url
で終わるヘルパーにhost
を明示的に指定する必要があります。
このパターンの発展形は、以下のようにActive Supportのconcernを用いて(おそらく)既に設定されているAction Mailerのurlオプションに乗っかるという方法です。
module Routing
extend ActiveSupport::Concern
included do
include Rails.application.routes.url_helpers
end
def default_url_options
Rails.application.config.action_mailer.default_url_options
end
end
class RequestUserCallBackJob < ApplicationJob
include Routing
def perform(user)
Net::HTTP.post(
"http://userinfoapi.com/",
body: {callback_to: user_url(user)})
end
enda
そうする理由
URLヘルパーは便利で使い方も一貫していますが、アプリケーション全体で使う方がよいでしょう。何らかの理由でルーティングを変更して、関連するURLメソッドの更新に失敗した場合、テストで問題が警告されます。ハードコードされたURLにid
が補完されている場合、事前にこのような警告を出してくれません。
上の例で示されているように、私がこのパターンをよく必要とするのは、レスポンスを受信するためのwebhookが必要な外部APIを呼び出す場合です。
このパターンは、アプリケーションのresouces
URLを記述するフィールドをエクスポートするアプリケーション用のAPIを書いている場合にも使うかもしれません。
{
"id": 23432,
"name": "Nadia",
"links": {
"self": "https://yourapp.com/user/23432.json"
}
}
しかしAPIレスポンスはそれ自身のためのものです。したがって、URLヘルパーを自分で混ぜるのではなく、 active_model_serializers
のようなAPIレスポンスを生成するためのツールを使うべきでしょう。
そうしない理由があるとすれば
ルーティングヘルパーがまだない場所でルーティングヘルパーを使おうとする場合は、このパターンを使うべきではない可能性があるかもしれません。
ルーティング(ヘルパー)をActive Recordモデル内で使うのは避けましょう。もっとふさわしい場所はきっと他にあります!
概要
原著者の許諾を得て翻訳・公開いたします。