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