monocle 0.2.2 → 0.2.3
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/lib/monocle.rb +36 -0
- data/lib/monocle/server.rb +17 -0
- data/lib/monocle/version.rb +1 -1
- data/spec/monocle_spec.rb +41 -2
- metadata +1 -2
- data/VERSION +0 -1
data/lib/monocle.rb
CHANGED
@@ -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
|
data/lib/monocle/server.rb
CHANGED
@@ -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
|
data/lib/monocle/version.rb
CHANGED
data/spec/monocle_spec.rb
CHANGED
@@ -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.
|
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
|