popularity 0.1.1 → 0.2.1

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: 8f43df47453436c7ba42f3d70d5196f939f518a5
4
- data.tar.gz: 8261963d61f74d92a8b06767d936a843d2d04c45
3
+ metadata.gz: 3c17e6a773a83fc813ffd30d5c14c2f72691c9e5
4
+ data.tar.gz: cd24795291873364d6383a473d94d191b21e83c9
5
5
  SHA512:
6
- metadata.gz: 5d867060540e84600a65bf8f33202314cc245466743a9b1acf64630c91964fe620624d56b435c6558bba88c9fb12ce54da34a201d5cc5be22c1d6ff45d97a95d
7
- data.tar.gz: 5e98e6ab95d4b38dc6e957523107d5e867a9712e517a43abb58c9f3d98ab992b48272f7d27c007ea091432a56789e1a65b3910278e85f3645b8240c92cf38bfa
6
+ metadata.gz: 473ced1189eab299c44f58b6fe32025c89e37c88b37311894adb3696ef9511ac282fbc8518d070a593692084ec281d1130106fbaed0459078a27e29598924f61
7
+ data.tar.gz: 01bfbee1959f78f8887da8dd1070ab31389ae7ac5537a2efc25d9cb3e4d2bca0abd2e59e4f46d86cd7f012e439978e4ce9317706711a17b8cd17be43f3dbea8f
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - "2.0.0"
5
+ - "2.1.1"
data/Gemfile CHANGED
@@ -3,9 +3,10 @@ source "http://rubygems.org"
3
3
  gem 'open_uri_redirections', '~> 0'
4
4
  gem 'json', '~> 1.8'
5
5
  gem 'unirest', '~> 1'
6
+ gem 'pry'
6
7
 
7
8
  group :development, :test do
8
- gem "pry", '~> 0.10'
9
+ # gem "pry", '~> 0.10'
9
10
  gem "shoulda", ">= 0"
10
11
  gem "rdoc", "~> 3.12"
11
12
  gem "bundler", "~> 1.0"
@@ -116,7 +116,7 @@ DEPENDENCIES
116
116
  jeweler (~> 2.0)
117
117
  json (~> 1.8)
118
118
  open_uri_redirections (~> 0)
119
- pry (~> 0.10)
119
+ pry
120
120
  rdoc (~> 3.12)
121
121
  rspec (~> 3.2)
122
122
  shoulda
data/README.md CHANGED
@@ -50,7 +50,7 @@ Sometimes multiple URLs refer to the same thing. Maybe your URLs changed, but yo
50
50
  JSON:
51
51
 
52
52
  ```ruby
53
- > search.to_json
53
+ > search.as_json
54
54
  #=> spits out by network, by url, and total stats
55
55
  ```
56
56
 
data/Rakefile CHANGED
@@ -25,20 +25,17 @@ Jeweler::Tasks.new do |gem|
25
25
  end
26
26
  Jeweler::RubygemsDotOrgTasks.new
27
27
 
28
- require 'rake/testtask'
29
- Rake::TestTask.new(:test) do |test|
30
- test.libs << 'lib' << 'test'
31
- test.pattern = 'test/**/test_*.rb'
32
- test.verbose = true
33
- end
34
-
35
28
  desc "Code coverage detail"
36
29
  task :simplecov do
37
30
  ENV['COVERAGE'] = "true"
38
- Rake::Task['test'].execute
31
+ Rake::Task['spec'].execute
39
32
  end
40
33
 
41
- task :default => :test
34
+ task :default => [:spec]
35
+ desc 'run Rspec specs'
36
+ task :spec do
37
+ sh 'rspec spec'
38
+ end
42
39
 
43
40
  require 'rdoc/task'
44
41
  Rake::RDocTask.new do |rdoc|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.1
@@ -7,7 +7,7 @@ module Popularity
7
7
  TYPES = []
8
8
  end
9
9
 
