Question

I want to save information about requests to a certain action in a model named Impression.

I assume it's benificial for the visitor's response time to save this info in an after_filter, e.g:

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

Can this code be optimized or am I doing it right?

Was it helpful?

Solution

A good solution for that would typically involve using a worker. Anything that is not mission critical to the request and that involves complex computing can be deferred and run later by a background job.

Two common implementations of workers are delayed_job and resque.

For example, with resque, you would have a job class in app/jobs/impression_creation_job.rb, containing something like that :

 class ImpressionJob
  @queue = :impression

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

And you can call it in your controller like that :

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

This will ensure a fast handling on the request part (it just loads data in redis) and will then be processed by a background process (see resque documentation for how to set it up and start workers).

Please note that this will be useful in your case in only two cases :

  1. Your app is always under heavy load or need especially good response time
  2. You do big computations in Impression#before_create or other callbacks

If not matching one of those conditions, it's probably more effective to just let your impression creation in a controller filter : accessing database has a cost, but not that much that a user will feel when you make a single insertion in database.

OTHER TIPS

This will still run before render. To run after the render/redirect, you need to spawn a separate thread.

See this question

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top