popularity 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
-
2
1
  module Popularity
3
2
  class RedditShare < Crawler
4
3
  include Popularity::ContainerMethods
4
+ stats :comments, :score, :posts
5
5
 
6
6
  def initialize(*args)
7
7
  super(*args)
@@ -19,20 +19,6 @@ module Popularity
19
19
  self
20
20
  end
21
21
 
22
- def to_json(options ={})
23
- total = {"comments" => 0, "posts" => 0, "score" => 0}
24
- return total unless @results
25
-
26
- @results.collect(&:to_json).each do |json|
27
- json.each do |key, value|
28
- total[key] ||= 0
29
- total[key] += value
30
- end
31
- end
32
- total["posts"] = posts
33
- total
34
- end
35
-
36
22
  def posts
37
23
  @results.size rescue 0
38
24
  end
@@ -45,4 +31,4 @@ module Popularity
45
31
  "http://www.reddit.com/r/search/search.json?q=url:#{@url}"
46
32
  end
47
33
  end
48
- end
34
+ end
@@ -1,17 +1,11 @@
1
1
  module Popularity
2
2
  class Rubygems < Crawler
3
+ stats :downloads
4
+
3
5
  def downloads
4
6
  response_json["downloads"]
5
7
  end
6
8
 
7
- def as_json(options = {})
8
- {"downloads" => downloads}
9
- end
10
-
11
- def total
12
- downloads
13
- end
14
-
15
9
  def valid?
16
10
  host == 'rubygems.org' && @url =~ /\/gems\//
17
11
  end
@@ -26,4 +20,4 @@ module Popularity
26
20
  "https://rubygems.org/api/v1/gems/#{gem_name}.json"
27
21
  end
28
22
  end
29
- end
23
+ end
@@ -1,5 +1,7 @@
1
1
  module Popularity
2
2
  class Soundcloud < Crawler
3
+ stats :plays, :likes, :comments, :downloads
4
+
3
5
  def plays
