impressionist 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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