Merge pull request #188 from asharma-ror/params_feature

Params feature
This commit is contained in:
John McAliley 2015-06-24 22:18:11 -04:00
commit 729e4fca3b
12 changed files with 110 additions and 14 deletions

View File

@ -55,6 +55,7 @@ The following fields are provided in the migration:
t.string "request_hash" # unique ID per request, in case you want to log multiple impressions and group them t.string "request_hash" # unique ID per request, in case you want to log multiple impressions and group them
t.string "session_hash" # logs the rails session t.string "session_hash" # logs the rails session
t.string "ip_address" # request.remote_ip t.string "ip_address" # request.remote_ip
t.text "params" # request.params, except action name, controller name and resource id
t.string "referrer" # request.referer t.string "referrer" # request.referer
t.string "message" # custom message you can add t.string "message" # custom message you can add
t.datetime "created_at" # I am not sure what this is.... Any clue? t.datetime "created_at" # I am not sure what this is.... Any clue?
@ -114,7 +115,12 @@ Usage
@widget.impressionist_count(:filter=>:ip_address) @widget.impressionist_count(:filter=>:ip_address)
7. Get the unique impression count from a model filtered by session hash. Same 7. Get the unique impression count from a model filtered by params. This
in turn will give you impressions with unique params.
@widget.impressionist_count(:filter => :params)
8. Get the unique impression count from a model filtered by session hash. Same
as #6 regarding request hash. This may be more desirable than filtering by as #6 regarding request hash. This may be more desirable than filtering by
IP address depending on your situation, since filtering by IP may ignore IP address depending on your situation, since filtering by IP may ignore
visitors that use the same IP. The downside to this filtering is that a visitors that use the same IP. The downside to this filtering is that a
@ -122,12 +128,12 @@ Usage
@widget.impressionist_count(:filter=>:session_hash) @widget.impressionist_count(:filter=>:session_hash)
8. Get total impression count. This may return more than 1 impression per http 9. Get total impression count. This may return more than 1 impression per http
request, depending on how you are logging impressions request, depending on how you are logging impressions
@widget.impressionist_count(:filter=>:all) @widget.impressionist_count(:filter=>:all)
9. Get impression count by message. This only counts impressions of the given message. 10. Get impression count by message. This only counts impressions of the given message.
@widget.impressionist_count(:message=>"pageview", :filter=>:all) @widget.impressionist_count(:message=>"pageview", :filter=>:all)
@ -183,6 +189,9 @@ impressions in your controller:
# only record impression if session is unique # only record impression if session is unique
impressionist :unique => [:session_hash] impressionist :unique => [:session_hash]
# only record impression if param is unique
impressionist :unique => [:params]
Or you can use the `impressionist` method directly: Or you can use the `impressionist` method directly:
impressionist(impressionable, "some message", :unique => [:session_hash]) impressionist(impressionable, "some message", :unique => [:session_hash])

View File

@ -3,7 +3,7 @@ require 'digest/sha2'
module ImpressionistController module ImpressionistController
module ClassMethods module ClassMethods
def impressionist(opts={}) def impressionist(opts={})
before_filter { |c| c.impressionist_subapp_filter(opts)} before_filter { |c| c.impressionist_subapp_filter(opts) }
end end
end end
@ -50,7 +50,8 @@ module ImpressionistController
:request_hash => @impressionist_hash, :request_hash => @impressionist_hash,
:session_hash => session_hash, :session_hash => session_hash,
:ip_address => request.remote_ip, :ip_address => request.remote_ip,
:referrer => request.referer :referrer => request.referer,
:params => params_hash
) )
end end
@ -81,7 +82,26 @@ module ImpressionistController
end end
def unique?(unique_opts) def unique?(unique_opts)
return unique_opts.blank? || !Impression.where(unique_query(unique_opts)).exists? return unique_opts.blank? || check_impression?(unique_opts)
end
def check_impression?(unique_opts)
impressions = Impression.where(unique_query(unique_opts - [:params]))
check_unique_impression?(impressions, unique_opts)
end
def check_unique_impression?(impressions, unique_opts)
impressions_present = impressions.exists?
impressions_present && unique_opts_has_params?(unique_opts) ? check_unique_with_params?(impressions) : !impressions_present
end
def unique_opts_has_params?(unique_opts)
unique_opts.include?(:params)
end
def check_unique_with_params?(impressions)
request_param = params_hash
impressions.detect{|impression| impression.params == request_param }.nil?
end end
# creates the query to check for uniqueness # creates the query to check for uniqueness
@ -112,6 +132,10 @@ module ImpressionistController
request.session_options[:id] request.session_options[:id]
end end
def params_hash
request.params.except(:controller, :action, :id)
end
#use both @current_user and current_user helper #use both @current_user and current_user helper
def user_id def user_id
user_id = @current_user ? @current_user.id : nil rescue nil user_id = @current_user ? @current_user.id : nil rescue nil

