share_counts 0.0.2 → 0.0.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/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
+ check.rb
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- share_counts (0.0.1)
4
+ share_counts (0.0.2)
5
5
  json
6
6
  nokogiri
7
7
  redis
@@ -1,110 +1,112 @@
1
- module ShareCountsCaching
2
-
3
- #
4
- #
5
- # Returns true if the Redis
6
- # cache store has been initialised
7
- #
8
- #
9
- def cache_enabled?
10
- !$share_counts_cache.nil?
11
- end
1
+ module ShareCounts
2
+ module Caching
12
3
 
4
+ #
5
+ #
6
+ # Returns true if the Redis
7
+ # cache store has been initialised
8
+ #
9
+ #
10
+ def cache_enabled?
11
+ !$share_counts_cache.nil?
12
+ end
13
13
 
14
14
 
15
- #
16
- #
17
- # Removes from Redis cache store all the keys
18
- # used by ShareCounts.
19
- #
20
- #
21
- def clear_cache
22
- ($share_counts_cache || {}).keys.select{|cache_key| cache_key =~ /^ShareCounts/ }.each{|cache_key|
23
- $share_counts_cache.del cache_key}
24
- end
25
-
26
-
27
- #
28
- #
29
- # Returns the cached share counts available for each URL, in the format
30
- #
31
- # {
32
- # "URL 1": {
33
- # :reddit => N,
34
- # :digg => N,
35
- # :twitter => N,
36
- # :facebook => N,
37
- # :fblike => N,
38
- # :linkedin => N,
39
- # :googlebuzz => N,
40
- # :stumbleupon => N
41
- # },
42
- #
43
- # "URL 2": {
44
- # ...
45
- # }
46
- # }
47
- #
48
- #
49
- def cached
50
- urls = ($share_counts_cache || {}).keys.select{|k| k =~ /^ShareCounts/ }.inject({}) do |result, key|
51
- data = key.split("||"); network = data[1]; url = data[2];
52
- count = from_redis("ShareCounts||#{network}||#{url}")
53
- (result[url] ||= {})[network.to_sym] = count unless ["all", "fball"].include? network
54
- result
15
+
16
+ #
17
+ #
18
+ # Removes from Redis cache store all the keys
19
+ # used by ShareCounts.
20
+ #
21
+ #
22
+ def clear_cache
23
+ ($share_counts_cache || {}).keys.select{|cache_key| cache_key =~ /^ShareCounts/ }.each{|cache_key|
24
+ $share_counts_cache.del cache_key}
55
25
  end
56
- urls
57
- end
58
-
59
- #
60
- #
61
- # Enables caching with Redis.
62
- #
63
- # By default, it connects to 127.0.0.1:6379, but it is also
64
- # possible to specify in the arguments :host, :port the
65
- # connection details.
66
- #
67
- # If the application using this gem is already using Redis too,
68
- # with the "redis" gem, it is possible to use the existing
69
- # instance of Redis by either setting the :redist_store argument
70
- # or by setting the global variable $share_counts_cache first.
71
- #
72
- #
73
- def use_cache *args
74
- arguments = args.inject({}) { |r, c| r.merge(c) }
75
- $share_counts_cache ||= arguments[:redis_store] ||
76
- Redis.new(:host => arguments[:host] || "127.0.0.1", :port => arguments[:port] || "6379")
77
- end
78
26
 
79
27
 
