如何在 ActiveJob 作业中使用 url_for / polymorphic_url?

How can I use url_for / polymorphic_url from an ActiveJob job?

我有一个从 ActiveJob 作业内部调用的通知服务(使用 delayed_job 后端)。每个通知的主题是一个模型实例,可以是几个不同的 classes 中的任何一个。为了收件人的方便,我需要在该对象的视图中包含一个 link。

这不起作用,因为 url_for 不是作业上下文中可用的方法:

class NotificationJob < ActiveJob::Base
  def perform(object, message)
    NotificationService.send(url_for(object), message)
  end
end

在此代码的先前且更受限制的版本中,我使用了 Rails.application.routes.url_helpers.model_name_url(object),但这是特定于模型的。 Rails.application.routes.url_for 似乎想要 controller/action 规范,而不是模型。

在邮件程序中,我可以使用 url_for(object),无论是什么型号,它都能正常工作 class。那么我如何访问作业中的多态 url 助手?

经过更多思考(并通读 Rails 源代码)后,我想出了一个解决方案。我在 app/jobs/application_job.rb 中创建了一个特定于应用程序的基础 class 以从以下位置继承作业:

class ApplicationJob < ActiveJob::Base
  include Rails.application.routes.url_helpers

  protected
  def default_url_options
    Rails.application.config.active_job.default_url_options
  end
end

config/application.rb 添加了必要的内容:

config.active_job.default_url_options = { host: "example.com" }

并改变了我原来的 class 这样:

class NotificationJob < ApplicationJob
  def perform(object, message)
    NotificationService.send(url_for(object), message)
  end
end

我惊讶地发现 Rails.application.routes.url_helpers.url_for 的行为作为包含的实例方法与作为单例的行为如此不同,但对源代码的检查证实了这一点。

有没有更好的解决方案?

@inopinatus 的回答很好,但我在 Rails 4 的配置中被绊倒了。

config.active_job.default_url_options = { host: "example.com" }

在初始化第一个 ActiveJob 时导致"NoMethodError: undefined method `default_url_options=' for ActiveJob::Base:Class"。

Rails 4 configuration guide 描述了使用 config.x… 自定义属性。我需要进行以下调整:

def default_url_options
  Rails.configuration.x.application_job.default_url_options
end

config.x.application_job.default_url_options = { host: 'example.com' }