visit-counter 0.1.1 → 0.1.2

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.
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # VisitCounter
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/KensoDev/visit-counter.png)](https://secure.travis-ci.org/KensoDev/visit-counter)
4
+
3
5
  VisitCounter is a gem which solves the annoying problem of counting visits and displaying them in real time. In an SQL database, for a site with a lot of hits, this can cause quite a lot of overhead. VisitCounter aims to solve this by using a quick key-value store to keep a delta, and only persist to the SQL DB when the delta crosses a certain percent of the saved counter.
4
6
  It can be used transparently, by overriding the accessor to the counter, or simply by using the helper functions it defines - incr_counter, read_counter, get_counter_delta and nullify_counter.
5
7
 
data/Rakefile CHANGED
@@ -1,2 +1,10 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task :default => :spec
@@ -38,7 +38,7 @@ module VisitCounter
38
38
  redis.decrby(key, by)
39
39
  end
40
40
 
41
- def aquire_lock!(object)
41
+ def acquire_lock(object)
42
42
  redis.setnx(lock_key(object), 1)
43
43
  end
44
44
 
@@ -51,7 +51,7 @@ module VisitCounter
51
51
  end
52
52
 
53
53
  def with_lock(object, &block)
54
- if aquire_lock!(object)
54
+ if acquire_lock(object)
55
55
  begin
56
56
  yield
57
57
  ensure
@@ -63,4 +63,4 @@ module VisitCounter
63
63
  end
64
64
  end
65
65
  end
66
- end
66
+ end
@@ -1,3 +1,3 @@
1
1
  module VisitCounter
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -4,7 +4,7 @@ module VisitCounter
4
4
  base.class_eval do
5
5
  class << self
6
6
  #defining class instance attributes
7
- attr_accessor :visit_counter_threshold, :visit_counter_threshold_method
7
+ attr_accessor :visit_counter_threshold, :visit_counter_threshold_method, :persist_with_callbacks
8
8
  end
9
9
  end
10
10
  base.send(:include, InstanceMethods)
@@ -73,7 +73,12 @@ module VisitCounter
73
73
 
74
74
  def persist(object, staged_count, diff, name)
75
75
  VisitCounter::Store.engine.with_lock(object) do
76
- object.update_attribute(name, staged_count + diff)
76
+ if object.class.persist_with_callbacks
77
+ object.send("#{name}=", staged_count + diff )
78
+ object.save
79
+ else
80
+ object.update_attribute(name, staged_count + diff)
81
+ end
77
82
  object.nullify_counter_cache(name, diff)
78
83
  end
79
84
  end
@@ -3,12 +3,16 @@ require "spec_helper"
3
3
  class DummyObject
4
4
  include VisitCounter
5
5
 
6
- attr_accessor :counter
6
+ attr_accessor :counter, :persist_with_callbacks
7
7
 
8
8
  def update_attribute(attribute, value)
9
9
  self.send("#{attribute}=", value)
10
10
  end
11
11
 
12
+ def save
13
+ nil
14
+ end
15
+
12
16
  def read_attribute(name)
13
17
  #yeah, evals are evil, but it works and it's for testing purposes only. we assume read_attribute is defined the same as in AR wherever we include this module
14
18
  eval("@#{name}")
@@ -124,13 +128,13 @@ describe VisitCounter do
124
128
  end
125
129
 
126
130
  it "should not persist if object is locked" do
127
- VisitCounter::Store.engine.stub!(:aquire_lock!).and_return(false)
131
+ VisitCounter::Store.engine.stub!(:acquire_lock).and_return(false)
128
132
  @d.should_not_receive(:update_attribute)
129
133
  VisitCounter::Helper.persist(@d, 1, 1, :counter)
130
134
  end
131
135
 
132
136
  it "should persist if object is locked" do
133
- VisitCounter::Store.engine.stub!(:aquire_lock!).and_return(true)
137
+ VisitCounter::Store.engine.stub!(:acquire_lock).and_return(true)
134
138
  @d.should_receive(:update_attribute)
135
139
  VisitCounter::Helper.persist(@d, 1, 1, :counter)
136
140
  end
@@ -157,5 +161,15 @@ describe VisitCounter do
157
161
  @d.counter.should == 11
158
162
  end
159
163
  end
164
+
165
+ describe "persist with callbacks" do
166
+ it "should use save method" do
167
+ @d = DummyObject.new
168
+ @d.class.persist_with_callbacks = true
169
+ @d.stub!(:id).and_return(1)
170
+ @d.should_receive(:save)
171
+ @d.incr_counter :counter
172
+ end
173
+ end
160
174
 
161
- end
175
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: visit-counter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,56 +9,56 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-24 00:00:00.000000000 Z
12
+ date: 2013-04-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
+ prerelease: false
16
17
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0'
22
+ none: false
22
23
  type: :development
23
- prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
25
  requirements:
27
26
  - - ! '>='
28
27
  - !ruby/object:Gem::Version
29
28
  version: '0'
29
+ none: false
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
+ prerelease: false
32
33
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
37
  version: 0.9.2
38
+ none: false
38
39
  type: :development
39
- prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
41
  requirements:
43
42
  - - ~>
44
43
  - !ruby/object:Gem::Version
45
44
  version: 0.9.2
45
+ none: false
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: redis
48
+ prerelease: false
48
49
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
50
  requirements:
51
51
  - - ! '>='
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
+ none: false
54
55
  type: :runtime
55
- prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
57
  requirements:
59
58
  - - ! '>='
60
59
  - !ruby/object:Gem::Version
61
60
  version: '0'
61
+ none: false
62
62
  description: Simple counter increment which only writes to DB once in a while
63
63
  email:
64
64
  - tcaspy@gmail.com
@@ -90,17 +90,17 @@ rdoc_options: []
90
90
  require_paths:
91
91
  - lib
92
92
  required_ruby_version: !ruby/object:Gem::Requirement
93
- none: false
94
93
  requirements:
95
94
  - - ! '>='
96
95
  - !ruby/object:Gem::Version
97
96
  version: '0'
98
- required_rubygems_version: !ruby/object:Gem::Requirement
99
97
  none: false
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
99
  requirements:
101
100
  - - ! '>='
102
101
  - !ruby/object:Gem::Version
103
102
  version: '0'
103
+ none: false
104
104
  requirements: []
105
105
  rubyforge_project:
106
106
  rubygems_version: 1.8.24