2

我想将有关请求的信息保存到名为 Impression 的模型中的某个操作。

我认为将此信息保存在 after_filter 中对访问者的响应时间是有益的,例如:

after_filter :save_impression


private
    def save_impression
        Impression.create!(ip_address: request.remote_ip, controller_name: params[:controller], action_name: params[:action], referer: request.referer)
    end

这段代码可以优化还是我做对了?

4

2 回答 2

3

一个好的解决方案通常涉及使用工人。任何对请求来说不是关键任务并且涉及复杂计算的东西都可以延迟并稍后由后台作业运行。

两种常见的worker实现是delayed_jobresque

例如,使用 resque,您将有一个工作类 in app/jobs/impression_creation_job.rb,其中包含类似的内容:

 class ImpressionJob
  @queue = :impression

  def self.perform( attrs )
    Impression.create!( attrs )
  end
end

您可以像这样在控制器中调用它:

after_filter :save_impression


private
  def save_impression
    Resque.enqueue( ImpressionJob, ip_address: request.remote_ip, controller_name: params[:controller], action_name: params[:action], referer: request.referer)
  end

这将确保对请求部分的快速处理(它只是在 redis 中加载数据),然后将由后台进程处理(有关如何设置和启动工作人员的信息,请参阅 resque 文档)。

请注意,这仅在两种情况下对您的情况有用:

  1. 您的应用程序总是处于高负载状态或需要特别好的响应时间
  2. 您在Impression#before_create或其他回调中进行大计算

如果不符合其中一个条件,那么只让您在控制器过滤器中创建印象可能更有效:访问数据库是有成本的,但当您在数据库中进行单次插入时,用户会感受到的成本并不高。

于 2013-09-09T12:49:43.903 回答
2

这仍然会在渲染之前运行。要在渲染/重定向之后运行,您需要生成一个单独的线程。

看到这个问题

于 2013-09-09T11:10:31.090 回答