Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails: URLヘルパーをビューやコントローラ以外の場所で使う(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

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モデル内で使うのは避けましょう。もっとふさわしい場所はきっと他にあります!

関連記事


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。