rubyoverflow 1.0.2 → 2.0.2.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +5 -0
  2. data/.rvmrc +47 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +1 -1
  6. data/README.rdoc +14 -20
  7. data/RELEASENOTES +1 -97
  8. data/Rakefile +7 -49
  9. data/lib/rubyoverflow.rb +46 -108
  10. data/lib/rubyoverflow/answers.rb +5 -57
  11. data/lib/rubyoverflow/base.rb +21 -68
  12. data/lib/rubyoverflow/questions.rb +5 -101
  13. data/lib/rubyoverflow/sites.rb +18 -0
  14. data/lib/rubyoverflow/stats.rb +8 -0
  15. data/lib/rubyoverflow/users.rb +5 -70
  16. data/lib/rubyoverflow/version.rb +3 -0
  17. data/rubyoverflow.gemspec +26 -0
  18. data/spec/answers_spec.rb +13 -0
  19. data/spec/questions_spec.rb +13 -0
  20. data/spec/sites_spec.rb +18 -0
  21. data/spec/spec_helper.rb +3 -0
  22. data/spec/stats_spec.rb +12 -0
  23. data/spec/users_spec.rb +23 -0
  24. metadata +94 -121
  25. data/VERSION +0 -1
  26. data/lib/rubyoverflow/answer.rb +0 -61
  27. data/lib/rubyoverflow/apiSite.rb +0 -32
  28. data/lib/rubyoverflow/apiSites.rb +0 -25
  29. data/lib/rubyoverflow/apiVersion.rb +0 -6
  30. data/lib/rubyoverflow/badge.rb +0 -44
  31. data/lib/rubyoverflow/badgeCounts.rb +0 -22
  32. data/lib/rubyoverflow/badges.rb +0 -59
  33. data/lib/rubyoverflow/comment.rb +0 -41
  34. data/lib/rubyoverflow/comments.rb +0 -115
  35. data/lib/rubyoverflow/errors.rb +0 -17
  36. data/lib/rubyoverflow/pagedBase.rb +0 -27
  37. data/lib/rubyoverflow/pagedDash.rb +0 -7
  38. data/lib/rubyoverflow/postTimelineEvent.rb +0 -93
  39. data/lib/rubyoverflow/postTimelineEvents.rb +0 -39
  40. data/lib/rubyoverflow/question.rb +0 -110
  41. data/lib/rubyoverflow/repChange.rb +0 -34
  42. data/lib/rubyoverflow/repChanges.rb +0 -41
  43. data/lib/rubyoverflow/revision.rb +0 -62
  44. data/lib/rubyoverflow/revisions.rb +0 -52
  45. data/lib/rubyoverflow/statistics.rb +0 -57
  46. data/lib/rubyoverflow/styling.rb +0 -19
  47. data/lib/rubyoverflow/tag.rb +0 -27
  48. data/lib/rubyoverflow/tags.rb +0 -46
  49. data/lib/rubyoverflow/user.rb +0 -181
  50. data/lib/rubyoverflow/userTimelineEvent.rb +0 -43
  51. data/lib/rubyoverflow/userTimelineEvents.rb +0 -35
  52. data/test/apiKey.rb +0 -5
  53. data/test/helper.rb +0 -159
  54. data/test/test_answer.rb +0 -20
  55. data/test/test_answers.rb +0 -32
  56. data/test/test_badge.rb +0 -18
  57. data/test/test_badges.rb +0 -30
  58. data/test/test_base.rb +0 -63
  59. data/test/test_statistics.rb +0 -26
  60. data/test/test_user.rb +0 -56
  61. data/test/test_users.rb +0 -37
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rspec
data/.rvmrc ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.9.2-p290@rubyoverflow"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+
14
+ #
15
+ # First we attempt to load the desired environment directly from the environment
16
+ # file. This is very fast and efficient compared to running through the entire
17
+ # CLI and selector. If you want feedback on which environment was used then
18
+ # insert the word 'use' after --create as this triggers verbose mode.
19
+ #
20
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
+ then
23
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
+
25
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
+ then
27
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
+ fi
29
+ else
30
+ # If the environment file has not yet been created, use the RVM CLI to select.
31
+ if ! rvm --create use "$environment_id"
32
+ then
33
+ echo "Failed to create RVM environment '${environment_id}'."
34
+ exit 1
35
+ fi
36
+ fi
37
+
38
+ #
39
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
+ # it be automatically loaded. Uncomment the following and adjust the filename if
41
+ # necessary.
42
+ #
43
+ # filename=".gems"
44
+ # if [[ -s "$filename" ]] ; then
45
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
46
+ # fi
47
+
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 phsr
1
+ Copyright (c) 2010 Dan Seaver
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -2,33 +2,27 @@
2
2
 
