rubyoverflow 0.5 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/README.rdoc +22 -11
  2. data/RELEASENOTES +97 -1
  3. data/Rakefile +49 -7
  4. data/VERSION +1 -1
  5. data/lib/rubyoverflow.rb +92 -18
  6. data/lib/rubyoverflow/answer.rb +61 -0
  7. data/lib/rubyoverflow/answers.rb +60 -0
  8. data/lib/rubyoverflow/apiSite.rb +32 -0
  9. data/lib/rubyoverflow/apiSites.rb +25 -0
  10. data/lib/rubyoverflow/apiVersion.rb +6 -0
  11. data/lib/rubyoverflow/badge.rb +44 -0
  12. data/lib/rubyoverflow/badgeCounts.rb +22 -0
  13. data/lib/rubyoverflow/badges.rb +59 -0
  14. data/lib/rubyoverflow/base.rb +76 -0
  15. data/lib/rubyoverflow/comment.rb +41 -0
  16. data/lib/rubyoverflow/comments.rb +115 -0
  17. data/lib/rubyoverflow/errors.rb +17 -0
  18. data/lib/rubyoverflow/pagedBase.rb +27 -0
  19. data/lib/rubyoverflow/pagedDash.rb +7 -0
  20. data/lib/rubyoverflow/postTimelineEvent.rb +93 -0
  21. data/lib/rubyoverflow/postTimelineEvents.rb +39 -0
  22. data/lib/rubyoverflow/question.rb +110 -0
  23. data/lib/rubyoverflow/questions.rb +104 -0
  24. data/lib/rubyoverflow/repChange.rb +34 -0
  25. data/lib/rubyoverflow/repChanges.rb +41 -0
  26. data/lib/rubyoverflow/revision.rb +62 -0
  27. data/lib/rubyoverflow/revisions.rb +52 -0
  28. data/lib/rubyoverflow/statistics.rb +57 -0
  29. data/lib/rubyoverflow/styling.rb +19 -0
  30. data/lib/rubyoverflow/tag.rb +27 -0
  31. data/lib/rubyoverflow/tags.rb +46 -0
  32. data/lib/rubyoverflow/user.rb +181 -0
  33. data/lib/rubyoverflow/userTimelineEvent.rb +43 -0
  34. data/lib/rubyoverflow/userTimelineEvents.rb +35 -0
  35. data/lib/rubyoverflow/users.rb +67 -18
  36. data/test/apiKey.rb +5 -0
  37. data/test/helper.rb +159 -0
  38. data/test/test_answer.rb +20 -0
  39. data/test/test_answers.rb +32 -0
  40. data/test/test_badge.rb +18 -0
  41. data/test/test_badges.rb +30 -0
  42. data/test/test_base.rb +63 -0
  43. data/test/test_statistics.rb +26 -0
  44. data/test/test_user.rb +56 -0
  45. data/test/test_users.rb +37 -0
  46. metadata +122 -87
  47. data/.gitignore +0 -4
  48. data/.rvmrc +0 -47
  49. data/.travis.yml +0 -5
  50. data/Gemfile +0 -3
  51. data/lib/rubyoverflow/sites.rb +0 -20
  52. data/lib/rubyoverflow/version.rb +0 -3
  53. data/rubyoverflow.gemspec +0 -26
  54. data/spec/sites_spec.rb +0 -18
  55. data/spec/spec_helper.rb +0 -3
  56. data/spec/users_spec.rb +0 -23
@@ -1,23 +1,34 @@
1
1
  = rubyoverflow
2
2
 
