[英]What is the best way of accessing routes in ActiveRecord models and observers
I have a situation where I want to make a request to third-party API(url shortening service) after creating a record in the database (updates a column in the table which stores the short url), in order to decouple the API request from the Model, I have set up an ActiveRecord Observer which kicks in every time a record is created, using after_create
callback hook, here is the relevant code: 我有一种情况,我想在数据库中创建一个记录(更新存储短网址的表中的列)之后向第三方API(网址缩短服务)发出请求,以便将API请求与模型,我已经设置了一个ActiveRecord Observer,它在每次创建记录时都会使用
after_create
回调钩子,这里是相关的代码:
class Article < ActiveRecord::Base
has_many :comments
end
class ArticleObserver < ActiveRecord::Observer
def after_create(model)
url = article_url(model)
# Make api request...
end
end
The problem in the above code is article_url
because Rails Routes are not available in either Model or ModelObservers, same as ActionMailer (similar problem exists in Mails where if we need to put an URL we have to configure "ActionMailer::default_options_url"). 上面代码中的问题是
article_url
因为Rails Routes在Model或ModelObservers中都不可用,与ActionMailer相同(Mails中存在类似的问题,如果我们需要放置一个URL,我们必须配置“ActionMailer :: default_options_url”)。 In theory accessing routes/request object in Model is considered a bad design. 理论上,在Model中访问路径/请求对象被认为是一种糟糕的设计。 To circumvent the above issue I could include the
url_helpers
module as described in the following URL: 为了避免上述问题,我可以包含
url_helpers
模块,如以下URL中所述:
http://slaive-prog.tumblr.com/post/7618787555/using-routes-in-your-model-in-rails-3-0-x http://slaive-prog.tumblr.com/post/7618787555/using-routes-in-your-model-in-rails-3-0-x
But this does not seem to me a clean solution, does anybody have a pointer on this issue or any advice on how it should be done? 但这对我来说似乎不是一个干净的解决方案,是否有人指出这个问题或者有关如何应该做的任何建议?
Thanks in advance. 提前致谢。
I would definitely not let your models know about your routes. 我绝对不会让你的模特知道你的路线。 Instead, add something like
attr_accessor :unshortened_url
on your Article
class. 相反,在
Article
类上添加类似attr_accessor :unshortened_url
内容。 Set that field in your controller, and then use it from your observer. 在控制器中设置该字段,然后从观察者中使用它。 This has the added benefit of continuing to work if you later decide to set your shortened URL asynchronously via a background task.
如果您以后决定通过后台任务异步设置缩短的URL,这还有继续工作的额外好处。
Edit 编辑
A couple of things, first of all. 首先是几件事。
So let's move the trigger of this soon-to-be-background task into the controller. 因此,让我们将这个即将成为后台任务的触发器移动到控制器中。
class ArticlesController < ApplicationController
after_filter :short_url_job, :only => [:create]
# ...
protected
def short_url_job
begin
@article.short_url = "I have a short URL"
@article.save!
rescue Exception => e
# Log thy exception here
end
end
end
Now, obviously, this version of short_url_job
is stupid, but it illustrates the point. 现在,显然,这个版本的
short_url_job
是愚蠢的,但它说明了这一点。 You could trigger a DelayedJob
, some sort of resque
task, or whatever at this point, and your controller will carry on from here. 你可以触发一个
DelayedJob
,某种resque
任务,或者此时的任何事情,你的控制器将从这里继续。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.