monocle 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -51,6 +51,15 @@ module Monocle
51
51
  field = v.call
52
52
  field.is_a?(String) ? field : field.to_i
53
53
  end
54
+
55
+ define_method("#{k}_clicks_count") do
56
+ self._monocle_redis_connection.hget(self.class.monocle_key(id), self.send("#{k}_clicks_field")).to_i || 0
57
+ end
58
+
59
+ define_method("#{k}_clicks_field") do
60
+ field = v.call
61
+ field.is_a?(String) ? field : field.to_i
62
+ end
54
63
  end
55
64
  end
56
65
 
@@ -90,10 +99,32 @@ module Monocle
90
99
  end
91
100
  end
92
101
 
102
+ def click!
103
+ results = self._monocle_redis_connection.pipelined do
104
+ self._monocle_view_types.keys.each do |view_type|
105
+ self._monocle_redis_connection.hincrby(self.class.monocle_key(id), self.send("#{view_type}_clicks_field"), 1)
106
+ end
107
+ self._monocle_redis_connection.zadd(self.class.monocle_key('recently_clicked'), Time.now.to_i, id)
108
+ self._monocle_redis_connection.zincrby(self.class.monocle_key('click_counts'), 1, id)
109
+ end
110
+
111
+ if should_cache_view_count?
112
+ self._monocle_view_types.keys.each_with_index do |view_type, i|
113
+ cache_click_count(view_type, results[i])
114
+ end
115
+ self.update_column(self._monocle_options[:cache_threshold_check_field].to_sym, Time.now) if respond_to?(:update_column)
116
+ self.set(self._monocle_options[:cache_threshold_check_field].to_sym, Time.now) if respond_to?(:set)
117
+ end
118
+ end
119
+
93
120
  def cache_field_for_view(view_type)
94
121
  :"#{view_type}_views"
95
122
  end
96
123
 
124
+ def cache_field_for_click(view_type)
125
+ :"#{view_type}_clicks"
126
+ end
127
+
97
128
  def should_cache_view_count?
98
129
  if self._monocle_options[:cache_view_counts]
99
130
  self.send(self._monocle_options[:cache_threshold_check_field]) < (Time.now - self._monocle_options[:cache_threshold])
@@ -107,6 +138,11 @@ module Monocle
107
138
  set(cache_field_for_view(view_type), count) if respond_to?(:set)
108
139
  end
109
140
 
141
+ def cache_click_count(view_type, count)
142
+ update_column(cache_field_for_click(view_type), count) if respond_to?(:update_column)
143
+ set(cache_field_for_click(view_type), count) if respond_to?(:set)
144
+ end
145
+
110
146
  def destroy_views
111
147
  self._monocle_redis_connection.del(self.class.monocle_key(id))
112
148
  end
@@ -1,4 +1,6 @@
1
1
  require 'sinatra/base'
2
+ require 'base64'
3
+ require 'uri'
2
4
 
3
5
  module Monocle
4
6
  class Server < Sinatra::Base
@@ -10,6 +12,14 @@ module Monocle
10
12
  view_object(params[:type], params[:id])
11
13
  end
12
14
 
15
+ get '/:type/click/:id.:format' do
16
+ click_object(params[:type], params[:id], params[:redirect_to])
17
+ end
18
+
19
+ get '/:type/click/:redirect_to/:id.:format' do
20
+ click_object(params[:type], params[:id], params[:redirect_to])
21
+ end
22
+
13
23
  def view_object(type, id)
14
24
  if object = type.classify.constantize.find(id)
15
25
  object.view!
@@ -18,5 +28,12 @@ module Monocle
18
28
  'o_0'
19
29
  end
20
30
  end
31
+
32
+ def click_object(type, id, redirect_to)
33
+ if object = type.classify.constantize.find(id)
34
+ object.click!
35
+ redirect(Base64.decode64(URI.unescape(redirect_to)), 301)
36
+ end
37
+ end
21
38
  end
22
39
  end
@@ -1,3 +1,3 @@
1
1
  module Monocle
2
- VERSION = '0.2.2'
2
+ VERSION = '0.2.3'
3
3
  end
