impressionist2 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.travis.yml +26 -0
- data/CHANGELOG.rdoc +82 -0
- data/Gemfile +26 -0
- data/LICENSE.txt +20 -0
- data/README.md +250 -0
- data/Rakefile +34 -0
- data/app/controllers/impressionist_controller.rb +146 -0
- data/app/models/impression.rb +2 -0
- data/app/models/impressionist/bots.rb +1468 -0
- data/app/models/impressionist/impressionable.rb +62 -0
- data/gemfiles/rails32.gemfile +30 -0
- data/gemfiles/rails40.gemfile +30 -0
- data/gemfiles/rails50.gemfile +30 -0
- data/impressionist2.gemspec +23 -0
- data/lib/generators/active_record/impressionist_generator.rb +22 -0
- data/lib/generators/active_record/templates/create_impressions_table.rb +32 -0
- data/lib/generators/impressionist_generator.rb +13 -0
- data/lib/generators/mongo_mapper/impressionist_generator.rb +8 -0
- data/lib/generators/mongoid/impressionist_generator.rb +8 -0
- data/lib/generators/templates/impression.rb +8 -0
- data/lib/impressionist/bots.rb +21 -0
- data/lib/impressionist/controllers/mongoid/impressionist_controller.rb +10 -0
- data/lib/impressionist/counter_cache.rb +73 -0
- data/lib/impressionist/engine.rb +30 -0
- data/lib/impressionist/is_impressionable.rb +23 -0
- data/lib/impressionist/load.rb +11 -0
- data/lib/impressionist/models/active_record/impression.rb +14 -0
- data/lib/impressionist/models/active_record/impressionist/impressionable.rb +12 -0
- data/lib/impressionist/models/mongo_mapper/impression.rb +18 -0
- data/lib/impressionist/models/mongo_mapper/impressionist/impressionable.rb +21 -0
- data/lib/impressionist/models/mongoid/impression.rb +25 -0
- data/lib/impressionist/models/mongoid/impressionist/impressionable.rb +28 -0
- data/lib/impressionist/rails_toggle.rb +26 -0
- data/lib/impressionist/setup_association.rb +49 -0
- data/lib/impressionist/update_counters.rb +69 -0
- data/lib/impressionist/version.rb +3 -0
- data/lib/impressionist.rb +12 -0
- data/logo.png +0 -0
- data/tests/README +11 -0
- data/tests/spec/minitest_helper.rb +4 -0
- data/tests/spec/rails_toggle_spec.rb +38 -0
- data/tests/spec/setup_association_spec.rb +56 -0
- data/tests/test_app/.gitignore +18 -0
- data/tests/test_app/.rspec +1 -0
- data/tests/test_app/Gemfile +51 -0
- data/tests/test_app/README +256 -0
- data/tests/test_app/README.rdoc +261 -0
- data/tests/test_app/Rakefile +7 -0
- data/tests/test_app/app/assets/images/rails.png +0 -0
- data/tests/test_app/app/assets/javascripts/application.js +13 -0
- data/tests/test_app/app/assets/stylesheets/application.css +13 -0
- data/tests/test_app/app/controllers/application_controller.rb +8 -0
- data/tests/test_app/app/controllers/articles_controller.rb +18 -0
- data/tests/test_app/app/controllers/dummy_controller.rb +8 -0
- data/tests/test_app/app/controllers/posts_controller.rb +23 -0
- data/tests/test_app/app/controllers/profiles_controller.rb +14 -0
- data/tests/test_app/app/controllers/widgets_controller.rb +12 -0
- data/tests/test_app/app/helpers/application_helper.rb +2 -0
- data/tests/test_app/app/mailers/.gitkeep +0 -0
- data/tests/test_app/app/models/.gitkeep +0 -0
- data/tests/test_app/app/models/article.rb +3 -0
- data/tests/test_app/app/models/dummy.rb +7 -0
- data/tests/test_app/app/models/post.rb +3 -0
- data/tests/test_app/app/models/profile.rb +6 -0
- data/tests/test_app/app/models/user.rb +3 -0
- data/tests/test_app/app/models/widget.rb +3 -0
- data/tests/test_app/app/views/articles/index.html.erb +1 -0
- data/tests/test_app/app/views/articles/show.html.erb +1 -0
- data/tests/test_app/app/views/dummy/index.html.erb +0 -0
- data/tests/test_app/app/views/layouts/application.html.erb +14 -0
- data/tests/test_app/app/views/posts/edit.html.erb +0 -0
- data/tests/test_app/app/views/posts/index.html.erb +0 -0
- data/tests/test_app/app/views/posts/show.html.erb +0 -0
- data/tests/test_app/app/views/profiles/show.html.erb +3 -0
- data/tests/test_app/app/views/widgets/index.html.erb +0 -0
- data/tests/test_app/app/views/widgets/new.html.erb +0 -0
- data/tests/test_app/app/views/widgets/show.html.erb +0 -0
- data/tests/test_app/config/application.rb +59 -0
- data/tests/test_app/config/boot.rb +6 -0
- data/tests/test_app/config/cucumber.yml +8 -0
- data/tests/test_app/config/database.yml +30 -0
- data/tests/test_app/config/environment.rb +5 -0
- data/tests/test_app/config/environments/development.rb +37 -0
- data/tests/test_app/config/environments/pg_test.rb +35 -0
- data/tests/test_app/config/environments/production.rb +67 -0
- data/tests/test_app/config/environments/test.rb +37 -0
- data/tests/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/tests/test_app/config/initializers/impression.rb +8 -0
- data/tests/test_app/config/initializers/inflections.rb +15 -0
- data/tests/test_app/config/initializers/mime_types.rb +5 -0
- data/tests/test_app/config/initializers/secret_token.rb +7 -0
- data/tests/test_app/config/initializers/session_store.rb +8 -0
- data/tests/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/tests/test_app/config/locales/en.yml +5 -0
- data/tests/test_app/config/routes.rb +4 -0
- data/tests/test_app/config.ru +4 -0
- data/tests/test_app/db/migrate/20110201153144_create_articles.rb +13 -0
- data/tests/test_app/db/migrate/20110210205028_create_posts.rb +13 -0
- data/tests/test_app/db/migrate/20111127184039_create_widgets.rb +15 -0
- data/tests/test_app/db/migrate/20130719024021_create_impressions_table.rb +32 -0
- data/tests/test_app/db/migrate/20150207135825_create_profiles.rb +10 -0
- data/tests/test_app/db/migrate/20150207140310_create_friendly_id_slugs.rb +18 -0
- data/tests/test_app/db/schema.rb +80 -0
- data/tests/test_app/db/seeds.rb +7 -0
- data/tests/test_app/lib/assets/.gitkeep +0 -0
- data/tests/test_app/lib/tasks/.gitkeep +0 -0
- data/tests/test_app/lib/tasks/cucumber.rake +53 -0
- data/tests/test_app/log/.gitkeep +0 -0
- data/tests/test_app/public/404.html +26 -0
- data/tests/test_app/public/422.html +26 -0
- data/tests/test_app/public/500.html +25 -0
- data/tests/test_app/public/favicon.ico +0 -0
- data/tests/test_app/public/images/rails.png +0 -0
- data/tests/test_app/public/index.html +241 -0
- data/tests/test_app/public/javascripts/application.js +2 -0
- data/tests/test_app/public/javascripts/controls.js +965 -0
- data/tests/test_app/public/javascripts/dragdrop.js +974 -0
- data/tests/test_app/public/javascripts/effects.js +1123 -0
- data/tests/test_app/public/javascripts/prototype.js +6001 -0
- data/tests/test_app/public/javascripts/rails.js +175 -0
- data/tests/test_app/public/robots.txt +5 -0
- data/tests/test_app/public/stylesheets/.gitkeep +0 -0
- data/tests/test_app/script/cucumber +10 -0
- data/tests/test_app/script/rails +6 -0
- data/tests/test_app/spec/controllers/articles_controller_spec.rb +76 -0
- data/tests/test_app/spec/controllers/dummy_controller_spec.rb +11 -0
- data/tests/test_app/spec/controllers/impressionist_uniqueness_spec.rb +396 -0
- data/tests/test_app/spec/controllers/posts_controller_spec.rb +28 -0
- data/tests/test_app/spec/controllers/widgets_controller_spec.rb +91 -0
- data/tests/test_app/spec/fixtures/articles.yml +3 -0
- data/tests/test_app/spec/fixtures/impressions.yml +43 -0
- data/tests/test_app/spec/fixtures/posts.yml +3 -0
- data/tests/test_app/spec/fixtures/profiles.yml +4 -0
- data/tests/test_app/spec/fixtures/widgets.yml +4 -0
- data/tests/test_app/spec/initializers/initializers_spec.rb +20 -0
- data/tests/test_app/spec/models/bots_spec.rb +27 -0
- data/tests/test_app/spec/models/counter_caching_spec.rb +51 -0
- data/tests/test_app/spec/models/model_spec.rb +70 -0
- data/tests/test_app/spec/rails_generators/rails_generators_spec.rb +23 -0
- data/tests/test_app/spec/spec_helper.rb +43 -0
- data/upgrade_migrations/version_0_3_0.rb +27 -0
- data/upgrade_migrations/version_0_4_0.rb +9 -0
- metadata +314 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7299ecfd37128db8e662cb4be2c69c264968f7b8
|
4
|
+
data.tar.gz: 7f86203d411036d87fe514868685beb07b67915d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4a31bbc1cf62ed5c0da878abb38dfcf1ef70b9747c432d3aa87d2413a911a767e0a7c750c20f942a00fd50a3e7525291c4add779b321216a69e2289a1eaf4bd3
|
7
|
+
data.tar.gz: d4477911efeacac44f762065709d6324f5b12121ee323ca11e1466c06aced8b5e5c3d6e5de11285945d1f628d670fc330d36665a31cfd31575da993c68433f2d
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
language: ruby
|
2
|
+
before_script:
|
3
|
+
- cd tests/test_app
|
4
|
+
- bundle exec rails g impressionist -f
|
5
|
+
- bundle exec rake db:create db:migrate RAILS_ENV=test
|
6
|
+
- cd ..
|
7
|
+
rvm:
|
8
|
+
- 1.9.3
|
9
|
+
- 2.0.0
|
10
|
+
- jruby-head
|
11
|
+
- rbx
|
12
|
+
- ruby-head
|
13
|
+
gemfile:
|
14
|
+
- gemfiles/rails32.gemfile
|
15
|
+
- gemfiles/rails40.gemfile
|
16
|
+
matrix:
|
17
|
+
allow_failures:
|
18
|
+
- rvm: jruby-head
|
19
|
+
- rvm: rbx
|
20
|
+
- rvm: ruby-head
|
21
|
+
fast_finish: true
|
22
|
+
notifications:
|
23
|
+
email:
|
24
|
+
- acnalesso@yahoo.co.uk
|
25
|
+
- john@couponshack.com
|
26
|
+
- mmcmahand@gmail.com
|
data/CHANGELOG.rdoc
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
== 1.5.1 (2016-08-24)
|
2
|
+
* Fixed #214
|
3
|
+
* (@xiaopow)
|
4
|
+
|
5
|
+
== 1.5.0 (2013-12-30)
|
6
|
+
* Added message filtering.
|
7
|
+
* (@overovermind)
|
8
|
+
|
9
|
+
== 1.4.8 (2013-09-01)
|
10
|
+
* Fixed #108
|
11
|
+
* Clean up
|
12
|
+
* (@acnalesso)
|
13
|
+
|
14
|
+
== 1.4.7 (2013-08-30)
|
15
|
+
* Fixed #103 - Allow impressions to be saved without a Model
|
16
|
+
* Fixed #104 - Wrong Documentation
|
17
|
+
* (@acnalesso)
|
18
|
+
|
19
|
+
== 1.4.6 (2013-08-17)
|
20
|
+
* Fixed 106
|
21
|
+
* Count unique records in Rails 4
|
22
|
+
|
23
|
+
== 1.4.5 (2013-07-17)
|
24
|
+
* Fixed update_counters raising an exception #97
|
25
|
+
|
26
|
+
== 1.4.4 (2013-07-15)
|
27
|
+
* Updated templates/impression.rb
|
28
|
+
|
29
|
+
== 1.4.3 (2013-07-15)
|
30
|
+
* Fixed Generators #96
|
31
|
+
* Remove pending tests, added tags
|
32
|
+
|
33
|
+
== 1.4.2 (2013-07-12)
|
34
|
+
* Added Mongoid Support
|
35
|
+
* Support Rails > 3.1 < 4.0
|
36
|
+
* Fixed #93
|
37
|
+
* Fixed travis failing
|
38
|
+
* Added two new entities
|
39
|
+
* Added MiniTest, testing against impressionist ( RSpec still testing test_app, will be removed soon)
|
40
|
+
* Clean up
|
41
|
+
* Moved all tests into tests dir
|
42
|
+
|
43
|
+
== 1.4.1 (2013-07-07)
|
44
|
+
* Added test support
|
45
|
+
* fix trailing space
|
46
|
+
* Created individually rspec files
|
47
|
+
* (@nbit001)
|
48
|
+
|
49
|
+
== 1.4.0 (2013-07-06)
|
50
|
+
* Fixed #92
|
51
|
+
* Pass option to unique for updatind counter_cache
|
52
|
+
* Clean up code, make it human readable
|
53
|
+
* Changed README in order to explain new features
|
54
|
+
* (@nbit001)
|
55
|
+
|
56
|
+
== 1.3.3 (2013-06-27)
|
57
|
+
* Added Rails4 Branch in order to support rails 4
|
58
|
+
* Rails 4 and Strong Parameters compability. (@bennick).
|
59
|
+
|
60
|
+
== 1.3.1 (non specified)
|
61
|
+
* Change controller_path back to controller_name (@johnmcaliley)
|
62
|
+
|
63
|
+
|
64
|
+
== 0.4.0 (2011-06-03)
|
65
|
+
* Fix postgres bug
|
66
|
+
* New impression count method that accepts options for filter, start_date and end_date
|
67
|
+
* Add referrer to Impression model. YOU MUST RUN THE UPGRADE MIGRATION IF YOU ARE UPGRADING FROM 0.3.0
|
68
|
+
* UPGRADE MIGRATION = impressionist/upgrade_migrations/version_0_4_0.rb
|
69
|
+
* NOTE IF YOU ARE UPGRADING FROM 0.2.5 OR BELOW, YOU MUST RUN BOTH UPGRADE MIGRATIONS
|
70
|
+
|
71
|
+
== 0.3.0 (2011-03-06)
|
72
|
+
* added session_hash to impression model
|
73
|
+
* migration template updated to add session_hash
|
74
|
+
* new count instance method for impressionable model - unique_impression_count_session
|
75
|
+
* NOTE: if you are upgrading from 0.2.5, then run the migration in the 'upgrade_migrations' dir
|
76
|
+
|
77
|
+
== 0.2.5 (2011-02-17)
|
78
|
+
* New model method - @widget.unique_impression_count_ip - This gives you unique impression account filtered by IP (and in turn request_hash since they have same IPs)
|
79
|
+
* @widget.unique_impression_count now uses request_hash. This was incorrectly stated in the README, since it was using ip_address. The README is correct as a result of the method change.
|
80
|
+
|
81
|
+
== 0.2.4 (2011-02-17)
|
82
|
+
* Fix issue #1 - action_name and controller_name were not being logged for impressionist method inside action
|
data/Gemfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'rake', '>= 0.9'
|
4
|
+
gem 'rdoc', '>= 2.4.2'
|
5
|
+
|
6
|
+
platforms :jruby do
|
7
|
+
gem 'activerecord-jdbcsqlite3-adapter'
|
8
|
+
gem 'jdbc-sqlite3'
|
9
|
+
gem 'jruby-openssl'
|
10
|
+
end
|
11
|
+
|
12
|
+
platforms :ruby, :mswin, :mingw do
|
13
|
+
gem 'sqlite3'
|
14
|
+
end
|
15
|
+
|
16
|
+
group :test do
|
17
|
+
gem 'capybara', '>= 2.0.3'
|
18
|
+
gem 'minitest'
|
19
|
+
gem 'minitest-rails'
|
20
|
+
gem 'rails', '>= 3.2.15'
|
21
|
+
gem 'rspec-rails'
|
22
|
+
gem 'simplecov'
|
23
|
+
gem 'systemu'
|
24
|
+
end
|
25
|
+
|
26
|
+
gemspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 cowboycoded
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,250 @@
|
|
1
|
+

|
2
|
+
|
3
|
+
[](http://travis-ci.org/charlotte-ruby/impressionist)
|
4
|
+
[](https://codeclimate.com/github/charlotte-ruby/impressionist)
|
5
|
+
|
6
|
+
impressionist
|
7
|
+
=============
|
8
|
+
|
9
|
+
A lightweight plugin that logs impressions per action or manually per model
|
10
|
+
|
11
|
+
--------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
What does this thing do?
|
14
|
+
------------------------
|
15
|
+
Logs an impression... and I use that term loosely. It can log page impressions
|
16
|
+
(technically action impressions), but it is not limited to that. You can log
|
17
|
+
impressions multiple times per request. And you can also attach it to a model.
|
18
|
+
The goal of this project is to provide customizable stats that are immediately
|
19
|
+
accessible in your application as opposed to using Google Analytics and pulling
|
20
|
+
data using their API. You can attach custom messages to impressions. No
|
21
|
+
reporting yet.. this thingy just creates the data.
|
22
|
+
|
23
|
+
What about bots?
|
24
|
+
----------------
|
25
|
+
They are ignored. 1200 known bots have been added to the ignore list as of
|
26
|
+
February 1, 2011. Impressionist uses this list:
|
27
|
+
http://www.user-agents.org/allagents.xml
|
28
|
+
|
29
|
+
Installation
|
30
|
+
------------
|
31
|
+
Add it to your Gemfile
|
32
|
+
|
33
|
+
gem 'impressionist'
|
34
|
+
|
35
|
+
Install with Bundler
|
36
|
+
|
37
|
+
bundle install
|
38
|
+
|
39
|
+
Generate the impressions table migration
|
40
|
+
|
41
|
+
rails g impressionist
|
42
|
+
|
43
|
+
Run the migration
|
44
|
+
|
45
|
+
rake db:migrate
|
46
|
+
|
47
|
+
The following fields are provided in the migration:
|
48
|
+
|
49
|
+
t.string "impressionable_type" # model type: Widget
|
50
|
+
t.integer "impressionable_id" # model instance ID: @widget.id
|
51
|
+
t.integer "user_id" # automatically logs @current_user.id
|
52
|
+
t.string "controller_name" # logs the controller name
|
53
|
+
t.string "action_name" # logs the action_name
|
54
|
+
t.string "view_name" # TODO: log individual views (as well as partials and nested partials)
|
55
|
+
t.string "request_hash" # unique ID per request, in case you want to log multiple impressions and group them
|
56
|
+
t.string "session_hash" # logs the rails session
|
57
|
+
t.string "ip_address" # request.remote_ip
|
58
|
+
t.text "params" # request.params, except action name, controller name and resource id
|
59
|
+
t.string "referrer" # request.referer
|
60
|
+
t.string "message" # custom message you can add
|
61
|
+
t.datetime "created_at" # I am not sure what this is.... Any clue?
|
62
|
+
t.datetime "updated_at" # never seen this one before either.... Your guess is as good as mine?? ;-)
|
63
|
+
|
64
|
+
Usage
|
65
|
+
-----
|
66
|
+
|
67
|
+
1. Log all actions in a controller
|
68
|
+
|
69
|
+
WidgetsController < ApplicationController
|
70
|
+
impressionist
|
71
|
+
end
|
72
|
+
|
73
|
+
2. Specify actions you want logged in a controller
|
74
|
+
|
75
|
+
WidgetsController < ApplicationController
|
76
|
+
impressionist :actions=>[:show,:index]
|
77
|
+
end
|
78
|
+
|
79
|
+
3. Make your models impressionable. This allows you to attach impressions to
|
80
|
+
an AR model instance. Impressionist will automatically log the Model name
|
81
|
+
(based on action_name) and the id (based on params[:id]), but in order to
|
82
|
+
get the count of impressions (example: @widget.impression_count), you will
|
83
|
+
need to make your model impressionable
|
84
|
+
|
85
|
+
class Widget < ActiveRecord::Base
|
86
|
+
is_impressionable
|
87
|
+
end
|
88
|
+
|
89
|
+
4. Log an impression per model instance in your controller. Note that it is
|
90
|
+
not necessary to specify "impressionist" (usage #1) in the top of you
|
91
|
+
controller if you are using this method. If you add "impressionist" to the
|
92
|
+
top of your controller and also use this method in your action, it will
|
93
|
+
result in 2 impressions being logged (but associated with one request_hash).
|
94
|
+
If you're using [friendly_id](https://github.com/norman/friendly_id) be sure
|
95
|
+
to log impressionist this way, as params[:id] will return a string(url slug)
|
96
|
+
while impressionable_id is a Integer column in database.
|
97
|
+
|
98
|
+
def show
|
99
|
+
@widget = Widget.find
|
100
|
+
impressionist(@widget, "message...") # 2nd argument is optional
|
101
|
+
end
|
102
|
+
|
103
|
+
5. Get unique impression count from a model. This groups impressions by
|
104
|
+
request_hash, so if you logged multiple impressions per request, it will
|
105
|
+
only count them one time. This unique impression count will not filter out
|
106
|
+
unique users, only unique requests
|
107
|
+
|
108
|
+
@widget.impressionist_count
|
109
|
+
@widget.impressionist_count(:start_date=>"2011-01-01",:end_date=>"2011-01-05")
|
110
|
+
@widget.impressionist_count(:start_date=>"2011-01-01") #specify start date only, end date = now
|
111
|
+
|
112
|
+
6. Get the unique impression count from a model filtered by IP address. This
|
113
|
+
in turn will give you impressions with unique request_hash, since rows with
|
114
|
+
the same request_hash will have the same IP address.
|
115
|
+
|
116
|
+
@widget.impressionist_count(:filter=>:ip_address)
|
117
|
+
|
118
|
+
7. Get the unique impression count from a model filtered by params. This
|
119
|
+
in turn will give you impressions with unique params.
|
120
|
+
|
121
|
+
@widget.impressionist_count(:filter => :params)
|
122
|
+
|
123
|
+
8. Get the unique impression count from a model filtered by session hash. Same
|
124
|
+
as #6 regarding request hash. This may be more desirable than filtering by
|
125
|
+
IP address depending on your situation, since filtering by IP may ignore
|
126
|
+
visitors that use the same IP. The downside to this filtering is that a
|
127
|
+
user could clear session data in their browser and skew the results.
|
128
|
+
|
129
|
+
@widget.impressionist_count(:filter=>:session_hash)
|
130
|
+
|
131
|
+
9. Get total impression count. This may return more than 1 impression per http
|
132
|
+
request, depending on how you are logging impressions
|
133
|
+
|
134
|
+
@widget.impressionist_count(:filter=>:all)
|
135
|
+
|
136
|
+
10. Get impression count by message. This only counts impressions of the given message.
|
137
|
+
|
138
|
+
@widget.impressionist_count(:message=>"pageview", :filter=>:all)
|
139
|
+
|
140
|
+
Logging impressions for authenticated users happens automatically. If you have
|
141
|
+
a current_user helper or use @current_user in your before_filter to set your
|
142
|
+
authenticated user, current_user.id will be written to the user_id field in the
|
143
|
+
impressions table.
|
144
|
+
|
145
|
+
Adding a counter cache
|
146
|
+
----------------------
|
147
|
+
Impressionist makes it easy to add a `counter_cache` column to your model. The
|
148
|
+
most basic configuration looks like:
|
149
|
+
|
150
|
+
is_impressionable :counter_cache => true
|
151
|
+
|
152
|
+
This will automatically increment the `impressions_count` column in the
|
153
|
+
included model. <b>Note: You'll need to add that column to your model. If you'd
|
154
|
+
like specific a different column name, you can:</b>
|
155
|
+
|
156
|
+
is_impressionable :counter_cache => true, :column_name => :my_column_name
|
157
|
+
|
158
|
+
If you'd like to include only unique impressions in your count:
|
159
|
+
|
160
|
+
# default will be filtered by ip_address
|
161
|
+
is_impressionable :counter_cache => true, :column_name => :my_column_name, :unique => true
|
162
|
+
|
163
|
+
If you'd like to specify what sort of unique impression you'd like to save? Fear not,
|
164
|
+
Any option you pass to unique, impressionist_count will use it as its filter to update_counters based on that unique option.
|
165
|
+
|
166
|
+
# options are any column in the impressions' table.
|
167
|
+
is_impressionable :counter_cache => true, :column_name => :my_column_name, :unique => :request_hash
|
168
|
+
is_impressionable :counter_cache => true, :column_name => :my_column_name, :unique => :all
|
169
|
+
|
170
|
+
|
171
|
+
Adding column to model
|
172
|
+
----------------------
|
173
|
+
It is as simple as this:
|
174
|
+
|
175
|
+
t.integer :my_column_name, :default => 0
|
176
|
+
|
177
|
+
What if I only want to record unique impressions?
|
178
|
+
-------------------------------------------------
|
179
|
+
Maybe you only care about unique impressions and would like to avoid
|
180
|
+
unnecessary database records. You can specify conditions for recording
|
181
|
+
impressions in your controller:
|
182
|
+
|
183
|
+
# only record impression if the request has a unique combination of type, id, and session
|
184
|
+
impressionist :unique => [:impressionable_type, :impressionable_id, :session_hash]
|
185
|
+
|
186
|
+
# only record impression if the request has a unique combination of controller, action, and session
|
187
|
+
impressionist :unique => [:controller_name, :action_name, :session_hash]
|
188
|
+
|
189
|
+
# only record impression if session is unique
|
190
|
+
impressionist :unique => [:session_hash]
|
191
|
+
|
192
|
+
# only record impression if param is unique
|
193
|
+
impressionist :unique => [:params]
|
194
|
+
|
195
|
+
Or you can use the `impressionist` method directly:
|
196
|
+
|
197
|
+
impressionist(impressionable, "some message", :unique => [:session_hash])
|
198
|
+
|
199
|
+
Are you using Mongoid?
|
200
|
+
---------------------
|
201
|
+
|
202
|
+
Execute this command on your terminal/console:
|
203
|
+
|
204
|
+
rails g impressionist --orm mongoid
|
205
|
+
|
206
|
+
This command create a file `impression.rb` on `config/initializer` folder. Add `config.orm = :mongoid` to this file:
|
207
|
+
|
208
|
+
# Use this hook to configure impressionist parameters
|
209
|
+
Impressionist.setup do |config|
|
210
|
+
# Define ORM. Could be :active_record (default), :mongo_mapper or :mongoid
|
211
|
+
# config.orm = :active_record
|
212
|
+
config.orm = :mongoid
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
Contributing to impressionist
|
217
|
+
-----------------------------
|
218
|
+
* Check out the latest master to make sure the feature hasn't been implemented
|
219
|
+
or the bug hasn't been fixed yet
|
220
|
+
* Check out the issue tracker to make sure someone already hasn't requested it
|
221
|
+
and/or contributed it
|
222
|
+
* Fork the project
|
223
|
+
* Start a feature/bugfix branch
|
224
|
+
* Commit and push until you are happy with your contribution
|
225
|
+
* Make sure to add rpsec tests for it. Patches or features without tests will
|
226
|
+
be ignored. Also, try to write better tests than I do ;-)
|
227
|
+
* If adding engine controller or view functionality, use HAML and Inherited
|
228
|
+
Resources.
|
229
|
+
* All testing is done inside a small Rails app (test_app). You will find specs
|
230
|
+
within this app.
|
231
|
+
|
232
|
+
|
233
|
+
Want to run the tests? Ok mummy
|
234
|
+
-------------------------------
|
235
|
+
* bundle install
|
236
|
+
* rails g impressionist
|
237
|
+
* rake db:migrate && rake db:test:prepare
|
238
|
+
* Run rake or rspec spec inside test_app dir
|
239
|
+
* nothing else.
|
240
|
+
* :wq
|
241
|
+
|
242
|
+
Contributors
|
243
|
+
------------
|
244
|
+
* [johnmcaliley - creator](https://github.com/johnmcaliley)
|
245
|
+
* [Antonio C Nalesso - maintainer](https://github.com/acnalesso)
|
246
|
+
* [coryschires](https://github.com/coryschires)
|
247
|
+
* [georgmittendorfer](https://github.com/georgmittendorfer)
|
248
|
+
|
249
|
+
|
250
|
+
Copyright (c) 2011 John McAliley. See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
# Impressionist will use MiniTest instead of RSpec
|
8
|
+
RSpec::Core::RakeTask.new do |task|
|
9
|
+
task.rspec_opts = "-I ./tests/test_app/spec"
|
10
|
+
task.pattern = "./tests/test_app/spec/**/*_spec.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
task :test_app => :spec
|
14
|
+
task :default => [:test, :test_app]
|
15
|
+
|
16
|
+
namespace :impressionist do
|
17
|
+
require File.dirname(__FILE__) + "/lib/impressionist/bots"
|
18
|
+
|
19
|
+
desc "output the list of bots from http://www.user-agents.org/"
|
20
|
+
task :bots do
|
21
|
+
p Impressionist::Bots.consume
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
# setup :test task to minitest
|
27
|
+
# Rake libs default is lib
|
28
|
+
# libs << path to load test_helper, etc..
|
29
|
+
Rake::TestTask.new do |t|
|
30
|
+
t.libs << "tests/spec"
|
31
|
+
t.pattern = "tests/spec/**/*_spec.rb"
|
32
|
+
t.test_files = FileList["tests/spec/**/*_spec.rb"]
|
33
|
+
t.verbose = true
|
34
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'digest/sha2'
|
2
|
+
|
3
|
+
module ImpressionistController
|
4
|
+
module ClassMethods
|
5
|
+
def impressionist(opts={})
|
6
|
+
before_action { |c| c.impressionist_subapp_filter(opts) }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
def self.included(base)
|
12
|
+
base.before_action :impressionist_app_filter
|
13
|
+
end
|
14
|
+
|
15
|
+
def impressionist(obj,message=nil,opts={})
|
16
|
+
if should_count_impression?(opts)
|
17
|
+
if obj.respond_to?("impressionable?")
|
18
|
+
if unique_instance?(obj, opts[:unique])
|
19
|
+
obj.impressions.create(associative_create_statement({:message => message}))
|
20
|
+
end
|
21
|
+
else
|
22
|
+
# we could create an impression anyway. for classes, too. why not?
|
23
|
+
raise "#{obj.class.to_s} is not impressionable!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def impressionist_app_filter
|
29
|
+
@impressionist_hash = Digest::SHA2.hexdigest(Time.now.to_f.to_s+rand(10000).to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
def impressionist_subapp_filter(opts = {})
|
33
|
+
if should_count_impression?(opts)
|
34
|
+
actions = opts[:actions]
|
35
|
+
actions.collect!{|a|a.to_s} unless actions.blank?
|
36
|
+
if (actions.blank? || actions.include?(action_name)) && unique?(opts[:unique])
|
37
|
+
Impression.create(direct_create_statement)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
# creates a statment hash that contains default values for creating an impression via an AR relation.
|
45
|
+
def associative_create_statement(query_params={})
|
46
|
+
query_params.reverse_merge!(
|
47
|
+
:controller_name => controller_name,
|
48
|
+
:action_name => action_name,
|
49
|
+
:user_id => user_id,
|
50
|
+
:request_hash => @impressionist_hash,
|
51
|
+
:session_hash => session_hash,
|
52
|
+
:ip_address => request.remote_ip,
|
53
|
+
:referrer => request.referer,
|
54
|
+
:params => params_hash
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def bypass
|
61
|
+
Impressionist::Bots.bot?(request.user_agent)
|
62
|
+
end
|
63
|
+
|
64
|
+
def should_count_impression?(opts)
|
65
|
+
!bypass && condition_true?(opts[:if]) && condition_false?(opts[:unless])
|
66
|
+
end
|
67
|
+
|
68
|
+
def condition_true?(condition)
|
69
|
+
condition.present? ? conditional?(condition) : true
|
70
|
+
end
|
71
|
+
|
72
|
+
def condition_false?(condition)
|
73
|
+
condition.present? ? !conditional?(condition) : true
|
74
|
+
end
|
75
|
+
|
76
|
+
def conditional?(condition)
|
77
|
+
condition.is_a?(Symbol) ? self.send(condition) : condition.call
|
78
|
+
end
|
79
|
+
|
80
|
+
def unique_instance?(impressionable, unique_opts)
|
81
|
+
return unique_opts.blank? || !impressionable.impressions.where(unique_query(unique_opts, impressionable)).exists?
|
82
|
+
end
|
83
|
+
|
84
|
+
def unique?(unique_opts)
|
85
|
+
return unique_opts.blank? || check_impression?(unique_opts)
|
86
|
+
end
|
87
|
+
|
88
|
+
def check_impression?(unique_opts)
|
89
|
+
impressions = Impression.where(unique_query(unique_opts - [:params]))
|
90
|
+
check_unique_impression?(impressions, unique_opts)
|
91
|
+
end
|
92
|
+
|
93
|
+
def check_unique_impression?(impressions, unique_opts)
|
94
|
+
impressions_present = impressions.exists?
|
95
|
+
impressions_present && unique_opts_has_params?(unique_opts) ? check_unique_with_params?(impressions) : !impressions_present
|
96
|
+
end
|
97
|
+
|
98
|
+
def unique_opts_has_params?(unique_opts)
|
99
|
+
unique_opts.include?(:params)
|
100
|
+
end
|
101
|
+
|
102
|
+
def check_unique_with_params?(impressions)
|
103
|
+
request_param = params_hash
|
104
|
+
impressions.detect{|impression| impression.params == request_param }.nil?
|
105
|
+
end
|
106
|
+
|
107
|
+
# creates the query to check for uniqueness
|
108
|
+
def unique_query(unique_opts,impressionable=nil)
|
109
|
+
full_statement = direct_create_statement({},impressionable)
|
110
|
+
# reduce the full statement to the params we need for the specified unique options
|
111
|
+
unique_opts.reduce({}) do |query, param|
|
112
|
+
query[param] = full_statement[param]
|
113
|
+
query
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# creates a statment hash that contains default values for creating an impression.
|
118
|
+
def direct_create_statement(query_params={},impressionable=nil)
|
119
|
+
query_params.reverse_merge!(
|
120
|
+
:impressionable_type => controller_name.singularize.camelize,
|
121
|
+
:impressionable_id => impressionable.present? ? impressionable.id : params[:id]
|
122
|
+
)
|
123
|
+
associative_create_statement(query_params)
|
124
|
+
end
|
125
|
+
|
126
|
+
def session_hash
|
127
|
+
# # careful: request.session_options[:id] encoding in rspec test was ASCII-8BIT
|
128
|
+
# # that broke the database query for uniqueness. not sure if this is a testing only issue.
|
129
|
+
# str = request.session_options[:id]
|
130
|
+
# logger.debug "Encoding: #{str.encoding.inspect}"
|
131
|
+
# # request.session_options[:id].encode("ISO-8859-1")
|
132
|
+
request.session_options[:id]
|
133
|
+
end
|
134
|
+
|
135
|
+
def params_hash
|
136
|
+
request.params.except(:controller, :action, :id)
|
137
|
+
end
|
138
|
+
|
139
|
+
#use both @current_user and current_user helper
|
140
|
+
def user_id
|
141
|
+
user_id = @current_user ? @current_user.id : nil rescue nil
|
142
|
+
user_id = current_user ? current_user.id : nil rescue nil if user_id.blank?
|
143
|
+
user_id
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|