popularity 0.1.1 → 0.2.1

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.
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