3
- {<img src="https://secure.travis-ci.org/phsr/rubyoverflow.png" />}[http://travis-ci.org/phsr/rubyoverflow]
4
-
5
3
  rubyoverflow is a library for querying the Stack Overflow API
6
4
 
7
- == Example
5
+ == Configuration
8
6
 
9
- require 'rubyoverflow'
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
10
12
 
11
- c = Rubyoverflow::Client.new
12
- result = c.users.fetch(:id => 53587) # By default, this will query StackOverflow.com
13
- me = result.users.first # Get the first user out of the results
14
- puts me.display_name # => "Dan Seaver"
13
+ == Example
15
14
 
15
+ 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
16
28
 
17
- c = Rubyoverflow::Client.new :host => "api.serverfault.com" # Query ServerFault.com
18
29
 
19
30
  == Note on Patches/Pull Requests
20
-
31
+
21
32
  * Fork the project.
22
33
  * Make your feature addition or bug fix.
23
34
  * Add tests for it. This is important so I don't break it in a
@@ -28,5 +39,5 @@ rubyoverflow is a library for querying the Stack Overflow API
28
39
 
29
40
  == Copyright
30
41
 
31
- Copyright (c) 2011 Dan Seaver. See LICENSE for details.
42
+ Copyright (c) 2010 phsr. See LICENSE for details.
32
43
 
@@ -1,2 +1,98 @@
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
+
1
67
  [0.5.0]
2
- Restarting rubyoverflow development, paths /sites and /users (only, no sub-paths) covered
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
data/Rakefile CHANGED
@@ -1,10 +1,52 @@
1
- require 'bundler/gem_tasks'
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
+
2
24
 
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'
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
8
37
  end
9
38
 
10
- task :default => :spec
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
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5
1
+ 1.0.2
@@ -2,44 +2,118 @@ path = File.expand_path(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
3
3
 
4
4
  require 'httparty'
5
+ require 'zlib'
5
6
  require 'ostruct'
6
-
7
7
  require 'hashie'
8
- require 'json'
9
- require 'rubyoverflow/sites'
8
+
9
+ 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'
10
23
  require 'rubyoverflow/users'
11
- require "rubyoverflow/version"
24
+
25
+ require 'rubyoverflow/answer'
26
+ require 'rubyoverflow/answers'
27
+
28
+ require 'rubyoverflow/question'
29
+ 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'
12
49
 
13
50
  module Rubyoverflow
14
51
  class Client
15
52
  include HTTParty
16
- format :plain
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
17
57
  HOST = 'http://api.stackoverflow.com'
18
58
  VERSION = '1.1'
19
59
 
20
- attr_accessor :host
21
- attr_accessor :api_key
22
-
60
+ attr_reader :host
61
+ attr_reader :api_key
62
+
23
63
  def initialize(options = OpenStruct.new)
24
64
  if options.kind_of? OpenStruct
25
65
  @host = options.host || HOST
26
66
  @version = options.version || VERSION
27
67
  @api_key = options.api_key if options.api_key
28
68
  end
69
+
70
+
29
71
  end
30
-
31
- def request(path, parameters = {})
32
- parameters['key'] = @api_key unless @api_key.nil? || @api_key.empty?
72
+
73
+
74
+
75
+ def request(path, parameters)
76
+ parameters['key'] = @api_key if @api_key
33
77
  url = host_path + normalize(path) + query_string(parameters)
34
78
  response = self.class.get url
35
- return JSON.parse(response.body), url
79
+ return response.parsed_response, url
36
80
  end
37
-
81
+
38
82
  def host_path
39
83
  normalize(@host) + normalize(@version)
40
84
  end
41
-
85
+
42
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
+
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)
107
+ 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
115
+ end
116
+
43
117
  def stackauth_client(api_key = '')
44
118
  options = OpenStruct.new
45
119
  options.host = 'http://stackauth.com/'
@@ -52,16 +126,16 @@ module Rubyoverflow
52
126
  def normalize(path)
53
127
  path.end_with?('/') ? path : path+ '/'
54
128
  end
55
-
129
+
56
130
  def query_string(parameters)
57
131
  if !parameters.empty?
58
132
  params = parameters.sort_by { |k, v| k.to_s }
59
133
  pairs = params.map { |key, value| "#{key}=#{value}" }
60
-
61
- '?' + pairs.join('&')
134
+
135
+ '?' + pairs.join('&') + "&jsonp"
62
136
  else
63
137
  ''
64
138
  end
65
139
  end
66
140
  end
67
- end
141
+ end
@@ -0,0 +1,61 @@
1
+ module Rubyoverflow
2
+ class Answer < Base
3
+ attr_reader :answer_id, :accepted, :answer_comments_url, :question_id, :locked_date, :owner,
4
+ :creation_date, :last_edit_date, :last_activity_date, :up_vote_count, :down_vote_count,
5
+ :view_count, :score, :community_owned, :title, :body, :comments
6
+
7
+ def initialize(hash, request_path = '')
8
+ dash = AnswerDash.new hash
9
+
10
+ @answer_id = dash.answer_id
11
+ @accepted = dash.accepted
12
+ @answer_comments_url = dash.answer_comments_url
13
+ @question_id = dash.question_id
14
+ @locked_date = dash.locked_date
15
+ @owner = User.new dash.owner
16
+ @creation_date = dash.creation_date
17
+ @last_edit_date = dash.last_edit_date
18
+ @last_activity_date = dash.last_activity_date
19
+ @up_vote_count = dash.up_vote_count
20
+ @down_vote_count = dash.down_vote_count
21
+ @view_count = dash.view_count
22
+ @score = dash.score
23
+ @community_owned = dash.community_owned
24
+ @title = dash.title
25
+ @body = dash.body
26
+ @comments = Comments.new dash.comments if dash.comments
27
+ end
28
+
29
+ #Gets the comments made on the answer
30
+ def get_comments(parameters = {})
31
+ if @answer_comments_url
32
+ hash,url =request(@answer_comments_url, parameters)
33
+ Comments.new hash, url
34
+ else
35
+ nil
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ class AnswerDash < BaseDash
42
+
43
+ property :answer_id
44
+ property :accepted
45
+ property :answer_comments_url
46
+ property :question_id
47
+ property :locked_date
48
+ property :owner
49
+ property :creation_date
50
+ property :last_edit_date
51
+ property :last_activity_date
52
+ property :up_vote_count
53
+ property :down_vote_count
54
+ property :view_count
55
+ property :score
56
+ property :community_owned
57
+ property :title
58
+ property :body
59
+ property :comments
60
+ end
61
+ end
@@ -0,0 +1,60 @@
1
+ module Rubyoverflow
2
+ class Answers < PagedBase
3
+ attr_reader :answers
4
+
5
+ def initialize(hash, request_path = '')
6
+ dash = AnswersDash.new hash
7
+
8
+ @answers = Array.new
9
+ dash.answers.each {|answerHash| @answers.push(Answer.new answerHash)}
10
+
11
+ super(dash, request_path)
12
+ end
13
+
14
+ #Retrieves the next set of answers using the same parameters used to retrieve the current set
15
+ def get_next_set
16
+ hash,url = perform_next_page_request
17
+ Answers.new hash,url
18
+ end
19
+
20
+ class << self
21
+
22
+ #Retrieves a set of questions by their id(s)
23
+ #
24
+ #id can be an int, string, or an array of ints or strings
25
+ #
26
+ #Maps to '/answers/{id}'
27
+ def retrieve_by_id(id, parameters = {})
28
+ id = convert_to_id_list(id)
29
+ hash,url = request('answers/'+id.to_s, parameters)
30
+ Answers.new hash,url
31
+ end
32
+
33
+ #Retrieves a set of answers made by a set of users by their ids
34
+ #
35
+ #id can be an int, string, or an array of ints or strings
36
+ #
37
+ #Maps to 'users/{id}/answers'
38
+ def retrieve_by_user(id, parameters={})
39
+ id = convert_to_id_list(id)
40
+ hash, url = request('users/'+id.to_s+"/answers", parameters)
41
+ Answers.new hash, url
42
+ end
43
+
44
+ #Retrieves a set of answers from a set of questions by the questions' ids
45
+ #
46
+ #id can be an int, string, or an array of ints or strings
47
+ #
48
+ #Maps to 'questions/{id}/answers'
49
+ def retrieve_by_question(id, parameters={})
50
+ id = convert_to_id_list(id)
51
+ hash, url = request('questions/'+id.to_s+"/answers", parameters)
52
+ Answers.new hash, url
53
+ end
54
+ end
55
+ end
56
+
57
+ class AnswersDash < PagedDash
58
+ property :answers
59
+ end
60
+ end