80
- private
81
-
82
- #
83
- #
84
- # Caches the given value in Redis under the key specified.
85
- # By default the value is cached for two minutes, but it
86
- # is also possible to override this expiration time by
87
- # setting the global variable $share_counts_cache_expire
88
- # to a number of seconds.
89
- #
90
- #
91
- def to_redis(cache_key, value)
92
- $share_counts_cache.set cache_key, Marshal.dump(value)
93
- $share_counts_cache.expire cache_key, $share_counts_cache_expire || 120
94
- value
95
- end
28
+ #
29
+ #
30
+ # Returns the cached share counts available for each URL, in the format
31
+ #
32
+ # {
33
+ # "URL 1": {
34
+ # :reddit => N,
35
+ # :digg => N,
36
+ # :twitter => N,
37
+ # :facebook => N,
38
+ # :fblike => N,
39
+ # :linkedin => N,
40
+ # :googlebuzz => N,
41
+ # :stumbleupon => N
42
+ # },
43
+ #
44
+ # "URL 2": {
45
+ # ...
46
+ # }
47
+ # }
48
+ #
49
+ #
50
+ def cached
51
+ urls = ($share_counts_cache || {}).keys.select{|k| k =~ /^ShareCounts/ }.inject({}) do |result, key|
52
+ data = key.split("||"); network = data[1]; url = data[2];
53
+ count = from_redis("ShareCounts||#{network}||#{url}")
54
+ (result[url] ||= {})[network.to_sym] = count unless ["all", "fball"].include? network
55
+ result
56
+ end
57
+ urls
58
+ end
59
+
60
+ #
61
+ #
62
+ # Enables caching with Redis.
63
+ #
64
+ # By default, it connects to 127.0.0.1:6379, but it is also
65
+ # possible to specify in the arguments :host, :port the
66
+ # connection details.
67
+ #
68
+ # If the application using this gem is already using Redis too,
69
+ # with the "redis" gem, it is possible to use the existing
70
+ # instance of Redis by either setting the :redist_store argument
71
+ # or by setting the global variable $share_counts_cache first.
72
+ #
73
+ #
74
+ def use_cache *args
75
+ arguments = args.inject({}) { |r, c| r.merge(c) }
76
+ $share_counts_cache ||= arguments[:redis_store] ||
77
+ Redis.new(:host => arguments[:host] || "127.0.0.1", :port => arguments[:port] || "6379")
78
+ end
79
+
80
+
81
+ private
82
+
83
+ #
84
+ #
85
+ # Caches the given value in Redis under the key specified.
86
+ # By default the value is cached for two minutes, but it
87
+ # is also possible to override this expiration time by
88
+ # setting the global variable $share_counts_cache_expire
89
+ # to a number of seconds.
90
+ #
91
+ #
92
+ def to_redis(cache_key, value)
93
+ $share_counts_cache.set cache_key, Marshal.dump(value)
94
+ $share_counts_cache.expire cache_key, $share_counts_cache_expire || 120
95
+ value
96
+ end
97
+
98
+
99
+ #
100
+ #
101
+ # Retrieves the value stores in Redis under
102
+ # the given key.
103
+ #
104
+ #
105
+ def from_redis(cache_key)
106
+ value = $share_counts_cache.get(cache_key)
107
+ return if value.nil?
108
+ Marshal.load value
109
+ end
96
110
 
97
-
98
- #
99
- #
100
- # Retrieves the value stores in Redis under
101
- # the given key.
102
- #
103
- #
104
- def from_redis(cache_key)
105
- value = $share_counts_cache.get(cache_key)
106
- return if value.nil?
107
- Marshal.load value
108
111
  end
109
-
110
- end
112
+ end
@@ -1,106 +1,108 @@
1
- module ShareCountsCommon
1
+ module ShareCounts
2
+ module Common
2
3
 
3
- private
4
-
5
- #
6
- #
7
- # Given the name of one of the supported social networks and a URL,
8
- # attempts the execution of the given block to fetch the relevant share count.
9
- #
10
- # If caching with Redis is enabled, it will first try to
11
- # fetch the share count from cache instead, if there is a valid
12
- # cached value for the combination of network/URL. When a share count is
13
- # instead retrieved with an HTTP request to the network's API and
14
- # the caching with Redis is enabled, the value fetched is also cached.
15
- #
16
- # NOTE: caching will be skipped if the block fails.
17
- #
18
- #
19
- def try service, url, &block
20
- cache_key = "ShareCounts||#{service}||#{url}"
21
- if cache_enabled?
22
- if result = from_redis(cache_key)
23
- puts "Loaded #{service} count from cache"
24
- result
4
+ private
5
+
6
+ #
7
+ #
8
+ # Given the name of one of the supported social networks and a URL,
9
+ # attempts the execution of the given block to fetch the relevant share count.
10
+ #
11
+ # If caching with Redis is enabled, it will first try to
12
+ # fetch the share count from cache instead, if there is a valid
13
+ # cached value for the combination of network/URL. When a share count is
14
+ # instead retrieved with an HTTP request to the network's API and
15
+ # the caching with Redis is enabled, the value fetched is also cached.
16
+ #
17
+ # NOTE: caching will be skipped if the block fails.
18
+ #
19
+ #
20
+ def try service, url, &block
21
+ cache_key = "ShareCounts||#{service}||#{url}"
22
+ if cache_enabled?
23
+ if result = from_redis(cache_key)
24
+ puts "Loaded #{service} count from cache"
25
+ result
26
+ else
27
+ puts "Making request to #{service}..."
28
+ to_redis(cache_key, yield)
29
+ end
25
30
  else
26
- puts "Making request to #{service}..."
27
- to_redis(cache_key, yield)
31
+ puts "Redis caching is disabled - Making request to #{service}..."
32
+ yield
28
33
  end
29
- else
30
- puts "Redis caching is disabled - Making request to #{service}..."
31
- yield
34
+ rescue Exception => e
35
+ puts "Something went wrong with #{service}: #{e}"
32
36
  end
33
- rescue Exception => e
34
- puts "Something went wrong with #{service}: #{e}"
35
- end
36
37
 
37
38
 
38
- #
39
- #
40
- # Performs an HTTP request to the given API URL with the specified params
41
- # and within 2 seconds, and max 3 attempts
42
- #
43
- # If a :callback param is also specified, then it is assumed that the API
44
- # returns a JSON text wrapped in a call to a method by that callback name,
45
- # therefore in this case it manipulates the response to extract only
46
- # the JSON data required.
47
- #
48
- def make_request *args
49
- result = nil
50
- attempts = 1
39
+ #
40
+ #
41
+ # Performs an HTTP request to the given API URL with the specified params
42
+ # and within 2 seconds, and max 3 attempts
43
+ #
44
+ # If a :callback param is also specified, then it is assumed that the API
45
+ # returns a JSON text wrapped in a call to a method by that callback name,
46
+ # therefore in this case it manipulates the response to extract only
47
+ # the JSON data required.
48
+ #
49
+ def make_request *args
50
+ result = nil
51
+ attempts = 1
51
52
 
