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

ino*_*tus 2 ruby-on-rails rails-activejob

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

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

class NotificationJob < ActiveJob::Base
  def perform(object, message)
    NotificationService.send(url_for(object), message)
  end
end
Run Code Online (Sandbox Code Playgroud)

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

在我可以使用的邮件中url_for(object),无论模型类是什么,它都是正确的.那么我如何在作业中访问多态url助手呢?

Luc*_*son 8

@inopinatus的答案很棒,但我在Rails 4中遇到了配置.

config.active_job.default_url_options = { host: "example.com" }
Run Code Online (Sandbox Code Playgroud)

初始化第一个ActiveJob时出现"NoMethodError:未定义的方法`default_url_options ='for ActiveJob :: Base:Class".

轨道4配置指南描述了使用config.x…对自定义属性.我需要做出以下调整:

def default_url_options
  Rails.configuration.x.application_job.default_url_options
end
Run Code Online (Sandbox Code Playgroud)

config.x.application_job.default_url_options = { host: 'example.com' }
Run Code Online (Sandbox Code Playgroud)


ino*_*tus 5

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

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
Run Code Online (Sandbox Code Playgroud)

添加了必要的config/application.rb

config.active_job.default_url_options = { host: "example.com" }
Run Code Online (Sandbox Code Playgroud)

并因此改变了我原来的班级:

class NotificationJob < ApplicationJob
  def perform(object, message)
    NotificationService.send(url_for(object), message)
  end
end
Run Code Online (Sandbox Code Playgroud)

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

有更好的解决方案吗?