我有一个通知服务,我从ActiveJob作业内部调用(使用delayed_job后端)。每个通知的主题是一个模型实例,可以是几个不同类中的任何一个。为了方便收件人,我需要包含指向该对象视图的链接。
这不起作用,因为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
想要一个控制器/动作规范,而不是模型。
在邮寄者中,我可以使用url_for(object)
,无论模型类是什么,它都是正确的。那么我如何在作业中访问多态url助手呢?
答案 0 :(得分:8)
@ inopinatus的答案很棒,但我在Rails 4中遇到了配置。
config.active_job.default_url_options = { host: "example.com" }
初始化第一个ActiveJob时出现“NoMethodError:未定义的方法`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' }
答案 1 :(得分:4)
经过一番思考(并阅读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
将必要的内容添加到config/application.rb
:
config.active_job.default_url_options = { host: "example.com" }
并改变了原来的课程:
class NotificationJob < ApplicationJob
def perform(object, message)
NotificationService.send(url_for(object), message)
end
end
我很惊讶地发现Rails.application.routes.url_helpers.url_for
的行为与包含的实例方法不同,而不是单例,但是对源的检查证实了它。
有更好的解决方案吗?