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?
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 :
Impression#before_create
or other callbacksIf 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.