Merge pull request #13 from georgmittendorfer/feature-unique

Unique impressions
This commit is contained in:
John McAliley 2011-11-15 18:43:51 -08:00
commit b6a001d6e9
11 changed files with 521 additions and 136 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ Gemfile.lock
/test_app/db/migrate/20*
/test_app/db/schema.rb
/pkg
*~

View File

@ -3,27 +3,23 @@ require 'digest/sha2'
module ImpressionistController
module ClassMethods
def impressionist(opts={})
before_filter { |c| c.impressionist_subapp_filter opts[:actions] }
before_filter { |c| c.impressionist_subapp_filter(opts[:actions], opts[:unique])}
end
end
module InstanceMethods
def self.included(base)
base.before_filter :impressionist_app_filter
end
def impressionist(obj,message=nil)
def impressionist(obj,message=nil,opts={})
unless bypass
if obj.respond_to?("impressionable?")
obj.impressions.create(:message=> message,
:request_hash=> @impressionist_hash,
:session_hash=> request.session_options[:id],
:ip_address=> request.remote_ip,
:user_id=> user_id,
:controller_name=>controller_name,
:action_name=> action_name,
:referrer=>request.referer)
if unique_instance?(obj, opts[:unique])
obj.impressions.create(associative_create_statement({:message => message}))
end
else
# we could create an impression anyway. for classes, too. why not?
raise "#{obj.class.to_s} is not impressionable!"
end
end
@ -33,31 +29,73 @@ module ImpressionistController
@impressionist_hash = Digest::SHA2.hexdigest(Time.now.to_f.to_s+rand(10000).to_s)
end
def impressionist_subapp_filter(actions=nil)
def impressionist_subapp_filter(actions=nil,unique_opts=nil)
unless bypass
actions.collect!{|a|a.to_s} unless actions.blank?
if actions.blank? or actions.include?(action_name)
Impression.create(:controller_name=> controller_name,
:action_name=> action_name,
:user_id=> user_id,
:request_hash=> @impressionist_hash,
:session_hash=> request.session_options[:id],
:ip_address=> request.remote_ip,
:impressionable_type=> controller_name.singularize.camelize,
:impressionable_id=> params[:id],
:referrer=>request.referer)
if (actions.blank? || actions.include?(action_name)) && unique?(unique_opts)
Impression.create(direct_create_statement)
end
end
end
private
def bypass
Impressionist::Bots::WILD_CARDS.each do |wild_card|
return true if request.user_agent and request.user_agent.downcase.include? wild_card
end
Impressionist::Bots::LIST.include? request.user_agent
end
def unique_instance?(impressionable, unique_opts)
return unique_opts.blank? || impressionable.impressions.where(unique_query(unique_opts)).size == 0
end
def unique?(unique_opts)
return unique_opts.blank? || Impression.where(unique_query(unique_opts)).size == 0
end
# creates the query to check for uniqueness
def unique_query(unique_opts)
full_statement = direct_create_statement
# reduce the full statement to the params we need for the specified unique options
unique_opts.reduce({}) do |query, param|
query[param] = full_statement[param]
query
end
end
# creates a statment hash that contains default values for creating an impression via an AR relation.
def associative_create_statement(query_params={})
query_params.reverse_merge!(
:controller_name => controller_name,
:action_name => action_name,
:user_id => user_id,
:request_hash => @impressionist_hash,
:session_hash => session_hash,
:ip_address => request.remote_ip,
:referrer => request.referer
)
end
# creates a statment hash that contains default values for creating an impression.
def direct_create_statement(query_params={})
query_params.reverse_merge!(
:impressionable_type => controller_name.singularize.camelize,
:impressionable_id=> params[:id]
)
associative_create_statement(query_params)
end
def session_hash
# # careful: request.session_options[:id] encoding in rspec test was ASCII-8BIT
# # that broke the database query for uniqueness. not sure if this is a testing only issue.
# str = request.session_options[:id]
# logger.debug "Encoding: #{str.encoding.inspect}"
# # request.session_options[:id].encode("ISO-8859-1")
request.session_options[:id]
end
#use both @current_user and current_user helper
def user_id
user_id = @current_user ? @current_user.id : nil rescue nil