52
- begin
53
- timeout(2) do
54
- url = args.shift
55
- params = args.inject({}) { |r, c| r.merge! c }
56
- response = RestClient.get url, { :params => params }
53
+ begin
54
+ timeout(2) do
55
+ url = args.shift
56
+ params = args.inject({}) { |r, c| r.merge! c }
57
+ response = RestClient.get url, { :params => params }
57
58
 
58
59
 
59
- # if a callback is specified, the expected response is in the format "callback_name(JSON data)";
60
- # with the response ending with ";" and, in some cases, "\n"
61
- result = params.keys.include?(:callback) \
62
- ? response.gsub(/^(.*);+\n*$/, "\\1").gsub(/^#{params[:callback]}\((.*)\)$/, "\\1") \
63
- : response
60
+ # if a callback is specified, the expected response is in the format "callback_name(JSON data)";
61
+ # with the response ending with ";" and, in some cases, "\n"
62
+ result = params.keys.include?(:callback) \
63
+ ? response.gsub(/^(.*);+\n*$/, "\\1").gsub(/^#{params[:callback]}\((.*)\)$/, "\\1") \
64
+ : response
65
+ end
66
+
67
+ rescue Exception => e
68
+ puts "Failed #{attempts} attempt(s)"
69
+ attempts += 1
70
+ retry if attempts <= 3
64
71
  end
65
-
66
- rescue Exception => e
67
- puts "Failed #{attempts} attempt(s)"
68
- attempts += 1
69
- retry if attempts <= 3
72
+
73
+ result
70
74
  end
71
-
72
- result
73
- end
74
75
 
75
76
 
76
- #
77
- #
78
- # Makes an HTTP request with the given URL and params, and assumes
79
- # that the response is in JSON format, therefore it returns
80
- # the parsed JSON.
81
- #
82
- #
83
- def from_json *args
84
- JSON.parse make_request *args
85
- end
77
+ #
78
+ #
79
+ # Makes an HTTP request with the given URL and params, and assumes
80
+ # that the response is in JSON format, therefore it returns
81
+ # the parsed JSON.
82
+ #
83
+ #
84
+ def from_json *args
85
+ JSON.parse make_request *args
86
+ end
86
87
 
87
- #
88
- #
89
- # Most social networks' APIs returns normal JSON data;
90
- # this method simply extracts directly the share count from
91
- # the given JSON data, by following a pattern common to the
92
- # structure of most JSON responses.
93
- #
94
- # It also requires a :selector argument that determines how
95
- # to "query" the JSON data in a way that emulates XPATH,
96
- # so to extract the share count.
97
- #
98
- #
99
- def extract_count *args
100
- json = args.shift
101
- result = args.first.flatten.last.split("/").inject( json.is_a?(Array) ? json.first : json ) {
102
- |r, c| r[c].is_a?(Array) ? r[c].first : r[c]
103
- }
104
- end
88
+ #
89
+ #
90
+ # Most social networks' APIs returns normal JSON data;
91
+ # this method simply extracts directly the share count from
92
+ # the given JSON data, by following a pattern common to the
93
+ # structure of most JSON responses.
94
+ #
95
+ # It also requires a :selector argument that determines how
96
+ # to "query" the JSON data in a way that emulates XPATH,
97
+ # so to extract the share count.
98
+ #
99
+ #
100
+ def extract_count *args
101
+ json = args.shift
102
+ result = args.first.flatten.last.split("/").inject( json.is_a?(Array) ? json.first : json ) {
103
+ |r, c| r[c].is_a?(Array) ? r[c].first : r[c]
104
+ }
105
+ end
105
106
 
106
- end
107
+ end
108
+ end
data/lib/share_counts.rb CHANGED
@@ -5,8 +5,8 @@ require File.expand_path(File.dirname(__FILE__) + "/share_counts/caching")
5
5
 
6
6
  module ShareCounts
7
7
 
8
- extend ShareCountsCommon
9
- extend ShareCountsCaching
8
+ extend Common
9
+ extend Caching
10
10
 
11
11
  def self.supported_networks
12
12
  %w(reddit digg twitter facebook fblike linkedin googlebuzz stumbleupon)
data/share_counts.gemspec CHANGED
@@ -4,7 +4,7 @@ $:.push File.expand_path("../lib/share_counts", __FILE__)
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "share_counts"
7
- s.version = "0.0.2"
7
+ s.version = "0.0.3"
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Vito Botta"]
10
10
  s.email = ["vito@botta.name"]
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Vito Botta
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-30 00:00:00 +00:00
17
+ date: 2011-01-31 00:00:00 +00:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency