Skip to content

Instantly share code, notes, and snippets.

@tyrauber
Created March 4, 2016 21:33
Show Gist options
  • Save tyrauber/ed4e0f6053d49608bee7 to your computer and use it in GitHub Desktop.
Save tyrauber/ed4e0f6053d49608bee7 to your computer and use it in GitHub Desktop.
HSTORE Model View Statistics
Let's say you got a Job model and you want to track index_count, show_count, etc.
Why not use Hstore?
Add a migration:
class AddHstoreCountsOnJobs < ActiveRecord::Migration
def change
add_column :jobs, :index_count, :hstore, default: {}
add_column :jobs, :show_count, :hstore, default: {}
add_index :jobs, :index_count, using: :gin
add_index :jobs, :show_count, using: :gin
end
end
Add a scope to the model:
scope :increment!, -> (field=:index_count, query=self.all){
query.update_all("#{field.to_s} = #{field.to_s} || hstore(to_char(NOW(), 'DD/MM/YYYY'), coalesce(((#{field.to_s} -> to_char(NOW(), 'DD/MM/YYYY'))::int+1),1)::text)")
}
Add after_filters to your controller, and a way for finding @jobs even on Show:
after_filter only: :index do @jobs.increment!(:index_count) if @jobs end
after_filter only: :show do @jobs.increment!(:show_count) if @jobs end
private
def set_job
@jobs = Job.where("id = ? OR slug = ?", params[:id].to_i, params[:id])
@job = @jobs.empty? ? nil : @jobs.first
end
And Voila! View Stats stored on the model:
> Job.select(:id,:list_count,:view_count)
Job Load (4.3ms) SELECT "jobs"."id", "jobs"."index_count", "jobs"."show_count" FROM "jobs"
=> #<ActiveRecord::Relation [#<Job id: 5, index_count: {"04/03/2016"=>"4"}, show_count: {}>, #<Job id: 1, index_count: {"04/03/2016"=>"4"}, show_count: {}>, #<Job id: 2, index_count: {"04/03/2016"=>"4"}, show_count: {"04/03/2016"=>"3"}>]>
Updating the stats with only a few records is about 2.2ms. It will be interesting to see how it scales.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment