impressionist 1.3.2 → 1.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 383f3c7524c62abeacef5033839a1e695e4f5065
4
- data.tar.gz: 784de1284002f83371788a3f3da0a397d3848651
3
+ metadata.gz: 565d11269849faecb7c83d6cda308c6c1e9eba4c
4
+ data.tar.gz: ed373d6474fee728c3742b0d475ad5d425f9902e
5
5
  SHA512:
6
- metadata.gz: 2e28487decb94bc12c205799df6fcb06fae81e1043bfb4e22b7fb4e69a36a0cd6ce15f653bb803d5fb3120f4e6ad95a1048b73715074c90766541bae2280ab1f
7
- data.tar.gz: 87a2fad11f4c54e0d7e83f0b21f2c2ee09468dc3aa1cd68b0469dbc8800c99a77f0f2e34c4884352217cb62a06c8ce2c4c65a201bbc8ea0135a77c9c70b30017
6
+ metadata.gz: 8a4160978bf2c001b1c8f2ea24f18bc563d3cd821de5294de0f5b2da8f1c87e8e3a7c2f0c210bd7420b8a7c216383f23ffb61875bac3930475dd163f90f6a5c6
7
+ data.tar.gz: bc2f41f6556664349216614eec6fdc9d366f40ac0e5fbd5bcbc1eab2fd470897104581f2b19ae31267067273a49a59693edff525a6c6c34596a8c00573932f65
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,18 @@
1
+ == 1.4.0 (2013-07-06)
2
+ * Fixed #92
3
+ * Pass option to unique for updatind counter_cache
4
+ * Clean up code, make it human readable
5
+ * Changed README in order to explain new features
6
+ * (@nbit001)
7
+
8
+ == 1.3.3 (2013-06-27)
9
+ * Added Rails4 Branch in order to support rails 4
10
+ * Rails 4 and Strong Parameters compability. (@bennick).
11
+
12
+ == 1.3.1 (non specified)
13
+ * Change controller_path back to controller_name (@johnmcaliley)
14
+
15
+
1
16
  == 0.4.0 (2011-06-03)
2
17
  * Fix postgres bug
3
18
  * New impression count method that accepts options for filter, start_date and end_date
data/README.md CHANGED
@@ -136,14 +136,29 @@ most basic configuration looks like:
136
136
  is_impressionable :counter_cache => true
137
137
 
138
138
  This will automatically increment the `impressions_count` column in the
139
- included model. Note: You'll need to add that column to your model. If you'd
140
- like specific a different column name, you can:
139
+ included model. <b>Note: You'll need to add that column to your model. If you'd
140
+ like specific a different column name, you can:</b>
141
141
 
142
- is_impressionable :counter_cache => { :column_name => :my_column }
142
+ is_impressionable :counter_cache => { :column_name => :my_column_name }
143
143
 
144
144
  If you'd like to include only unique impressions in your count:
145
145
 
146
- is_impressionable :counter_cache => { :column_name => :my_column, :unique => true }
146
+ # default will be filtered by ip_address
147
+ is_impressionable :counter_cache => { :column_name => :my_column_name, :unique => true }
148
+
149
+ If you'd like to specify what sort of unique impression you'd like to save? Fear not,
150
+ Any option you pass to unique, impressionist_count will use it as its filter to update_counters based on that unique option.
151
+
152
+ # options are any column in the impressions' table.
153
+ is_impressionable :counter_cache => { :column_name => :my_column_name, :unique => :request_hash }
154
+ is_impressionable :counter_cache => { :column_name => :my_column_name, :unique => :all }
155
+
156
+
157
+ Adding column to model
158
+ ----------------------
159
+ It is as simple as this:
160
+
161
+ t.integer :my_column_name, :default => 0
147
162
 
148
163
  What if I only want to record unique impressions?
149
164
  -------------------------------------------------
@@ -170,7 +185,7 @@ Are you using Mongoid?
170
185
  Execute this command on your terminal/console:
171
186
 
172
187
  rails g impressionist --orm mongoid
173
-
188
+
174
189
  This command create a file `impression.rb` on `config/initializer` folder. Add `config.orm = :mongoid` to this file:
175
190
 
176
191
  # Use this hook to configure impressionist parameters
@@ -179,7 +194,7 @@ This command create a file `impression.rb` on `config/initializer` folder. Add `
179
194
  # config.orm = :active_record
180
195
  config.orm = :mongoid
181
196
  end
182
-
197
+
183
198
 
184
199
  Contributing to impressionist
185
200
  -----------------------------
@@ -197,10 +212,21 @@ Contributing to impressionist
197
212
  * All testing is done inside a small Rails app (test_app). You will find specs
198
213
  within this app.
199
214
 
215
+
216
+ Want to run the tests? Ok mummy
217
+ -------------------------------
218
+ * bundle install
219
+ * rails g impressionist
220
+ * rake db:migrate && rake db:test:prepare
221
+ * Run rake or rspec spec inside test_app dir
222
+ * nothing else.
223
+ * :wq
224
+
200
225
  Contributors
201
226
  ------------
202
227
  * [johnmcaliley](https://github.com/johnmcaliley)
203
228
  * [coryschires](https://github.com/coryschires)
204
229
  * [georgmittendorfer](https://github.com/georgmittendorfer)
230
+ * [Antonio C Nalesso](https://github.com/nbit001)
205
231
 
206
232
  Copyright (c) 2011 John McAliley. See LICENSE.txt for further details.
@@ -4,59 +4,43 @@ module Impressionist
4
4
 
5
5
  module ClassMethods
6
6
  attr_accessor :impressionist_cache_options
7
- @impressionist_cache_options = nil
7
+
8
+ DEFAULT_CACHE = { :counter_cache => false, :column_name => :impressions_count, :unique => false }
8
9
 
9
10
  def impressionist_counter_cache_options
10
- if @impressionist_cache_options
11
- options = { :column_name => :impressions_count, :unique => false }
12
- options.merge!(@impressionist_cache_options) if @impressionist_cache_options.is_a?(Hash)
13
- options
14
- end
11
+ @impressionist_cache_options ||= {}
12
+ @impressionist_cache_options.reverse_merge!(DEFAULT_CACHE)
15
13
  end
16
14
 
15
+ # true or false
17
16
  def impressionist_counter_caching?
18
- impressionist_counter_cache_options.present?
17
+ impressionist_counter_cache_options[:counter_cache]
19
18
  end
20
19
 
21
20
  def counter_caching?
22
- ::ActiveSupport::Deprecation.warn("#counter_caching? is deprecated; please use #impressionist_counter_caching? instead")
23
- impressionist_counter_caching?
21
+ ::ActiveSupport::Deprecation.warn("#counter_caching? is deprecated; please use #impressionist_counter_caching? instead")
22
+ impressionist_counter_caching?
24
23
  end
25
- end
26
24
 
27
- def impressionable?
28
- true
29
25
  end
30
26
 
27
+ # ------------------------------------------
28
+ # TODO: CLEAN UP, make it HUMAN readable
31
29
  def impressionist_count(options={})
32
30
  options.reverse_merge!(:filter=>:request_hash, :start_date=>nil, :end_date=>Time.now)
33
31
  imps = options[:start_date].blank? ? impressions : impressions.where("created_at>=? and created_at<=?",options[:start_date],options[:end_date])
34
32
  options[:filter] == :all ? imps.count : imps.count(options[:filter], :distinct => true)
35
33
  end
36
34
 
37
- def update_impressionist_counter_cache
38
- cache_options = self.class.impressionist_counter_cache_options
39
- column_name = cache_options[:column_name].to_sym
40
- count = cache_options[:unique] ? impressionist_count(:filter => :ip_address) : impressionist_count
41
- old_count = send(column_name) || 0
42
- self.class.update_counters(id, column_name => (count - old_count))
43
- end
44
-
45
- # OLD METHODS - DEPRECATE IN V0.5
46
- def impression_count(start_date=nil,end_date=Time.now)
47
- impressionist_count({:start_date=>start_date, :end_date=>end_date, :filter=>:all})
48
- end
35
+ def update_impressionist_counter_cache
36
+ slave = Impressionist::UpdateCounters.new(self)
37
+ slave.update
38
+ end
49
39
 
50
- def unique_impression_count(start_date=nil,end_date=Time.now)
51
- impressionist_count({:start_date=>start_date, :end_date=>end_date, :filter=> :request_hash})
52
- end
53
-
54
- def unique_impression_count_ip(start_date=nil,end_date=Time.now)
55
- impressionist_count({:start_date=>start_date, :end_date=>end_date, :filter=> :ip_address})
40
+ def impressionable?
41
+ true
56
42
  end
57
43
 
58
- def unique_impression_count_session(start_date=nil,end_date=Time.now)
59
- impressionist_count({:start_date=>start_date, :end_date=>end_date, :filter=> :session_hash})
60
- end
61
44
  end
45
+
62
46
  end
data/lib/impressionist.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'impressionist/engine'
1
+ require 'impressionist/load'
2
2
 
3
3
  module Impressionist
4
4
  # Define default ORM
@@ -0,0 +1,83 @@
1
+ module Impressionist
2
+ module CounterCache
3
+
4
+ attr_reader :impressionable_class, :entity
5
+
6
+ private
7
+ LOG_MESSAGE = "Can't find impressionable_type or impressionable_id. Will not update_counters!"
8
+
9
+ # if updatable returns true, it must be qualified to update_counters
10
+ # Therefore there's no need to validate again
11
+ # impressionable_class instance var is set when updatable? is called
12
+ def impressionable_counter_cache_updatable?
13
+ updatable? ? update_impression_cache : impressionist_log(LOG_MESSAGE)
14
+ end
15
+
16
+ def update_impression_cache
17
+ impressionable_find
18
+ impressionable_try
19
+ end
20
+
21
+ # asks imp_id whether it's present or not
22
+ # also expect imp_class to be true
23
+ # all should be true, so that it is updatable
24
+ def updatable?
25
+ @impressionable_class = impressionable_class_set
26
+ impressionable_valid?
27
+ end
28
+
29
+ # imps_type == nil, constantize returns Object
30
+ # Therefore it attemps to return false so it won't be updatable
31
+ # calls to_s otherwise it would try to constantize nil
32
+ # and it would raise an exeception..
33
+ def impressionable_class_set
34
+ _type_ = self.impressionable_type.to_s.constantize
35
+ ((_type_.to_s !~ /Object/) && _type_.impressionist_counter_caching? ? _type_ : false)
36
+ end
37
+
38
+ # Either true or false
39
+ # needs true to be updatable
40
+ def impressionable_valid?
41
+ (self.impressionable_id.present? && impressionable_class && impressionable_find)
42
+ end
43
+
44
+ # Logs to log file, expects a message to be passed
45
+ # default mode is ERROR
46
+ def impressionist_log(mode=:error, str)
47
+ Rails.logger.send(mode.to_s, str)
48
+ end
49
+
50
+ # read it out and LOUD
51
+ def impressionable_find
52
+ exeception_rescuer {
53
+ @entity = impressionable_class.find(self.impressionable_id)
54
+ }
55
+ @entity
56
+
57
+ end
58
+
59
+ # receives an entity(instance of a Model) and then tries to update
60
+ # counter_cache column
61
+ # entity is a impressionable_model
62
+ def impressionable_try
63
+ entity.try(:update_impressionist_counter_cache)
64
+ end
65
+
66
+ # Returns false, as it is only handling one exeception
67
+ # It would make updatable to fail thereafter it would not try
68
+ # to update cache_counter
69
+ def exeception_rescuer
70
+ begin
71
+ yield
72
+ rescue ActiveRecord::RecordNotFound
73
+ exeception_to_log
74
+ false
75
+ end
76
+ end
77
+
78
+ def exeception_to_log
79
+ impressionist_log("Couldn't find Widget with id=#{self.impressionable_id}")
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,7 @@
1
+ require "impressionist/engine"
2
+
3
+ require "impressionist/set_up_association"
4
+
5
+ require "impressionist/counter_cache"
6
+
7
+ require "impressionist/update_counters"
@@ -1,21 +1,13 @@
1
- class Impression < ActiveRecord::Base
2
- attr_accessible :impressionable_type, :impressionable_id, :user_id,
3
- :controller_name, :action_name, :view_name, :request_hash, :ip_address,
4
- :session_hash, :message, :referrer
5
-
6
- belongs_to :impressionable, :polymorphic=>true
1
+ # Responsability
2
+ # * be able to update_counters
3
+ # * log an error if imps_id and imps_type can not be found
4
+ # asks updatable? whether it may or may not be updated
5
+ # FIX exeception raising when no imps_id is found
7
6
 
8
- after_save :update_impressions_counter_cache
7
+ class Impression < ActiveRecord::Base
8
+ include Impressionist::CounterCache
9
+ include Impressionist::SetUpAssociation
9
10
 
10
- private
11
+ after_save :impressionable_counter_cache_updatable?
11
12
 
12
- def update_impressions_counter_cache
13
- if self.impressionable_type && self.impressionable_id
14
- impressionable_class = self.impressionable_type.constantize
15
- if impressionable_class.impressionist_counter_cache_options
16
- resouce = impressionable_class.find(self.impressionable_id)
17
- resouce.try(:update_impressionist_counter_cache)
18
- end
19
- end
20
- end
21
13
  end
@@ -2,13 +2,27 @@ ActiveRecord::Base.send(:include, Impressionist::Impressionable)
2
2
 
3
3
  module Impressionist
4
4
  module Impressionable
5
+
5
6
  extend ActiveSupport::Concern
6
7
 
7
8
  module ClassMethods
8
9
  def is_impressionable(options={})
9
- has_many :impressions, :as => :impressionable, :dependent => :destroy
10
- @impressionist_cache_options = options[:counter_cache]
10
+ define_association
11
+ imp_cache_options_set(options)
12
+ end
13
+
14
+ def define_association
15
+ has_many(:impressions,
16
+ :as => :impressionable,
17
+ :dependent => :destroy)
18
+ end
19
+
20
+ def imp_cache_options_set(options)
21
+ @impressionist_cache_options = options
11
22
  end
23
+
12
24
  end
25
+
13
26
  end
27
+
14
28
  end
@@ -0,0 +1,14 @@
1
+ module Impressionist
2
+ module SetUpAssociation
3
+
4
+ def self.included(base)
5
+ base.attr_accessible(:impressionable_type,:impressionable_id,
6
+ :user_id,:controller_name,:action_name,:view_name,:request_hash,
7
+ :ip_address,:session_hash,:message,:referrer)
8
+
9
+ base.belongs_to(:impressionable, :polymorphic => true)
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,63 @@
1
+ module Impressionist
2
+ class UpdateCounters
3
+ attr_reader :receiver, :master
4
+
5
+ def initialize(receiver)
6
+ @receiver = receiver
7
+ @master = receiver.class
8
+ end
9
+
10
+ def update
11
+ result = (impressions_total - impressions_cached)
12
+
13
+ master.
14
+ update_counters(id, column_name => result)
15
+ end
16
+
17
+ private
18
+ def id
19
+ receiver.id
20
+ end
21
+
22
+ # if unique == true then uses it
23
+ # otherwise just count all impressions
24
+ # using filter: :all
25
+ def impressions_total
26
+ receiver.impressionist_count filter(unique_filter)
27
+ end
28
+
29
+ # from a given db column
30
+ # default should be impressions_count
31
+ def impressions_cached
32
+ receiver.send(column_name) || 0
33
+ end
34
+
35
+ def column_name
36
+ cache_options[:column_name].to_sym
37
+ end
38
+
39
+ def cache_options
40
+ master.
41
+ impressionist_counter_cache_options
42
+ end
43
+
44
+ # default is ip_address if what_is_unique is TRUE or FALSE
45
+ def unique_filter
46
+ what_is_unique? ? :ip_address : cache_options[:unique]
47
+ end
48
+
49
+ # Either true or false
50
+ # :filter gets assigned to :ip_address as default
51
+ # One could do
52
+ # is_impressionable :counter_cache => true, :unique => :any_other_colum
53
+ def what_is_unique?
54
+ cache_options[:unique].to_s =~ /true|false/
55
+ end
56
+
57
+ def filter(filter_will_be)
58
+ {:filter => filter_will_be.to_sym}
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -1,3 +1,3 @@
1
1
  module Impressionist
2
- VERSION = "1.3.2"
2
+ VERSION = "1.4.0"
3
3
  end
data/test_app/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'rails', '3.2.2'
3
+ gem 'rails', '3.2.12'
4
4
 
5
5
  gem 'impressionist', :path => '../'
6
6
 
@@ -41,7 +41,7 @@ group :test do
41
41
  gem 'systemu'
42
42
  end
43
43
 
44
- #gem 'jquery-rails'
44
+ gem 'jquery-rails'
45
45
 
46
46
  # To use ActiveModel has_secure_password
47
47
  # gem 'bcrypt-ruby', '~> 3.0.0'
@@ -1,3 +1,3 @@
1
1
  class Widget < ActiveRecord::Base
2
- is_impressionable :counter_cache => true
2
+ is_impressionable :counter_cache => true, :unique => :request_hash
3
3
  end
@@ -2,7 +2,7 @@ class CreateWidgets < ActiveRecord::Migration
2
2
  def self.up
3
3
  create_table :widgets do |t|
4
4
  t.string :name
5
- t.integer :impressions_count
5
+ t.integer :impressions_count, :default => 0
6
6
 
7
7
  t.timestamps
8
8
  end
@@ -131,4 +131,4 @@ describe DummyController do
131
131
  get "index"
132
132
  Impression.all.size.should eq 12
133
133
  end
134
- end
134
+ end
@@ -3,8 +3,9 @@ require 'spec_helper'
3
3
  describe Impression do
4
4
  fixtures :widgets
5
5
 
6
+ let(:widget) { Widget.find(1) }
7
+
6
8
  before(:each) do
7
- @widget = Widget.find(1)
8
9
  Impression.destroy_all
9
10
  end
10
11
 
@@ -33,17 +34,17 @@ describe Impression do
33
34
 
34
35
  describe "#update_impressionist_counter_cache" do
35
36
  it "should update the counter cache column to reflect the correct number of impressions" do
36
- lambda {
37
- @widget.impressions.create(:request_hash => 'abcd1234')
38
- @widget.reload
39
- }.should change(@widget, :impressions_count).from(0).to(1)
37
+ expect {
38
+ widget.impressions.create(:request_hash => 'abcd1234')
39
+ widget.reload
40
+ }.to change(widget, :impressions_count).from(0).to(1)
40
41
  end
41
42
 
42
43
  it "should not update the timestamp on the impressable" do
43
- lambda {
44
- @widget.impressions.create(:request_hash => 'abcd1234')
45
- @widget.reload
46
- }.should_not change(@widget, :updated_at)
44
+ expect {
45
+ widget.impressions.create(:request_hash => 'abcd1234')
46
+ widget.reload
47
+ }.to_not change(widget, :updated_at)
47
48
  end
48
49
  end
49
50
 
@@ -51,7 +51,7 @@ describe Impression do
51
51
 
52
52
  # tests :dependent => :destroy
53
53
  it "should delete impressions on deletion of impressionable" do
54
- impressions_count = Impression.all.size
54
+ #impressions_count = Impression.all.size
55
55
  a = Article.create
56
56
  i = a.impressions.create
57
57
  a.destroy
@@ -59,36 +59,4 @@ describe Impression do
59
59
  i.destroyed?.should be_true
60
60
  end
61
61
 
62
- #OLD COUNT METHODS. DEPRECATE SOON
63
- it "should return the impression count with no date range specified" do
64
- @article.impression_count.should eq 11
65
- end
66
-
67
- it "should return unique impression count with no date range specified" do
68
- @article.unique_impression_count.should eq 9
69
- end
70
-
71
- it "should return impression count with only start date specified" do
72
- @article.impression_count("2011-01-01").should eq 8
73
- end
74
-
75
- it "should return impression count with whole date range specified" do
76
- @article.impression_count("2011-01-01","2011-01-02").should eq 7
77
- end
78
-
79
- it "should return unique impression count with only start date specified" do
80
- @article.unique_impression_count("2011-01-01").should eq 7
81
- end
82
-
83
- it "should return unique impression count with date range specified" do
84
- @article.unique_impression_count("2011-01-01","2011-01-02").should eq 7
85
- end
86
-
87
- it "should return unique impression count using ip address (which in turn eliminates duplicate request_hashes)" do
88
- @article.unique_impression_count_ip.should eq 8
89
- end
90
-
91
- it "should return unique impression count using session_hash (which in turn eliminates duplicate request_hashes)" do
92
- @article.unique_impression_count_session.should eq 7
93
- end
94
62
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: impressionist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - johnmcaliley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-27 00:00:00.000000000 Z
11
+ date: 2013-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient
@@ -178,13 +178,17 @@ files:
178
178
  - lib/impressionist.rb
179
179
  - lib/impressionist/bots.rb
180
180
  - lib/impressionist/controllers/mongoid/impressionist_controller.rb
181
+ - lib/impressionist/counter_cache.rb
181
182
  - lib/impressionist/engine.rb
183
+ - lib/impressionist/load.rb
182
184
  - lib/impressionist/models/active_record/impression.rb
183
185
  - lib/impressionist/models/active_record/impressionist/impressionable.rb
184
186
  - lib/impressionist/models/mongo_mapper/impression.rb
185
187
  - lib/impressionist/models/mongo_mapper/impressionist/impressionable.rb
186
188
  - lib/impressionist/models/mongoid/impression.rb
187
189
  - lib/impressionist/models/mongoid/impressionist/impressionable.rb
190
+ - lib/impressionist/set_up_association.rb
191
+ - lib/impressionist/update_counters.rb
188
192
  - lib/impressionist/version.rb
189
193
  - logo.png
190
194
  - spec/spec_helper.rb