TRACKS_VISITS
Rails: Track unique and total visits/viewings of an ActiveRecord resource based on user/account or IP.
Installation
sudo gem install grimen-tracks_visits
Usage
1. Generate migration:
$ ./script/generate tracks_visits_migration
Generates db/migrations/{timestamp}_tracks_visits_migration
with:
class TracksVisitsMigration < ActiveRecord::Migration
def self.up
create_table :visits do |t|
t.references :visitable, :polymorphic => true
t.references :visitor, :polymorphic => true
t.string :ip, :limit => 24
t.integer :visits, :default => 0
# created_at <=> first_visited_at
# updated_at <=> last_visited_at
t.
end
add_index :visits, [:visitor_id, :visitor_type]
add_index :visits, [:visitable_id, :visitable_type]
end
def self.down
drop_table :visits
end
end
2. Make your model count visits:
class Post < ActiveRecord::Base
tracks_visits
end
or
class Post < ActiveRecord::Base
tracks_visits :by => :user # Setup associations for the visitor class automatically
end
Note: :by
is optional if you choose any of User
or Account
as visitor classes.
3. …and here we go:
@post = Post.create
@post.visited? # => false
@post.unique_visits # => 0
@post.total_visits # => 0
@post.visit!(:ip => '128.0.0.0')
@post.visit!(:visitor => @user) # aliases: :user, :account
@post.visited? # => true
@post.unique_visits # => 2
@post.total_visits # => 2
@post.visit!(:ip => '128.0.0.0')
@post.visit!(:visitor => @user)
@post.visit!(:ip => '128.0.0.1')
@post.unique_visits # => 3
@post.total_visits # => 5
@post.visted_by?('128.0.0.0') # => true
@post.visted_by?(@user) # => true
@post.visted_by?('128.0.0.2') # => false
@post.visted_by?(@another_user) # => false
@post.reset_visits!
@post.unique_visits # => 0
@post.total_visits # => 0
# Note: See documentation for more info.
Caching
If the visitable class table – in the sample above Post
– contains a columns total_visits_count
and unique_visits_count
, then a cached value will be maintained within it for the number of unique and total visits the object have got. This will save a database query for counting the number of visits, which is a common task.
Additional caching fields:
class AddTrackVisitsCachingToPostsMigration < ActiveRecord::Migration
def self.up
# Enable tracks_visits-caching.
add_column :posts, :unique_visits_count, :integer
add_column :posts, :total_visits_count, :integer
end
def self.down
remove_column :posts, :unique_visits_count
remove_column :posts, :total_visits_count
end
end
Dependencies
Basic usage:
- rails (well…)
For running tests:
- sqlite3-ruby
- thoughtbot-shoulda
- nakajima-acts_as_fu
- jgre-monkeyspecdoc
Notes
- Tested with Ruby 1.9+. =)
- Let me know if you find any bugs; not used in production yet so consider this a concept version.
TODO
- More thorough tests for more complex scenarios.
- ActiveModel finder helpers.
License
Copyright © Jonas Grimfelt, released under the MIT-license.