Tracking page views really isn't too difficult with Ruby on Rails. Consider a blog with a Post
model, which has a views
column.
in app/models/post.rb
:
def increment(by = 1)
self.views ||= 0
self.views += by
self.save
end
Then in app/controllers/post_controller.rb
:
def show
@post = …
@post.increment
…
end
This is very simple, and it works. But it also means that for every request, we have to do an extra SQL query to update the post with the new view count. For a blog, we want to optimize for fast page loads, so it would be better to move this work into an asynchronously queue.
Afterparty is a queue that is compatible with Rails 3 and 4. It was designed to be compatible with the rails 4 queueing api and supports executing jobs in the future.
After you install Afterparty, change posts_controller
to increment asynchronously:
def show
@post = …
job = Afterparty::BasicJob.new @post, :increment
Rails.configuration.queue << job
…
end
Using Afterparty::BasicJob
will create a simple job that accepts an object, a method, and any number of arguments. When the job is run, the method will simply be called on the object. Make sure you have a worker queue running by executing rake jobs:work
. The next time you view that post, the views
value will increment in the background.
This absolutely has some trade-offs. For one, you don't display the exact count of views when a visitor views a post. This is because the value is being updated simultaneously as the page is rendered. You can account for this by displaying @post.views + 1
, but you still can't guarantee that it's accurate, as there may be other background jobs also about to increment the views of this post. The advantage of this approach is that page requests will be much faster. If you're in a situation like this where you want to count something and care about fast requests more than precise counts, I encourage you to try this pattern.