View File

@ -12,6 +12,7 @@ class CreateImpressionsTable < ActiveRecord::Migration
t.string :session_hash t.string :session_hash
t.text :message t.text :message
t.text :referrer t.text :referrer
t.text :params
t.timestamps t.timestamps
end end
add_index :impressions, [:impressionable_type, :message, :impressionable_id], :name => "impressionable_type_message_index", :unique => false, :length => {:message => 255 } add_index :impressions, [:impressionable_type, :message, :impressionable_id], :name => "impressionable_type_message_index", :unique => false, :length => {:message => 255 }
@ -21,6 +22,7 @@ class CreateImpressionsTable < ActiveRecord::Migration
add_index :impressions, [:controller_name,:action_name,:request_hash], :name => "controlleraction_request_index", :unique => false add_index :impressions, [:controller_name,:action_name,:request_hash], :name => "controlleraction_request_index", :unique => false
add_index :impressions, [:controller_name,:action_name,:ip_address], :name => "controlleraction_ip_index", :unique => false add_index :impressions, [:controller_name,:action_name,:ip_address], :name => "controlleraction_ip_index", :unique => false
add_index :impressions, [:controller_name,:action_name,:session_hash], :name => "controlleraction_session_index", :unique => false add_index :impressions, [:controller_name,:action_name,:session_hash], :name => "controlleraction_session_index", :unique => false
add_index :impressions, [:impressionable_type, :impressionable_id, :params], :name => "poly_params_request_index", :unique => false
add_index :impressions, :user_id add_index :impressions, :user_id
end end

View File

@ -9,6 +9,6 @@ class Impression < ActiveRecord::Base
# sets belongs_to and attr_accessible depending on Rails version # sets belongs_to and attr_accessible depending on Rails version
Impressionist::SetupAssociation.new(self).set Impressionist::SetupAssociation.new(self).set
store :params
after_save :impressionable_counter_cache_updatable? after_save :impressionable_counter_cache_updatable?
end end

View File

@ -35,7 +35,8 @@ module Impressionist
:view_name, :view_name,
:referrer, :referrer,
:message, :message,
:user_id) :user_id,
:params)
end end
def toggle def toggle

View File

@ -9,10 +9,10 @@ module Impressionist
before do before do
# expects attr_accessible to return true # expects attr_accessible to return true
# and pass 11 arguments # and pass 12 arguments
mock. mock.
expect(:attr_accessible, true) do |args| expect(:attr_accessible, true) do |args|
args.size == 11 args.size == 12
end end
end end

View File

@ -1,5 +1,5 @@
class WidgetsController < ApplicationController class WidgetsController < ApplicationController
impressionist :actions=>[:show,:index], :unique => [:controller_name,:action_name,:impressionable_id] impressionist :actions=>[:show, :index], :unique => [:controller_name, :action_name, :impressionable_id, :params]
def show def show
end end

View File

@ -11,6 +11,7 @@ class CreateImpressionsTable < ActiveRecord::Migration
t.string :ip_address t.string :ip_address
t.string :session_hash t.string :session_hash
t.text :message t.text :message
t.text :params
t.text :referrer t.text :referrer
t.timestamps t.timestamps
end end
@ -21,6 +22,7 @@ class CreateImpressionsTable < ActiveRecord::Migration
add_index :impressions, [:controller_name,:action_name,:request_hash], :name => "controlleraction_request_index", :unique => false add_index :impressions, [:controller_name,:action_name,:request_hash], :name => "controlleraction_request_index", :unique => false
add_index :impressions, [:controller_name,:action_name,:ip_address], :name => "controlleraction_ip_index", :unique => false add_index :impressions, [:controller_name,:action_name,:ip_address], :name => "controlleraction_ip_index", :unique => false
add_index :impressions, [:controller_name,:action_name,:session_hash], :name => "controlleraction_session_index", :unique => false add_index :impressions, [:controller_name,:action_name,:session_hash], :name => "controlleraction_session_index", :unique => false
add_index :impressions, [:impressionable_type, :impressionable_id, :params], :name => "poly_params_request_index", :unique => false
add_index :impressions, :user_id add_index :impressions, :user_id
end end

View File