View File

@ -1,9 +1,9 @@
source 'http://rubygems.org'
gem 'rails', '3.1.0.rc1'
gem 'rails', '3.1'
gem 'sqlite3-ruby', :require => 'sqlite3'
gem 'impressionist', :path=>"#{File.dirname(__FILE__)}/../"
gem "pg"
#gem "pg"
group :development do
gem 'ZenTest'

View File

@ -1,155 +1,156 @@
PATH
remote: /rails_plugins/mine/impressionist
remote: /home/mio/prog/projects/impressionist
specs:
impressionist (0.3.2)
impressionist (0.4.0)
GEM
remote: http://rubygems.org/
specs:
ZenTest (4.5.0)
actionmailer (3.1.0.rc1)
actionpack (= 3.1.0.rc1)
ZenTest (4.6.2)
actionmailer (3.1.0)
actionpack (= 3.1.0)
mail (~> 2.3.0)
actionpack (3.1.0.rc1)
activemodel (= 3.1.0.rc1)
activesupport (= 3.1.0.rc1)
actionpack (3.1.0)
activemodel (= 3.1.0)
activesupport (= 3.1.0)
builder (~> 3.0.0)
erubis (~> 2.7.0)
i18n (~> 0.6.0beta1)
rack (~> 1.3.0.beta2)
rack-cache (~> 1.0.1)
rack-mount (~> 0.8.1)
rack-test (~> 0.6.0)
sprockets (~> 2.0.0.beta.5)
tzinfo (~> 0.3.27)
activemodel (3.1.0.rc1)
activesupport (= 3.1.0.rc1)
bcrypt-ruby (~> 2.1.4)
i18n (~> 0.6)
rack (~> 1.3.2)
rack-cache (~> 1.0.3)
rack-mount (~> 0.8.2)
rack-test (~> 0.6.1)
sprockets (~> 2.0.0)
activemodel (3.1.0)
activesupport (= 3.1.0)
bcrypt-ruby (~> 3.0.0)
builder (~> 3.0.0)
i18n (~> 0.6.0beta1)
activerecord (3.1.0.rc1)
activemodel (= 3.1.0.rc1)
activesupport (= 3.1.0.rc1)
arel (~> 2.1.1)
tzinfo (~> 0.3.27)
activeresource (3.1.0.rc1)
activemodel (= 3.1.0.rc1)
activesupport (= 3.1.0.rc1)
activesupport (3.1.0.rc1)
i18n (~> 0.6)
activerecord (3.1.0)
activemodel (= 3.1.0)
activesupport (= 3.1.0)
arel (~> 2.2.1)
tzinfo (~> 0.3.29)
activeresource (3.1.0)
activemodel (= 3.1.0)
activesupport (= 3.1.0)
activesupport (3.1.0)
multi_json (~> 1.0)
arel (2.1.1)
addressable (2.2.6)
arel (2.2.1)
autotest (4.4.6)
ZenTest (>= 4.4.1)
autotest-notification (2.3.1)
autotest (~> 4.3)
bcrypt-ruby (2.1.4)
autotest-notification (2.3.3)
autotest-standalone (~> 4.5)
autotest-standalone (4.5.8)
bcrypt-ruby (3.0.1)
builder (3.0.0)
capybara (1.0.0.beta1)
capybara (1.1.1)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
selenium-webdriver (>= 0.0.27)
selenium-webdriver (~> 2.0)
xpath (~> 0.1.4)
childprocess (0.1.9)
childprocess (0.2.2)
ffi (~> 1.0.6)
configuration (1.2.0)
cucumber (0.10.3)
cucumber (1.1.1)
builder (>= 2.1.2)
diff-lcs (>= 1.1.2)
gherkin (>= 2.3.8)
gherkin (~> 2.6.0)
json (>= 1.4.6)
term-ansicolor (>= 1.0.5)
cucumber-rails (0.5.1)
capybara (>= 1.0.0.beta1)
cucumber (>= 0.10.3)
nokogiri (>= 1.4.4)
rack-test (>= 0.5.7)
term-ansicolor (>= 1.0.6)
cucumber-rails (1.2.0)
capybara (>= 1.1.1)
cucumber (>= 1.1.1)
nokogiri (>= 1.5.0)
daemons (1.0.10)
database_cleaner (0.6.7)
diff-lcs (1.1.2)
diff-lcs (1.1.3)
erubis (2.7.0)
ffi (1.0.9)
gem_plugin (0.2.3)
gherkin (2.3.10)
gherkin (2.6.2)
json (>= 1.4.6)
hike (1.0.0)
hike (1.2.1)
i18n (0.6.0)
json (1.5.1)
json_pure (1.5.1)
launchy (0.4.0)
configuration (>= 0.0.5)
rake (>= 0.8.1)
json (1.6.1)
json_pure (1.6.1)
launchy (2.0.5)
addressable (~> 2.2.6)
mail (2.3.0)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.16)
mime-types (1.17.2)
mongrel (1.2.0.pre2)
daemons (~> 1.0.10)
gem_plugin (~> 0.2.3)
multi_json (1.0.3)
nokogiri (1.4.4)
pg (0.11.0)
polyglot (0.3.1)
rack (1.3.0)
rack-cache (1.0.2)
nokogiri (1.5.0)
polyglot (0.3.3)
rack (1.3.5)
rack-cache (1.0.3)
rack (>= 0.4)
rack-mount (0.8.1)
rack-mount (0.8.3)
rack (>= 1.0.0)
rack-ssl (1.3.2)
rack
rack-test (0.6.0)
rack-test (0.6.1)
rack (>= 1.0)
rails (3.1.0.rc1)
actionmailer (= 3.1.0.rc1)
actionpack (= 3.1.0.rc1)
activerecord (= 3.1.0.rc1)
activeresource (= 3.1.0.rc1)
activesupport (= 3.1.0.rc1)
rails (3.1.0)
actionmailer (= 3.1.0)
actionpack (= 3.1.0)
activerecord (= 3.1.0)
activeresource (= 3.1.0)
activesupport (= 3.1.0)
bundler (~> 1.0)
railties (= 3.1.0.rc1)
railties (3.1.0.rc1)
actionpack (= 3.1.0.rc1)
activesupport (= 3.1.0.rc1)
railties (= 3.1.0)
railties (3.1.0)
actionpack (= 3.1.0)
activesupport (= 3.1.0)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.6)
rake (0.9.1)
rspec (2.6.0)
rspec-core (~> 2.6.0)
rspec-expectations (~> 2.6.0)
rspec-mocks (~> 2.6.0)
rspec-core (2.6.3)
rspec-expectations (2.6.0)
rake (0.9.2.2)
rdoc (3.11)
json (~> 1.4)
rspec (2.7.0)
rspec-core (~> 2.7.0)
rspec-expectations (~> 2.7.0)
rspec-mocks (~> 2.7.0)
rspec-core (2.7.1)
rspec-expectations (2.7.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.6.0)
rspec-rails (2.6.1)
rspec-mocks (2.7.0)
rspec-rails (2.7.0)
actionpack (~> 3.0)
activesupport (~> 3.0)
railties (~> 3.0)
rspec (~> 2.6.0)
rspec (~> 2.7.0)
rubyzip (0.9.4)
selenium-webdriver (0.2.1)
childprocess (>= 0.1.7)
ffi (>= 1.0.7)
selenium-webdriver (2.10.0)
childprocess (>= 0.2.1)
ffi (= 1.0.9)
json_pure
rubyzip
spork (0.8.5)
sprockets (2.0.0.beta.9)
hike (~> 1.0)
sprockets (2.0.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.3)
sqlite3 (1.3.4)
sqlite3-ruby (1.3.3)
sqlite3 (>= 1.3.3)
systemu (2.2.0)
term-ansicolor (1.0.5)
systemu (2.4.1)
term-ansicolor (1.0.7)
thor (0.14.6)
tilt (1.3.2)
treetop (1.4.9)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.27)
tzinfo (0.3.31)
xpath (0.1.4)
nokogiri (~> 1.3)
@ -167,8 +168,7 @@ DEPENDENCIES
impressionist!
launchy
mongrel (= 1.2.0.pre2)
pg
rails (= 3.1.0.rc1)
rails (= 3.1)
rspec
rspec-rails
spork