@@ -21,6 +21,10 @@ class TestObject
21
21
  attr_accessor :weekly_views, :daily_views, :hourly_views
22
22
  attr_accessor :quarterly_views
23
23
 
24
+ attr_accessor :overall_clicks, :yearly_clicks, :monthly_clicks
25
+ attr_accessor :weekly_clicks, :daily_clicks, :hourly_clicks
26
+ attr_accessor :quarterly_clicks
27
+
24
28
  def self.find(id)
25
29
  o = new
26
30
  o.id = id.to_i
@@ -29,7 +33,7 @@ class TestObject
29
33
 
30
34
  def initialize
31
35
  @id = '12345'
32
- @overall_views = 0
36
+ @overall_views, @overall_clicks = 0
33
37
  @updated_at = Time.now - 1.hour
34
38
  end
35
39
 
@@ -43,6 +47,7 @@ def make_viewed_objects(number_of_objects_to_make)
43
47
  o = TestObject.new
44
48
  o.id = i
45
49
  o.view!
50
+ o.click!
46
51
  end
47
52
  end
48
53
 
@@ -81,12 +86,14 @@ describe Monocle do
81
86
  object.view!
82
87
  object.destroy_views
83
88
  REDIS.hget('monocle:test_object:12345', 'overall_views').should == nil
89
+ REDIS.hget('monocle:test_object:12345', 'overall_clicks').should == nil
84
90
  end
85
91
  end
86
92
 
87
93
  describe '#cache_field_for_view' do
88
94
  it 'returns the cache field for the given view type' do
89
95
  object.cache_field_for_view('overall').should == :overall_views
96
+ object.cache_field_for_click('overall').should == :overall_clicks
90
97
  end
91
98
  end
92
99
 
@@ -117,7 +124,7 @@ describe Monocle do
117
124
  context 'when cache time is over threshold' do
118
125
  describe '#view!' do
119
126
  before { object.stub(:updated_at).and_return(Time.now - 1.hour) }
120
- before { 50.times { object.view! }}
127
+ before { 50.times { object.view! } }
121
128
  after { object.destroy_views }
122
129
 
123
130
  %w(overall yearly monthly weekly daily hourly quarterly).each do |view_type|
@@ -130,6 +137,22 @@ describe Monocle do
130
137
  end
131
138
  end
132
139
  end
140
+
141
+ describe '#click!' do
142
+ before { object.stub(:updated_at).and_return(Time.now - 1.hour) }
143
+ before { 50.times { object.click! } }
144
+ after { object.destroy_views }
145
+
146
+ %w(overall yearly monthly weekly daily hourly quarterly).each do |view_type|
147
+ it "sets #{view_type} views count" do
148
+ object.send("#{view_type}_clicks_count").should == 50
149
+ end
150
+
151
+ it "updates cached #{view_type} views count" do
152
+ object.send("#{view_type}_clicks").should == 50
153
+ end
154
+ end
155
+ end
133
156
  end
134
157
 
135
158
  context 'when cache time is under threshold' do
@@ -148,5 +171,21 @@ describe Monocle do
148
171
  end
149
172
  end
150
173
  end
174
+
175
+ describe '#click!' do
176
+ before { object.stub(:updated_at).and_return(Time.now) }
177
+ before { 50.times { object.click! }}
178
+ after { object.destroy_views }
179
+
180
+ %w(overall yearly monthly weekly daily hourly quarterly).each do |view_type|
181
+ it "sets #{view_type} views count" do
182
+ object.send("#{view_type}_clicks_count").should == 50
183
+ end
184
+
185
+ it "updates cached #{view_type} views count" do
186
+ object.send("#{view_type}_clicks").to_i.should == 0
187
+ end
188
+ end
189
+ end
151
190
  end
152
191
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monocle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -74,7 +74,6 @@ files:
74
74
  - LICENSE.txt
75
75
  - README.rdoc
76
76
  - Rakefile
77
- - VERSION
78
77
  - lib/monocle.rb
79
78
  - lib/monocle/core_ext.rb
80
79
  - lib/monocle/server.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.1.1