@ -41,6 +41,7 @@ ActiveRecord::Schema.define(:version => 20150207140310) do
t.string "ip_address" t.string "ip_address"
t.string "session_hash" t.string "session_hash"
t.text "message" t.text "message"
t.text "params"
t.text "referrer" t.text "referrer"
t.datetime "created_at", :null => false t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
@ -50,6 +51,7 @@ ActiveRecord::Schema.define(:version => 20150207140310) do
add_index "impressions", ["controller_name", "action_name", "request_hash"], :name => "controlleraction_request_index" add_index "impressions", ["controller_name", "action_name", "request_hash"], :name => "controlleraction_request_index"
add_index "impressions", ["controller_name", "action_name", "session_hash"], :name => "controlleraction_session_index" add_index "impressions", ["controller_name", "action_name", "session_hash"], :name => "controlleraction_session_index"
add_index "impressions", ["impressionable_type", "impressionable_id", "ip_address"], :name => "poly_ip_index" add_index "impressions", ["impressionable_type", "impressionable_id", "ip_address"], :name => "poly_ip_index"
add_index "impressions", ["impressionable_type", "impressionable_id", "params"], :name => "poly_params_request_index"
add_index "impressions", ["impressionable_type", "impressionable_id", "request_hash"], :name => "poly_request_index" add_index "impressions", ["impressionable_type", "impressionable_id", "request_hash"], :name => "poly_request_index"
add_index "impressions", ["impressionable_type", "impressionable_id", "session_hash"], :name => "poly_session_index" add_index "impressions", ["impressionable_type", "impressionable_id", "session_hash"], :name => "poly_session_index"
add_index "impressions", ["impressionable_type", "message", "impressionable_id"], :name => "impressionable_type_message_index" add_index "impressions", ["impressionable_type", "message", "impressionable_id"], :name => "impressionable_type_message_index"

View File

@ -53,8 +53,24 @@ describe ArticlesController do
click_link "Same Page" click_link "Same Page"
Impression.last.referrer.should eq "http://test.host/articles/1" Impression.last.referrer.should eq "http://test.host/articles/1"
end end
it "should log request with params (checked = true)" do
get "show", id: 1, checked: true
Impression.last.params.should eq({"checked"=>true})
Impression.last.request_hash.size.should eq 64
Impression.last.ip_address.should eq "0.0.0.0"
Impression.last.session_hash.size.should eq 32
Impression.last.referrer.should eq nil
end
it "should log request with params {}" do
get "index"
Impression.last.params.should eq({})
Impression.last.request_hash.size.should eq 64
Impression.last.ip_address.should eq "0.0.0.0"
Impression.last.session_hash.size.should eq 32
Impression.last.referrer.should eq nil
end
end end

View File

@ -16,4 +16,13 @@ describe PostsController do
Post.first.impressions.last.user_id.should eq 123 Post.first.impressions.last.user_id.should eq 123
end end
it "should log impression at the action level with params" do
get "show", id: 1, checked: true
Impression.all.size.should eq 12
Impression.last.params.should eq({"checked"=>true})
Impression.last.controller_name.should eq "posts"
Impression.last.action_name.should eq "show"
Impression.last.impressionable_type.should eq "Post"
Impression.last.impressionable_id.should eq 1
end
end end

View File

@ -44,7 +44,6 @@ describe WidgetsController do
it "should log unique impressions only once per id" do it "should log unique impressions only once per id" do
get "show", :id=> 1 get "show", :id=> 1
Impression.all.size.should eq 12 Impression.all.size.should eq 12
get "show", :id=> 2 get "show", :id=> 2
Impression.all.size.should eq 13 Impression.all.size.should eq 13
@ -57,4 +56,36 @@ describe WidgetsController do
end end
context "Impresionist unique params options" do
it "should log unique impressions at the per action and params level" do
get "show", :id => 1
Impression.all.size.should eq 12
get "show", :id => 2, checked: true
Impression.all.size.should eq 13
get "show", :id => 2, checked: false
Impression.all.size.should eq 14
get "index"
Impression.all.size.should eq 15
end
it "should not log impression for same params and same id" do
get "show", :id => 1
Impression.all.size.should eq 12
get "show", :id => 1
Impression.all.size.should eq 12
get "show", :id => 1, checked: true
Impression.all.size.should eq 13
get "show", :id => 1, checked: false
Impression.all.size.should eq 14
get "show", :id => 1, checked: true
Impression.all.size.should eq 14
get "show", :id => 1, checked: false
Impression.all.size.should eq 14
get "show", :id => 1
Impression.all.size.should eq 14
get "show", :id => 2
Impression.all.size.should eq 15
end
end
end end