View File

@ -0,0 +1,6 @@
# This controller imports the impressionist module to make the modules methods available for testing
class DummyController < ActionController::Base
impressionist
end

View File

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

View File

@ -6,28 +6,19 @@ development:
pool: 5
timeout: 5000
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
#test: &test
# adapter: sqlite3
# database: db/test.sqlite3
# pool: 5
# timeout: 5000
test:
test: &test
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000
pg_test:
adapter: postgresql
database: impressionist_test
username: johnmcaliley
password:
host: localhost
encoding: UTF8
#pg_test:
# adapter: postgresql
# database: impressionist_test
# username: johnmcaliley
# password:
# host: localhost
# encoding: UTF8
production:
adapter: sqlite3

View File

@ -89,5 +89,32 @@ describe WidgetsController do
get "show", :id=> 1
Impression.all.size.should eq 11
end
describe "impressionist unique options" do
it "should log unique impressions at the per action level" do
get "show", :id=> 1
Impression.all.size.should eq 12
get "show", :id=> 2
Impression.all.size.should eq 13
get "show", :id => 2
Impression.all.size.should eq 13
get "index"
Impression.all.size.should eq 14
end
it "should log unique impressions only once per id" do
get "show", :id=> 1
Impression.all.size.should eq 12
get "show", :id=> 2
Impression.all.size.should eq 13
get "show", :id => 2
Impression.all.size.should eq 13
get "index"
Impression.all.size.should eq 14
end
end
end