4
6
  response.scan(/\"soundcloud:play_count\" content=\"([0-9]*)\"/).flatten.first.to_f.to_i
5
7
  end
@@ -16,17 +18,6 @@ module Popularity
16
18
  response.scan(/\"soundcloud:download_count\" content=\"([0-9]*)\"/).flatten.first.to_f.to_i
17
19
  end
18
20
 
19
- def as_json(options = {})
20
- {"plays" => plays,
21
- "likes" => likes,
22
- "comments" => comments,
23
- "downloads" => downloads }
24
- end
25
-
26
- def total
27
- plays + likes + downloads + comments
28
- end
29
-
30
21
  def valid?
31
22
  host == 'soundcloud.com'
32
23
  end
@@ -41,4 +32,4 @@ module Popularity
41
32
  @url
42
33
  end
43
34
  end
44
- end
35
+ end
@@ -1,21 +1,15 @@
1
1
  module Popularity
2
2
  class Twitter < Crawler
3
+ stats :tweets
4
+
3
5
  def tweets
4
6
  response_json['count'].to_i if has_response?
5
7
  end
6
8
 
7
- def total
8
- tweets
9
- end
10
-
11
- def as_json(options = {})
12
- {"tweets" => tweets}
13
- end
14
-
15
9
  protected
16
10
 
17
11
  def request_url
18
12
  "https://cdn.api.twitter.com/1/urls/count.json?url=#{@url}"
19
13
  end
20
14
  end
21
- end
15
+ end
@@ -1,10 +1,9 @@
1
-
2
1
  module Popularity
3
2
  module ContainerMethods
4
3
  def self.included(base)
5
4
  base.class_eval do
6
5
  def results
7
- @results
6
+ @results || []
8
7
  end
9
8
 
10
9
  def add_result(result)
@@ -22,32 +21,42 @@ module Popularity
22
21
  end
23
22
  end
24
23
 
25
- def to_json(options ={})
26
- individual = {}
27
- total = {}
28
- @results.collect do |result|
29
- json = result.to_json
30
- individual[result.url] = json
31
-
32
- json.each do |key, value|
33
- next if key == "total"
34
-
35
- if value.is_a?(Hash)
36
- # RedditShare breaks out into separate results for each reddit link
37
- # I'm not a big fan of this hacky stuff here
38
- value.each do |k,v|
39
- total[k] ||= 0
40
- total[k] += v
41
- end
42
- else
43
- total[key] ||= 0
44
- total[key] += value
45
- end
24
+ def as_json(options = {})
25
+ result_property_names = []
26
+ results_json = self.results.collect do |r|
27
+ json = {}
28
+
29
+ r.class.property_names.each do |name|
30
+ json[name.to_s] = r.send(name.to_sym)
46
31
  end
32
+
33
+ json["total"] = r.total
34
+
35
+ {r.url => json}
47
36
  end
48
37
 
49
- individual["total"] = total
50
- individual
38
+ json = aggregate_json
39
+ json["_results"] = results_json
40
+
41
+ json
42
+ end
43
+
44
+ def aggregate_json
45
+ json = {}
46
+
47
+ names = if self.class.respond_to?(:property_names)
48
+ self.class.property_names
49
+ else
50
+ self.results.first.class.property_names
51
+ end
52
+
53
+ names.each do |name|
54
+ json[name.to_s] = self.send(name.to_sym)
55
+ end
56
+
57
+ json["total"] = self.total
58
+
59
+ json
51
60
  end
52
61
 
53
62
  def method_missing(method_sym, *arguments, &block)
@@ -57,7 +66,9 @@ module Popularity
57
66
  end
58
67
 
59
68
  if collection.all? { |t| t.is_a?(Fixnum) }
60
- collection.reduce(:+)
69
+ collection.reduce(:+)
70
+ else
71
+ collection.flatten
61
72
  end
62
73
  end
63
74
  end
@@ -3,7 +3,6 @@ module Popularity
3
3
  attr_accessor :info
4
4
  attr_accessor :results
5
5
  attr_accessor :sources
6
- attr_reader :total
7
6
  attr_reader :url
8
7
 
9
8
  def initialize(url)
@@ -14,10 +13,8 @@ module Popularity
14
13
  selected_types.each do |network|
15
14
  network.fetch_async do |code, body|
16
15
  add_result(network)
17
- begin
18
- if network.has_response?
19
- total_score << network.total
20
- end
16
+ begin
17
+
21
18
  rescue Exception => e
22
19
  puts "#{network.name} had an accident"
23
20
  puts e.message
@@ -26,24 +23,22 @@ module Popularity
26
23
  end
27
24
  end
28
25
 
29
- loop do
30
- # we want the requests to be asyncronous, but we don't
26
+ loop do
27
+ # we want the requests to be asyncronous, but we don't
31
28
  # want gem users to have to deal with async code
32
- #
29
+ #
33
30
  break if selected_types.all? { |network| network.async_done? }
34
31
  end
35
-
36
- @total = total_score.reduce(:+)
37
32
  end
38
33
 
39
- def to_json(options ={})
34
+ def as_json(options ={})
40
35
  json = {}
41
36
  self.results.collect do |result|
42
- json[result.name.to_s] = result.to_json
37
+ json[result.name.to_s] = result.as_json
43
38
  end
44
39
 
45
40
  self.sources.collect do |source|
46
- json[source.to_s] = self.send(source.to_sym).to_json
41
+ json[source.to_s] = self.send(source.to_sym).as_json
47
42
  end
48
43
 
49
44
  json["total"] = total
@@ -51,6 +46,10 @@ module Popularity
51
46
  json
52
47
  end
53
48
 
49
+ def total
50
+ self.results.collect(&:total).compact.reduce(:+)
51
+ end
52
+
54
53
  protected
55
54
 
56
55
  def selected_types
@@ -69,6 +68,8 @@ module Popularity
69
68
 
70
69
  self.instance_variable_set "@#{result.name}", result
71
70
 
71
+ # if there's a facebook result, this class will
72
+ # have a facebook method returning it
72
73
  self.define_singleton_method(result.name.to_sym) { result }
73
74
  end
74
75
 
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: popularity 0.1.1 ruby lib
5
+ # stub: popularity 0.2.1 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "popularity"
9
- s.version = "0.1.1"
9
+ s.version = "0.2.1"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Jeff Keen"]
14
- s.date = "2015-04-11"
14
+ s.date = "2015-05-22"
15
15
  s.description = "Supports Facebook, Twitter, Pinterest, Reddit (Links, Posts, and Comments), Github, Soundcloud, Medium, and Rubygems"
16
16
  s.email = "jeff@keen.me"
17
17
  s.extra_rdoc_files = [
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
21
21
  s.files = [
22
22
  ".document",
23
23
  ".rspec",
24
+ ".travis.yml",
24
25
  "Gemfile",
25
26
  "Gemfile.lock",
26
27
  "LICENSE.txt",
@@ -73,13 +74,7 @@ Gem::Specification.new do |s|
73
74
  "spec/search_spec.rb",
74
75
  "spec/soundcloud_spec.rb",
75
76
  "spec/spec_helper.rb",
76
- "spec/twitter_spec.rb",
77
- "test/facebook_test.rb",
78
- "test/fixtures/vcr_cassettes/facebook.yml",
79
- "test/fixtures/vcr_cassettes/google.yml",
80
- "test/helper.rb",
81
- "test/test_non_specific.rb",
82
- "test/test_twitter.rb"
77
+ "spec/twitter_spec.rb"
83
78
  ]
84
79
  s.homepage = "http://github.com/jkeen/popularity"
85
80
  s.licenses = ["MIT"]
@@ -93,7 +88,7 @@ Gem::Specification.new do |s|
93
88
  s.add_runtime_dependency(%q<open_uri_redirections>, ["~> 0"])
94
89
  s.add_runtime_dependency(%q<json>, ["~> 1.8"])
95
90
  s.add_runtime_dependency(%q<unirest>, ["~> 1"])
96
- s.add_development_dependency(%q<pry>, ["~> 0.10"])
91
+ s.add_runtime_dependency(%q<pry>, [">= 0"])
97
92
  s.add_development_dependency(%q<shoulda>, [">= 0"])
98
93
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
99
94
  s.add_development_dependency(%q<bundler>, ["~> 1.0"])
@@ -104,7 +99,7 @@ Gem::Specification.new do |s|
104
99
  s.add_dependency(%q<open_uri_redirections>, ["~> 0"])
105
100
  s.add_dependency(%q<json>, ["~> 1.8"])
106
101
  s.add_dependency(%q<unirest>, ["~> 1"])
107
- s.add_dependency(%q<pry>, ["~> 0.10"])
102
+ s.add_dependency(%q<pry>, [">= 0"])
108
103
  s.add_dependency(%q<shoulda>, [">= 0"])
109
104
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
110
105
  s.add_dependency(%q<bundler>, ["~> 1.0"])
@@ -116,7 +111,7 @@ Gem::Specification.new do |s|
116
111
  s.add_dependency(%q<open_uri_redirections>, ["~> 0"])
117
112
  s.add_dependency(%q<json>, ["~> 1.8"])
118
113
  s.add_dependency(%q<unirest>, ["~> 1"])
119
- s.add_dependency(%q<pry>, ["~> 0.10"])
114
+ s.add_dependency(%q<pry>, [">= 0"])
120
115
  s.add_dependency(%q<shoulda>, [">= 0"])
121
116
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
122
117
  s.add_dependency(%q<bundler>, ["~> 1.0"])
@@ -17,11 +17,11 @@ describe Popularity::GooglePlus do
17
17
  end
18
18
 
19
19
  context "json" do
20
- let(:json) { subject.to_json }
20
+ let(:json) { subject.as_json }
21
21
 
22
- it "should have required attributes in json" do
22
+ it "should have required attributes in json" do
23
23
  expect(subject.plus_ones).to eq(json["plus_ones"])
24
24
  end
25
25
  end
26
26
  end
27
- end
27
+ end
@@ -37,11 +37,11 @@ describe Popularity::Medium do
37
37
  end
38
38
 
39
39
  context "json" do
40
- let(:json) { subject.to_json }
40
+ let(:json) { subject.as_json }
41
41
 
42
- it "should have required attributes in json" do
42
+ it "should have required attributes in json" do
43
43
  expect(subject.recommends).to eq(json["recommends"])
44
44
  end
45
45
  end
46
46
  end
47
- end
47
+ end
@@ -17,11 +17,11 @@ describe Popularity::Pinterest do
17
17
  end
18
18
 
19
19
  context "json" do
20
- let(:json) { subject.to_json }
20
+ let(:json) { subject.as_json }
21
21
 
22
- it "should have required attributes in json" do
22
+ it "should have required attributes in json" do
23
23
  expect(subject.pins).to eq(json["pins"])
24
24
  end
25
25
  end
26
26
  end
27
- end
27
+ end
@@ -61,4 +61,4 @@ describe Popularity::RedditPost do
61
61
  expect(subject.total).to eq(subject.score + subject.comments)
62
62
  end
63
63
  end
64
- end
64
+ end
@@ -27,19 +27,48 @@ describe Popularity::RedditShare do
27
27
  end
28
28
 
29
29
  context "json" do
30
- let(:json) { subject.to_json }
30
+ let(:json) { subject.as_json }
31
31
 
32
- it "should include post count in json" do
33
- expect(25).to eq(json["posts"])
32
+ it "should include post count in json" do
33
+ expect(json["posts"]).to eq(25)
34
34
  end
35
35
 
36
- it "should comments in json" do
36
+ it "should have comments in json" do
37
37
  expect(json["comments"]).to_not be_nil
38
38
  end
39
39
 
40
- it "should score in json" do
40
+ it "should have score in json" do
41
41
  expect(json["score"]).to_not be_nil
42
42
  end
43
+
44
+ it "should have _results in json" do
45
+ expect(json["_results"]).to_not be_nil
46
+ end
47
+
48
+ context "results" do
49
+ let(:json_results) { subject.as_json["_results"] }
50
+
51
+ it "should equal number of results" do
52
+ expect(subject.results.size).to eq(json_results.size)
53
+ end
54
+
55
+ it "should contain the result urls" do
56
+ subject.results.each_with_index do |result, index|
57
+ json_result = json_results[index]
58
+
59
+ expect(json_result.keys.first).to eq(result.url)
60
+ end
61
+ end
62
+
63
+ it "should contain the correct values" do
64
+ subject.results.each_with_index do |result, index|
65
+ json_result = json_results[index]
66
+ expect(json_result.values.first["score"]).to eq(result.score)
67
+ expect(json_result.values.first["comments"]).to eq(result.comments)
68
+ expect(json_result.values.first["total"]).to eq(result.total)
69
+ end
70
+ end
71
+ end
43
72
  end
44
73
 
45
74
  context "unknown url" do
@@ -65,25 +94,25 @@ describe Popularity::RedditShare do
65
94
  end
66
95
 
67
96
  it "should have correct total" do
68
- expect(subject.total).to eq(subject.score + subject.comments)
97
+ expect(subject.total).to eq(subject.score + subject.comments + subject.posts)
69
98
  end
70
99
 
71
100
  context "json" do
72
- let(:json) { subject.to_json }
101
+ let(:json) { subject.as_json }
73
102
 
74
- it "should include post count in json" do
103
+ it "should include post count in json" do
75
104
  expect(0).to eq(json["posts"])
76
105
  end
77
106
 
78
- it "should comments in json" do
107
+ it "should comments in json" do
79
108
  expect(0).to eq(json["comments"])
80
109
  end
81
110
 
82
- it "should score in json" do
111
+ it "should score in json" do
83
112
  expect(0).to eq(json["score"])
84
113
  end
85
114
 
86
115
  end
87
116
  end
88
117
  end
89
- end
118
+ end