3
3
  rubyoverflow is a library for querying the Stack Overflow API
4
4
 
5
- == Configuration
5
+ == Build Status
6
+ {<img src="https://secure.travis-ci.org/danseaver/rubyoverflow.png" />}[http://travis-ci.org/danseaver/rubyoverflow]
7
+
8
+ == Dependency Status
9
+ {<img src="https://gemnasium.com/danseaver/rubyoverflow.png" alt="Dependency Status Gemnasium" />}[https://gemnasium.com/danseaver/rubyoverflow]
6
10
 
7
- Rubyoverflow::Client.config do |options|
8
- options.host = 'http://api.superuser.com' # optional, defaults to stackoverflow, queries super user
9
- options.api_key = 'api_key_here' # optional, sets the api key
10
- options.version = '0.8' # optional, defaults to 0.8,sets the api version
11
- end
12
11
 
13
12
  == Example
14
13
 
15
14
  require 'rubyoverflow'
16
- include Rubyoverflow
17
- # Tags Example
18
- tagsSet = Tags.retrieve_all({:sort=>'name',:order=>'asc',:pagesize=>'5'}) # gets the first 5 tags in alphabetical order by name
19
- firstTag = tagsSet.tags.first # gets the first tag
20
- secondTagSet = tagsSet.get_next_set #gets the next page of tags using the prior parameters
21
- thirdTagSet = secondTagSet.get_next_set #gets the third page of tags using the prior parameters
22
- puts firstTag.name # => tag's name
23
- puts tag.count # => # of questions with tag
24
-
25
- #User Example
26
- me = Users.retrieve_by_id(53587).users.first #gets me
27
- myquestions = me.get_questions #gets the questions I asked
15
+
16
+ c = Rubyoverflow::Client.new
17
+ result = c.users.fetch(:id => 53587) # By default, this will query StackOverflow.com
18
+ me = result.users.first # Get the first user out of the results
19
+ puts me.display_name # => "Dan Seaver"
28
20
 
29
21
 
22
+ c = Rubyoverflow::Client.new :host => "http://api.serverfault.com" # Query ServerFault.com
23
+
30
24
  == Note on Patches/Pull Requests
31
-
25
+
32
26
  * Fork the project.
33
27
  * Make your feature addition or bug fix.
34
28
  * Add tests for it. This is important so I don't break it in a
@@ -39,5 +33,5 @@ rubyoverflow is a library for querying the Stack Overflow API
39
33
 
40
34
  == Copyright
41
35
 
42
- Copyright (c) 2010 phsr. See LICENSE for details.
36
+ Copyright (c) 2011 Dan Seaver. See LICENSE for details.
43
37
 
@@ -1,98 +1,2 @@
1
- [1.0.1]
2
- Minor formatting refactorings
3
- Setup tests with rspec
4
- Updated Client.new to accept an ApiSite
5
- Added Styling class
6
- Added styling and state to ApiSite (was previously missing)
7
- Added change_end_point to Client and Base classes (accessible from any querying class)
8
- Removed display_name from Statistics
9
- Added site, total_accepted, and view_per_day from Statistics (was previously missing)
10
- Added tests for Answer and Answers
11
- Added tests for Base and got Base.convert_if_array working correctly
12
- Replaced convert_if_array to convert_to_id_list
13
- Added User#item_id
14
- Added tests for Badge and Badges
15
- Completed check_badge_set stub in test/helper
16
- Added item_id to badge so that you can pass an array containing badges to a method
17
- Updated convert_if_array to append the id of an item if that class defines the item_id method
18
- Added protected_date to Question (previously missing)
19
- Removed parameters from User#get_badges, as the route doesn't support parameters
20
- Update Users.retrieve_by_badge to support a Badge as a parameter
21
- Stubbed out test helper methods for checking class sets
22
- Completed unit tests for Users and User classes
23
-
24
-
25
- [1.0.0]
26
- Updated PostTimelineEvent to implement new property, question_id
27
- Updated get_post to properly handle the post being a question or answer
28
- Added get_parent_question to PostTimelineEvent
29
-
30
- [0.9.1]
31
- Switched from using Open-URI+GZIP+JSON to HTTParty
32
-
33
- [0.9.0]
34
- Updated API_VERSION to match the Stack Exchange API version
35
-
36
- [0.8.4]
37
- Added ApiSite and ApiSites as well as ApiSites.retrieve_sites to retrieve all API endpoints known to the Stack Exchange API
38
- Added the class method Users.retrieve_associated_accounts and the instance method User.retrieve_associated_accounts, which calls the Users.retrieve_associated_accounts method with the instance's associated_id
39
-
40
- [0.8.3]
41
- Added Badge#get_recipients
42
- Added Answer#get_comments
43
- Added Users.get_moderators
44
- Added PostTimelineEvent#get_post, PostTimelineEvent#get_post_comment, and PostTimelineEvent#get_revision
45
- Added Question#get_timeline, Question#get_answers, Question#get_comments
46
-
47
- [0.8.2]
48
- Added get_next_set to paged results, retrieve the next set using the same parameters that were used to retrieve the initial set
49
- Added methods to get answers, questions, favorites, etc from a user that has been retrieved
50
-
51
- [0.8.1]
52
- All classes moved into the Rubyoverflow module
53
-
54
- [0.8.0]
55
- Added Revision and Revisions, along with revision retrieval methods
56
- Added Questions.search which maps to '/search'
57
- Added Errors
58
-
59
- [0.6.0]
60
- Added RepChange and RepChanges with RepChanges.retrieve_by_user
61
- Added UserTimeLineEvent and UserTimeLineEvents with UserTimeLineEvent.retrieve_by_user
62
- Added PostTimeLineEvent and PostTimeLineEvents with PostTimeLineEvent.retrieve_by_question
63
-
64
- [0.5.1]
65
- Removed @dash member from classes, as it is only used in initialize, shrinking memory usage of classes
66
-
67
1
  [0.5.0]
68
- Added Question and Questions with question retrieval methods
69
-
70
- [0.4.1]
71
- Added Users and retrieve, retrieve_by_id and retrieve_by_badge
72
-
73
- [0.4.0]
74
- Added Comment and Answer wrappers
75
- Added retrieval methods for comments and answers
76
-
77
- [0.3.2]
78
- Update Badges.retrieve_by_user(id) and Tags.retrieve_by_user(id) to accept an array of ids
79
-
80
- [0.3.1]
81
- Added Badges.retrieve_by_user(id)
82
- Fixed User class (added if to creation of BadgesCount member)
83
-
84
- [0.3.0]
85
- Mapped User, Badge, BadgeCount, Badges
86
- Added PagedBase and PagedDash to reuse common properties of paged queries
87
- Added Badges.retrieve_all, retrieve_all_non_tag_based and retrieve_all_tag_based
88
- Refactored Tags to use new PagedBase and PagedDash classes
89
-
90
- [0.2.3]
91
- Tags.retrieve_by_user(id,parameters) gets tags that the user has participated in
92
-
93
- [0.2.0-2]
94
- Added support for query string, api key, other stack overflow sites
95
- Added support for Tag retrieval
96
-
97
- [0.1]
98
- Initial Release, retrieves stack overflow statistics
2
+ Restarting rubyoverflow development, paths /sites and /users (only, no sub-paths) covered
data/Rakefile CHANGED
@@ -1,52 +1,10 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require 'rspec'
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "rubyoverflow"
8
- gem.summary = %Q{rubyoverflow is a library for querying the Stack Overflow API}
9
- gem.description = %Q{rubyoverflow is a library for querying the Stack Overflow API}
10
- gem.email = "phasor@phsr.org"
11
- gem.homepage = "http://github.com/phsr/rubyoverflow"
12
- gem.authors = ["phsr"]
13
- gem.add_dependency 'httparty', '>=0'
14
- gem.add_dependency 'hashie', '>=0'
15
- gem.add_development_dependency "rspec", ">= 0"
16
- gem.files.include FileList['lib/**/*.rb', 'bin/*', '[A-Z]*', 'test/**/*'].to_a
17
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
- end
19
- Jeweler::GemcutterTasks.new
20
- rescue LoadError
21
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
22
- end
23
-
1
+ require 'bundler/gem_tasks'
24
2
 
25
-
26
- begin
27
- require 'rcov/rcovtask'
28
- Rcov::RcovTask.new do |test|
29
- test.libs << 'test'
30
- test.pattern = 'test/**/test_*.rb'
31
- test.verbose = true
32
- end
33
- rescue LoadError
34
- task :rcov do
35
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
- end
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec) do |t|
6
+ t.pattern = 'spec/**/*_spec.rb'
7
+ t.rspec_opts = '--format progress'
37
8
  end
38
9
 
39
-
40
- task :default => :test
41
-
42
- task :doc => :rdoc
43
-
44
- require 'rake/rdoctask'
45
- Rake::RDocTask.new do |rdoc|
46
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
-
48
- rdoc.rdoc_dir = 'rdoc'
49
- rdoc.title = "rubyoverflow #{version}"
50
- rdoc.rdoc_files.include('README*')
51
- rdoc.rdoc_files.include('lib/**/*.rb')
52
- end
10
+ task :default => :spec
@@ -1,119 +1,67 @@
1
1
  path = File.expand_path(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
3
3
 
4
- require 'httparty'
5
- require 'zlib'
4
+ require 'faraday'
6
5
  require 'ostruct'
7
- require 'hashie'
6
+ require 'zlib'
8
7
 
8
+ require 'hashie'
9
+ require 'json'
9
10
  require 'rubyoverflow/base'
10
- require 'rubyoverflow/pagedBase'
11
- require 'rubyoverflow/pagedDash'
12
-
13
- require 'rubyoverflow/apiVersion'
14
- require 'rubyoverflow/badge'
15
- require 'rubyoverflow/badges'
16
- require 'rubyoverflow/comments'
17
- require 'rubyoverflow/comment'
18
- require 'rubyoverflow/badgeCounts'
19
- require 'rubyoverflow/statistics'
20
- require 'rubyoverflow/tag'
21
- require 'rubyoverflow/tags'
22
- require 'rubyoverflow/user'
11
+ require 'rubyoverflow/sites'
12
+ require 'rubyoverflow/stats'
23
13
  require 'rubyoverflow/users'
24
-
25
- require 'rubyoverflow/answer'
26
14
  require 'rubyoverflow/answers'
27
-
28
- require 'rubyoverflow/question'
29
15
  require 'rubyoverflow/questions'
30
-
31
- require 'rubyoverflow/repChange'
32
- require 'rubyoverflow/repChanges'
33
-
34
- require 'rubyoverflow/userTimelineEvent'
35
- require 'rubyoverflow/userTimelineEvents'
36
-
37
- require 'rubyoverflow/postTimelineEvent'
38
- require 'rubyoverflow/postTimelineEvents'
39
-
40
- require 'rubyoverflow/revision'
41
- require 'rubyoverflow/revisions'
42
-
43
- require 'rubyoverflow/errors'
44
-
45
- require 'rubyoverflow/styling'
46
-
47
- require 'rubyoverflow/apiSite'
48
- require 'rubyoverflow/apiSites'
16
+ require "rubyoverflow/version"
49
17
 
50
18
  module Rubyoverflow
51
19
  class Client
52
- include HTTParty
53
- format :json
54
- #Most of this class is borrowed from the Pilha (http://github.com/dlt/pilha) project because a) it works, b) a lot of this code would be the same regardless of implementation
55
- # (especially the open => gzip code, query string, and normalize), and c) I'm new to ruby, so I'm going to skip pass some of the more 'boring' stuff and get to the
56
- # interesting parts. I plan to re-examine this at a later point
57
20
  HOST = 'http://api.stackoverflow.com'
58
21
  VERSION = '1.1'
59
22
 
60
- attr_reader :host
61
- attr_reader :api_key
62
-
63
- def initialize(options = OpenStruct.new)
64
- if options.kind_of? OpenStruct
65
- @host = options.host || HOST
66
- @version = options.version || VERSION
67
- @api_key = options.api_key if options.api_key
23
+ Rubyoverflow.constants.select {|c| Class === Rubyoverflow.const_get(c) and Rubyoverflow.const_get(c) < Rubyoverflow::Base}.each do |class_sym|
24
+ send :attr_reader, class_sym.downcase
25
+ send "define_method", class_sym.downcase do
26
+ instance_variable_set("@#{class_sym.downcase}", Rubyoverflow.const_get(class_sym).new(self)) unless instance_variable_get("@#{class_sym.downcase}")
27
+ instance_variable_get "@#{class_sym.downcase}"
68
28
  end
69
-
70
-
71
29
  end
72
-
73
-
74
-
75
- def request(path, parameters)
76
- parameters['key'] = @api_key if @api_key
77
- url = host_path + normalize(path) + query_string(parameters)
78
- response = self.class.get url
79
- return response.parsed_response, url
80
- end
81
-
82
- def host_path
83
- normalize(@host) + normalize(@version)
30
+
31
+ attr_accessor :host
32
+ attr_accessor :api_key
33
+
34
+ def initialize(options = {})
35
+ @host = options[:host] || HOST
36
+ @version = options[:version] || VERSION
37
+ @api_key = options[:api_key] if options[:api_key]
84
38
  end
85
-
86
- class << self
87
- # this specifically works well, and I don't fully understand it, so I borrowed this from Pilha more than anything else
88
- # If you want to explain why I only have to configure this once than forget about it, please do, because this stuff is currently over my head
89
- def config &block
90
- options = OpenStruct.new
91
- yield options if block_given?
92
- init_client! Client.new(options)
93
- end
94
-
95
- def change_end_point(val = nil)
96
- options = OpenStruct.new
97
- if val.kind_of? ApiSite
98
- options.host = val.api_endpoint
99
- end
100
39
 
101
- if val.kind_of? String
102
- options.host = val
103
- end
104
- options.api_key = Base.client.api_key
105
-
106
- init_client! Client.new(options)
40
+ def request(path, parameters = {})
41
+ conn = Faraday.new(:url => host_path) do |builder|
42
+ builder.request :url_encoded
43
+ builder.request :json
44
+ builder.adapter :net_http
107
45
  end
108
-
109
- def init_client!(client)
110
- base_eigenclass = class << Base; self; end
111
- base_eigenclass.send :define_method, :client do
112
- @client = client
113
- end
114
- client
46
+ parameters[:key] = @api_key unless @api_key.nil? || @api_key.empty?
47
+ parameters['Accept-Encoding'] = 'gzip'
48
+ response = conn.get do |req|
49
+ req.url normalize(path), parameters
115
50
  end
116
-
51
+ rep_string = response.body
52
+ begin
53
+ gz = Zlib::GzipReader.new(StringIO.new(response.body.to_s))
54
+ rep_string = gz.read
55
+ rescue Zlib::GzipFile::Error
56
+ end
57
+ return JSON.parse(rep_string), response.env[:url]
58
+ end
59
+
60
+ def host_path
61
+ "#{normalize(@host)}#{normalize(@version)}"
62
+ end
63
+
64
+ class << self
117
65
  def stackauth_client(api_key = '')
118
66
  options = OpenStruct.new
119
67
  options.host = 'http://stackauth.com/'
@@ -123,19 +71,9 @@ module Rubyoverflow
123
71
  end
124
72
 
125
73
  private
74
+
126
75
  def normalize(path)
127
- path.end_with?('/') ? path : path+ '/'
76
+ path.end_with?('/') ? path : path + '/'
128
77
  end
129
-
130
- def query_string(parameters)
131
- if !parameters.empty?
132
- params = parameters.sort_by { |k, v| k.to_s }
133
- pairs = params.map { |key, value| "#{key}=#{value}" }
134
-
135
- '?' + pairs.join('&') + "&jsonp"
136
- else
137
- ''
138
- end
139
- end
140
78
  end
141
- end
79
+ end