View File

@ -0,0 +1,312 @@
require "spec_helper.rb"
# we use the posts controller as it uses the impressionsist module. any such controller would do.
describe DummyController do
before do
@impression_count = Impression.all.size
end
describe "impressionist filter uniqueness" do
it "should ignore uniqueness if not requested" do
controller.impressionist_subapp_filter(nil, nil)
controller.impressionist_subapp_filter(nil, nil)
Impression.should have(@impression_count + 2).records
end
it "should recognize unique session" do
# the following line was necessary as session hash returned a binary string (ASCII-8BIT encoded)
controller.stub!(:session_hash).and_return(request.session_options[:id].encode("ISO-8859-1"))
controller.impressionist_subapp_filter(nil, [:session_hash])
controller.impressionist_subapp_filter(nil, [:session_hash])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique ip" do
controller.request.stub!(:remote_ip).and_return("1.2.3.4")
controller.impressionist_subapp_filter(nil, [:ip_address])
controller.impressionist_subapp_filter(nil, [:ip_address])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique request" do
controller.impressionist_subapp_filter(nil, [:request_hash])
controller.impressionist_subapp_filter(nil, [:request_hash])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique action" do
controller.stub!(:action_name).and_return("test_action")
controller.impressionist_subapp_filter(nil, [:action_name])
controller.impressionist_subapp_filter(nil, [:action_name])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique controller" do
controller.stub!(:controller_name).and_return("test_controller")
controller.impressionist_subapp_filter(nil, [:controller_name])
controller.impressionist_subapp_filter(nil, [:controller_name])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique user" do
controller.stub!(:user_id).and_return(42)
controller.impressionist_subapp_filter(nil, [:user_id])
controller.impressionist_subapp_filter(nil, [:user_id])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique referer" do
controller.request.stub!(:referer).and_return("http://foo/bar")
controller.impressionist_subapp_filter(nil, [:referrer])
controller.impressionist_subapp_filter(nil, [:referrer])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique id" do
controller.stub!(:params).and_return({:id => "666"}) # for correct impressionable id in filter
controller.impressionist_subapp_filter(nil, [:impressionable_id])
controller.impressionist_subapp_filter(nil, [:impressionable_id])
Impression.should have(@impression_count + 1).records
end
# extra redundant test for important controller and action combination.
it "should recognize different controller and action" do
controller.stub!(:controller_name).and_return("test_controller")
controller.stub!(:action_name).and_return("test_action")
controller.impressionist_subapp_filter(nil, [:controller_name, :action_name])
controller.impressionist_subapp_filter(nil, [:controller_name, :action_name])
Impression.should have(@impression_count + 1).records
controller.stub!(:action_name).and_return("another_action")
controller.impressionist_subapp_filter(nil, [:controller_name, :action_name])
controller.impressionist_subapp_filter(nil, [:controller_name, :action_name])
Impression.should have(@impression_count + 2).records
controller.stub!(:controller_name).and_return("another_controller")
controller.impressionist_subapp_filter(nil, [:controller_name, :action_name])
controller.impressionist_subapp_filter(nil, [:controller_name, :action_name])
Impression.should have(@impression_count + 3).records
end
it "should recognize different action" do
controller.stub!(:action_name).and_return("test_action")
controller.impressionist_subapp_filter(nil, [:action_name])
controller.impressionist_subapp_filter(nil, [:action_name])
Impression.should have(@impression_count + 1).records
controller.stub!(:action_name).and_return("another_action")
controller.impressionist_subapp_filter(nil, [:action_name])
controller.impressionist_subapp_filter(nil, [:action_name])
Impression.should have(@impression_count + 2).records
end
it "should recognize different controller" do
controller.stub!(:controller_name).and_return("test_controller")
controller.impressionist_subapp_filter(nil, [:controller_name])
controller.impressionist_subapp_filter(nil, [:controller_name])
Impression.should have(@impression_count + 1).records
controller.stub!(:controller_name).and_return("another_controller")
controller.impressionist_subapp_filter(nil, [:controller_name])
controller.impressionist_subapp_filter(nil, [:controller_name])
Impression.should have(@impression_count + 2).records
end
it "should recognize different session" do
controller.stub!(:session_hash).and_return("foo")
controller.impressionist_subapp_filter(nil, [:session_hash])
controller.impressionist_subapp_filter(nil, [:session_hash])
Impression.should have(@impression_count + 1).records
controller.stub!(:session_hash).and_return("bar")
controller.impressionist_subapp_filter(nil, [:session_hash])
controller.impressionist_subapp_filter(nil, [:session_hash])
Impression.should have(@impression_count + 2).records
end
it "should recognize different ip" do
controller.request.stub!(:remote_ip).and_return("1.2.3.4")
controller.impressionist_subapp_filter(nil, [:ip_address])
controller.impressionist_subapp_filter(nil, [:ip_address])
Impression.should have(@impression_count + 1).records
controller.request.stub!(:remote_ip).and_return("5.6.7.8")
controller.impressionist_subapp_filter(nil, [:ip_address])
controller.impressionist_subapp_filter(nil, [:ip_address])
Impression.should have(@impression_count + 2).records
end
it "should recognize different referer" do
controller.request.stub!(:referer).and_return("http://foo/bar")
controller.impressionist_subapp_filter(nil, [:referrer])
controller.impressionist_subapp_filter(nil, [:referrer])
Impression.should have(@impression_count + 1).records
controller.request.stub!(:referer).and_return("http://bar/fo")
controller.impressionist_subapp_filter(nil, [:referrer])
controller.impressionist_subapp_filter(nil, [:referrer])
Impression.should have(@impression_count + 2).records
end
it "should recognize different id" do
controller.stub!(:params).and_return({:id => "666"}) # for correct impressionable id in filter
controller.impressionist_subapp_filter(nil, [:impressionable_type, :impressionable_id])
controller.impressionist_subapp_filter(nil, [:impressionable_type, :impressionable_id])
controller.stub!(:params).and_return({:id => "42"}) # for correct impressionable id in filter
controller.impressionist_subapp_filter(nil, [:impressionable_type, :impressionable_id])
controller.impressionist_subapp_filter(nil, [:impressionable_type, :impressionable_id])
Impression.should have(@impression_count + 2).records
end
it "should recognize combined uniqueness" do
controller.stub!(:action_name).and_return("test_action")
controller.impressionist_subapp_filter(nil, [:ip_address, :request_hash, :action_name])
controller.impressionist_subapp_filter(nil, [:request_hash, :ip_address, :action_name])
controller.impressionist_subapp_filter(nil, [:request_hash, :action_name])
controller.impressionist_subapp_filter(nil, [:ip_address, :action_name])
controller.impressionist_subapp_filter(nil, [:ip_address, :request_hash])
controller.impressionist_subapp_filter(nil, [:action_name])
controller.impressionist_subapp_filter(nil, [:ip_address])
controller.impressionist_subapp_filter(nil, [:request_hash])
Impression.should have(@impression_count + 1).records
end
it "should recognize combined non-uniqueness" do
controller.stub!(:action_name).and_return(nil)
controller.impressionist_subapp_filter(nil, [:ip_address, :action_name])
controller.stub!(:action_name).and_return("test_action")
controller.impressionist_subapp_filter(nil, [:ip_address, :action_name])
controller.stub!(:action_name).and_return("another_action")
controller.impressionist_subapp_filter(nil, [:ip_address, :action_name])
Impression.should have(@impression_count + 3).records
end
end
describe "impressionist method uniqueness for impressionables" do
# in this test we reuse the post model. might break if model changes.
it "should ignore uniqueness if not requested" do
impressionable = Post.create
controller.impressionist impressionable
controller.impressionist impressionable
Impression.should have(@impression_count + 2).records
end
it "should recognize unique session" do
# the following line was necessary as session hash returned a binary string (ASCII-8BIT encoded)
controller.stub!(:session_hash).and_return(request.session_options[:id].encode("ISO-8859-1"))
impressionable = Post.create
controller.impressionist(impressionable, nil, :unique => [:session_hash])
controller.impressionist(impressionable, nil, :unique => [:session_hash])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique ip" do
controller.request.stub!(:remote_ip).and_return("1.2.3.4")
impressionable = Post.create
controller.impressionist(impressionable, nil, :unique => [:ip_address])
controller.impressionist(impressionable, nil, :unique => [:ip_address])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique request" do
impressionable = Post.create
controller.impressionist(impressionable, nil, :unique => [:request_hash])
controller.impressionist(impressionable, nil, :unique => [:request_hash])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique user" do
controller.stub!(:user_id).and_return(666)
impressionable = Post.create
controller.impressionist(impressionable, nil, :unique => [:user_id])
controller.impressionist(impressionable, nil, :unique => [:user_id])
Impression.should have(@impression_count + 1).records
end
it "should recognize unique referer" do
controller.request.stub!(:referer).and_return("http://foo/bar")
impressionable = Post.create
controller.impressionist(impressionable, nil, :unique => [:referrer])
controller.impressionist(impressionable, nil, :unique => [:referrer])
Impression.should have(@impression_count + 1).records
end
it "should recognize different session" do
impressionable = Post.create
controller.stub!(:session_hash).and_return("foo")
controller.impressionist(impressionable, nil, :unique => [:session_hash])
controller.impressionist(impressionable, nil, :unique => [:session_hash])
Impression.should have(@impression_count + 1).records
controller.stub!(:session_hash).and_return("bar")
controller.impressionist(impressionable, nil, :unique => [:session_hash])
controller.impressionist(impressionable, nil, :unique => [:session_hash])
Impression.should have(@impression_count + 2).records
end
it "should recognize different ip" do
controller.request.stub!(:remote_ip).and_return("1.2.3.4")
impressionable = Post.create
controller.impressionist(impressionable, nil, :unique => [:ip_address])
controller.impressionist(impressionable, nil, :unique => [:ip_address])
Impression.should have(@impression_count + 1).records
controller.request.stub!(:remote_ip).and_return("5.6.7.8")
controller.impressionist(impressionable, nil, :unique => [:ip_address])
controller.impressionist(impressionable, nil, :unique => [:ip_address])
Impression.should have(@impression_count + 2).records
end
it "should recognize different user" do
impressionable = Post.create
controller.stub!(:user_id).and_return(666)
controller.impressionist(impressionable, nil, :unique => [:user_id])
controller.impressionist(impressionable, nil, :unique => [:user_id])
Impression.should have(@impression_count + 1).records
controller.stub!(:user_id).and_return(42)
controller.impressionist(impressionable, nil, :unique => [:user_id])
controller.impressionist(impressionable, nil, :unique => [:user_id])
Impression.should have(@impression_count + 2).records
end
it "should recognize combined uniqueness" do
impressionable = Post.create
controller.stub!(:session_hash).and_return("foo")
controller.impressionist(impressionable, nil, :unique => [:ip_address, :request_hash, :session_hash])
controller.impressionist(impressionable, nil, :unique => [:request_hash, :ip_address, :session_hash])
controller.impressionist(impressionable, nil, :unique => [:request_hash, :session_hash])
controller.impressionist(impressionable, nil, :unique => [:ip_address, :session_hash])
controller.impressionist(impressionable, nil, :unique => [:ip_address, :request_hash])
controller.impressionist(impressionable, nil, :unique => [:session_hash])
controller.impressionist(impressionable, nil, :unique => [:ip_address])
controller.impressionist(impressionable, nil, :unique => [:request_hash])
Impression.should have(@impression_count + 1).records
end
it "should recognize combined non-uniqueness" do
impressionable = Post.create
controller.stub!(:session_hash).and_return(nil)
controller.impressionist(impressionable, nil, :unique => [:ip_address, :session_hash])
controller.stub!(:session_hash).and_return("foo")
controller.impressionist(impressionable, nil, :unique => [:ip_address, :session_hash])
controller.stub!(:session_hash).and_return("bar")
controller.impressionist(impressionable, nil, :unique => [:ip_address, :session_hash])
Impression.should have(@impression_count + 3).records
end
end
describe "impressionist filter and method uniqueness" do
it "should recognize uniqueness" do
impressionable = Post.create
controller.stub!(:controller_name).and_return("posts") # for correct impressionable type in filter
controller.stub!(:params).and_return({:id => impressionable.id.to_s}) # for correct impressionable id in filter
controller.stub!(:session_hash).and_return("foo")
controller.request.stub!(:remote_ip).and_return("1.2.3.4")
# order of the following methods is important for the test!
controller.impressionist_subapp_filter(nil, [:ip_address, :request_hash, :session_hash])
controller.impressionist(impressionable, nil, :unique => [:ip_address, :request_hash, :session_hash])
Impression.should have(@impression_count + 1).records
end
end
end

View File

@ -1,6 +1,8 @@
require 'spec_helper'
require 'systemu'
# FIXME this test might break the others if run before them
#
describe Impressionist do
fixtures :articles,:impressions,:posts
it "should delete existing migration and generate the migration file" do

View File

@ -24,4 +24,10 @@ RSpec.configure do |config|
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# make the rails logger usable in the tests as logger.xxx "..."
def logger
Rails.logger
end
end