10
- Gem.find_files("popularity/networks/*.rb").each { |path|
10
+ Gem.find_files("popularity/networks/*.rb").each { |path|
11
11
  require path
12
12
  file_name = path.split('/').last.split('.').first
13
13
  class_name = file_name.gsub(/_[a-z]|^[a-z]/, &:upcase).gsub('_', '')
@@ -18,8 +18,6 @@ Gem.find_files("popularity/networks/*.rb").each { |path|
18
18
 
19
19
  module Popularity
20
20
  def self.search(*urls)
21
- response = {}
22
-
23
21
  MultiSearch.new(:urls => urls)
24
22
  end
25
23
 
@@ -43,20 +41,20 @@ module Popularity
43
41
  add_search_result(result)
44
42
  end
45
43
  end
46
- end
44
+ end
47
45
 
48
46
  def results
49
47
  searches.collect(&:results).reduce(:+)
50
48
  end
51
49
 
52
- def to_json(options = {})
50
+ def as_json(options = {})
53
51
  json = {}
54
52
  self.searches.collect do |search|
55
- json[search.url] = search.to_json
53
+ json[search.url] = search.as_json
56
54
  end
57
55
 
58
56
  self.sources.collect do |source|
59
- json[source.to_s] = self.send(source.to_sym).to_json
57
+ json[source.to_s] = self.send(source.to_sym).as_json
60
58
  end
61
59
 
62
60
  json["total"] = total
@@ -65,22 +63,17 @@ module Popularity
65
63
  end
66
64
 
67
65
  def total
68
- total = 0
69
- self.searches.each do |a|
70
- total += a.total
71
- end
72
-
73
- total
66
+ self.searches.collect(&:total).compact.reduce(:+)
74
67
  end
75
68
 
76
69
  protected
77
70
 
78
71
  def add_search_result(result)
79
- container = self.instance_variable_get("@#{result.name}")
72
+ container = self.instance_variable_get("@#{result.name}")
80
73
 
81
74
  unless container
82
- @sources ||= []
83
- @sources << result.name.to_sym
75
+ @sources ||= []
76
+ @sources << result.name.to_sym
84
77
  container = Popularity::ResultsContainer.new
85
78
  self.instance_variable_set "@#{result.name}", container
86
79
  self.define_singleton_method(result.name.to_sym) { container }
@@ -90,4 +83,4 @@ module Popularity
90
83
  end
91
84
 
92
85
  end
93
- end
86
+ end
@@ -2,11 +2,27 @@ require 'open-uri'
2
2
  require 'open_uri_redirections'
3
3
  require 'json'
4
4
  require 'unirest'
5
+ require 'pry'
5
6
 
6
7
  module Popularity
7
8
  class Crawler
8
9
  attr_reader :url
9
10
 
11
+ def self.stats(*args)
12
+ @property_names ||= []
13
+ args.each do |name|
14
+ @property_names << name
15
+ end
16
+ end
17
+
18
+ def self.property_names
19
+ @property_names
20
+ end
21
+
22
+ def total
23
+ self.class.property_names.uniq.collect { |n| self.send(n.to_sym) }.select { |t| t.class == Fixnum }.compact.reduce(:+)
24
+ end
25
+
10
26
  def initialize(url)
11
27
  @url = url
12
28
  end
@@ -22,13 +38,13 @@ module Popularity
22
38
  def has_response?
23
39
  response #fetch it
24
40
 
25
- return false if response.nil?
41
+ return false if response.nil?
26
42
  return false if response.empty?
27
43
 
28
44
  true
29
45
  end
30
46
 
31
- def valid?
47
+ def valid?
32
48
  true # to be overridden in subclasses
33
49
  end
34
50
 
@@ -48,8 +64,15 @@ module Popularity
48
64
  self.class.to_s.split('::').last.gsub(/(.)([A-Z])/,'\1_\2').downcase
49
65
  end
50
66
 
51
- def to_json(options = {})
52
- as_json(options)
67
+ def as_json(options = {})
68
+ json = {}
69
+
70
+ self.class.property_names.each do |name|
71
+ json[name.to_s] = self.send(name.to_sym)
72
+ end
73
+
74
+ json["total"] = total
75
+ json
53
76
  end
54
77
 
55
78
  def fetch_async(&block)
@@ -58,13 +81,13 @@ module Popularity
58
81
  Unirest.get(request_url) do |response|
59
82
  @async_done = true
60
83
  @response = response.raw_body
61
- block.call(response.code, response.raw_body) if block_given?
84
+ block.call(response.code, response.raw_body) if block_given?
62
85
  end
63
86
  end
64
87
 
65
88
  def fetch
66
89
  return false unless valid?
67
-
90
+
68
91
  begin
69
92
  response = Unirest.get(request_url)
70
93
  @response = response.raw_body
@@ -73,4 +96,4 @@ module Popularity
73
96
  end
74
97
  end
75
98
  end
76
- end
99
+ end
@@ -1,5 +1,7 @@
1
1
  module Popularity
2
2
  class Facebook < Crawler
3
+ stats :shares, :comments
4
+
3
5
  def shares
4
6
  response_json['shares'].to_f.to_i
5
7
  end
@@ -8,19 +10,10 @@ module Popularity
8
10
  response_json['comments'].to_f.to_i
9
11
  end
10
12
 
11
- def as_json(options = {})
12
- { "shares" => shares,
13
- "comments" => comments }
14
- end
15
-
16
- def total
17
- shares + comments
18
- end
19
-
20
13
  protected
21
14
 
22
- def request_url
23
- "http://graph.facebook.com/?id=#{@url}"
24
- end
25
- end
15
+ def request_url
16
+ "http://graph.facebook.com/?id=#{@url}"
17
+ end
18
+ end
26
19
  end
@@ -1,14 +1,8 @@
1
1
  module Popularity
2
2
  class Github < Crawler
3
- def stars
4
- response_json.size
5
- end
3
+ stats :stars
6
4
 
7
- def as_json(options = {})
8
- { "stars" => stars }
9
- end
10
-
11
- def total
5
+ def stars
12
6
  response_json.size
13
7
  end
14
8
 
@@ -25,4 +19,4 @@ module Popularity
25
19
  "https://api.github.com/repos/#{owner}/#{repo}/stargazers"
26
20
  end
27
21
  end
28
- end
22
+ end
@@ -1,22 +1,16 @@
1
1
  module Popularity
2
2
  class GooglePlus < Crawler
3
+ stats :plus_ones
4
+
3
5
  def plus_ones
4
- matches = response.scan(/window.__SSR = {c\: (\d+.\d+E?\d+)/)
6
+ matches = response.scan(/window.__SSR = {c\: (\d+.\d+E?\d+)/)
5
7
  matches.flatten.first.to_f.to_i
6
8
  end
7
9
 
8
- def as_json(options = {})
9
- {"plus_ones" => plus_ones}
10
- end
11
-
12
- def total
13
- plus_ones
14
- end
15
-
16
10
  protected
17
11
 
18
12
  def request_url
19
13
  "https://plusone.google.com/_/+1/fastbutton?url=#{URI::encode(@url)}"
20
14
  end
21
15
  end
22
- end
16
+ end
@@ -1,17 +1,11 @@
1
1
  module Popularity
2
2
  class Medium < Crawler
3
+ stats :recommends
4
+
3
5
  def recommends
4
6
  response_json["payload"]["value"]["count"]
5
7
  end
6
8
 
7
- def as_json(options = {})
8
- {"recommends" => recommends}
9
- end
10
-
11
- def total
12
- recommends
13
- end
14
-
15
9
  def valid?
16
10
  host == 'medium.com'
17
11
  end
@@ -30,4 +24,4 @@ module Popularity
30
24
  JSON.parse(response.sub("])}while(1);</x>", ""))
31
25
  end
32
26
  end
33
- end
27
+ end
@@ -1,21 +1,15 @@
1
1
  module Popularity
2
2
  class Pinterest < Crawler
3
+ stats :pins
4
+
3
5
  def pins
4
6
  JSON.parse(response.gsub('receiveCount(','').gsub(')',''))['count'].to_f.to_i
5
7
  end
6
8
 
7
- def as_json(options = {})
8
- {"pins" => pins}
9
- end
10
-
11
- def total
12
- pins
13
- end
14
-
15
9
  protected
16
10
 
17
11
  def request_url
18
12
  "http://api.pinterest.com/v1/urls/count.json?url=#{@url}"
19
13
  end
20
14
  end
21
- end
15
+ end
@@ -1,20 +1,14 @@
1
1
  module Popularity
2
2
  class RedditComment < Crawler
3
- def score
4
- response_json[1]["data"]["children"][0]["data"]["score"]
5
- end
6
-
7
- def as_json(options = {})
8
- {"score" => score}
9
- end
3
+ stats :score
10
4
 
11
- def total
12
- score
5
+ def score
6
+ response_json[1]["data"]["children"][0]["data"]["score"]
13
7
  end
14
8
 
15
9
  def valid?
16
10
  return false unless host == 'reddit.com'
17
-
11
+
18
12
  path = URI.parse(@url).path
19
13
  path.split('/').delete_if { |a| a.empty? }.size == 6
20
14
  end
@@ -1,8 +1,10 @@
1
1
  module Popularity
2
2
  class RedditPost < Crawler
3
+ stats :score, :comments
4
+
3
5
  def score
4
6
  begin
5
- response_json[0]["data"]["children"][0]["data"]["score"]
7
+ response_json[0]["data"]["children"][0]["data"]["score"]
6
8
  rescue
7
9
  0
8
10
  end
@@ -10,26 +12,15 @@ module Popularity
10
12
 
11
13
  def comments
12
14
  begin
13
- response_json[0]["data"]["children"][0]["data"]["num_comments"]
15
+ response_json[0]["data"]["children"][0]["data"]["num_comments"]
14
16
  rescue
15
17
  0
16
18
  end
17
19
  end
18
20
 
19
- def as_json(options = {})
20
- {
21
- "comments" => comments,
22
- "score" => score
23
- }
24
- end
25
-
26
- def total
27
- comments + score
28
- end
29
-
30
21
  def valid?
31
22
  return false unless host == 'reddit.com'
32
-
23
+
33
24
  path = URI.parse(@url).path
34
25
  path.split('/').delete_if { |a| a.empty? }.size < 6
35
26
  end
@@ -46,11 +37,14 @@ module Popularity
46
37
  end
47
38
 
48
39
  class RedditResult < RedditPost
49
- # A stubbed out version of a RedditPost so RedditShare can
40
+ # A stubbed out version of a RedditPost so RedditShare can
50
41
  # stub in the json response it already has
51
42
 
43
+ stats :score, :comments
44
+
52
45
  def initialize(url, r)
53
46
  super(url)
47
+ @url = url
54
48
  @response = r
55
49
 
56
50
  self
@@ -60,6 +54,10 @@ module Popularity
60
54
  true
61
55
  end
62
56
 
57
+ def reddit_url
58
+ @url
59
+ end
60
+
63
61
  def valid?
64
62
  URI.parse(@url).host
65
63
  end