stacked 0.5.0 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +3 -1
  3. data/Gemfile.lock +43 -0
  4. data/LICENSE +1 -1
  5. data/README.markdown +58 -25
  6. data/Rakefile +6 -45
  7. data/genddoc.sh +4 -1
  8. data/lib/stacked.rb +11 -9
  9. data/lib/stacked/answer.rb +10 -27
  10. data/lib/stacked/badge.rb +15 -11
  11. data/lib/stacked/base.rb +59 -92
  12. data/lib/stacked/client.rb +31 -0
  13. data/lib/stacked/comment.rb +13 -18
  14. data/lib/stacked/parser.rb +47 -0
  15. data/lib/stacked/post_timeline.rb +17 -0
  16. data/lib/stacked/question.rb +52 -51
  17. data/lib/stacked/{reputation.rb → rep_change.rb} +5 -3
  18. data/lib/stacked/tag.rb +10 -2
  19. data/lib/stacked/user.rb +29 -161
  20. data/lib/stacked/{usertimeline.rb → user_timeline.rb} +5 -5
  21. data/lib/stacked/version.rb +4 -0
  22. data/spec/fakes/answers/1237127 +0 -0
  23. data/spec/fakes/answers/2272830 +0 -0
  24. data/spec/fakes/answers/2558700 +0 -0
  25. data/spec/fakes/badges/index +0 -0
  26. data/spec/fakes/badges/name +0 -0
  27. data/spec/fakes/badges/tags +0 -0
  28. data/spec/fakes/comments/1063043 +0 -0
  29. data/spec/fakes/comments/2561833 +0 -0
  30. data/spec/fakes/questions/1236996 +0 -0
  31. data/spec/fakes/questions/1236996-answers +0 -0
  32. data/spec/fakes/questions/1236996-comments +0 -0
  33. data/spec/fakes/questions/1236996-timeline +0 -0
  34. data/spec/fakes/questions/4839321/answers +0 -0
  35. data/spec/fakes/questions/index +0 -0
  36. data/spec/fakes/questions/search +0 -0
  37. data/spec/fakes/questions/tagged +0 -0
  38. data/spec/fakes/questions/unanswered +0 -0
  39. data/spec/fakes/questions/withcomments +0 -0
  40. data/spec/fakes/stats/index +0 -0
  41. data/spec/fakes/tags/activity +0 -0
  42. data/spec/fakes/tags/index +0 -0
  43. data/spec/fakes/tags/name +0 -0
  44. data/spec/fakes/tags/popular +0 -0
  45. data/spec/fakes/users/148722 +0 -0
  46. data/spec/fakes/users/148722-comments +0 -0
  47. data/spec/fakes/users/148722-comments-by-creation +0 -0
  48. data/spec/fakes/users/148722-comments-by-votes +0 -0
  49. data/spec/fakes/users/22656 +0 -0
  50. data/spec/fakes/users/22656-answers +0 -0
  51. data/spec/fakes/users/22656-answers-by-activity +0 -0
  52. data/spec/fakes/users/22656-answers-by-creation +0 -0
  53. data/spec/fakes/users/22656-answers-by-views +0 -0
  54. data/spec/fakes/users/22656-answers-by-votes +0 -0
  55. data/spec/fakes/users/22656-badges +0 -0
  56. data/spec/fakes/users/22656-comments-mentioning-by-creation +0 -0
  57. data/spec/fakes/users/22656-comments-mentioning-by-votes +0 -0
  58. data/spec/fakes/users/22656-favorites +0 -0
  59. data/spec/fakes/users/22656-favorites-by-activity +0 -0
  60. data/spec/fakes/users/22656-favorites-by-added +0 -0
  61. data/spec/fakes/users/22656-favorites-by-creation +0 -0
  62. data/spec/fakes/users/22656-favorites-by-views +0 -0
  63. data/spec/fakes/users/22656-mentioned +0 -0
  64. data/spec/fakes/users/22656-questions +0 -0
  65. data/spec/fakes/users/22656-questions-by-activity +0 -0
  66. data/spec/fakes/users/22656-questions-by-creation +0 -0
  67. data/spec/fakes/users/22656-questions-by-views +0 -0
  68. data/spec/fakes/users/22656-questions-by-votes +0 -0
  69. data/spec/fakes/users/22656-reputation +0 -0
  70. data/spec/fakes/users/22656-reputation-ranged +0 -0
  71. data/spec/fakes/users/22656-tags +0 -0
  72. data/spec/fakes/users/22656-timeline +0 -0
  73. data/spec/fakes/users/filter +0 -0
  74. data/spec/fakes/users/index +0 -0
  75. data/spec/fakes/users/index-page2 +0 -0
  76. data/spec/fakes/users/index-pagesize1 +0 -0
  77. data/spec/fakes/users/name +0 -0
  78. data/spec/fakes/users/newest +0 -0
  79. data/spec/fakes/users/oldest +0 -0
  80. data/spec/sorted_by_spec.rb +2 -2
  81. data/spec/spec_helper.rb +10 -8
  82. data/spec/stacked/answer_spec.rb +9 -8
  83. data/spec/stacked/badge_spec.rb +11 -3
  84. data/spec/stacked/base_spec.rb +24 -2
  85. data/spec/stacked/comment_spec.rb +11 -9
  86. data/spec/stacked/question_spec.rb +49 -61
  87. data/spec/stacked/{reputation_spec.rb → rep_change_spec.rb} +9 -5
  88. data/spec/stacked/tag_spec.rb +13 -6
  89. data/spec/stacked/user_spec.rb +99 -70
  90. data/spec/stacked/{usertimeline_spec.rb → user_timeline_spec.rb} +1 -1
  91. data/spec/support/fakes.rb +28 -0
  92. data/spec/support/{sorted_by.rb → matchers/sorted_by.rb} +7 -6
  93. data/spec/support/{within.rb → matchers/within.rb} +3 -3
  94. data/spec/within_spec.rb +2 -2
  95. data/stacked.gemspec +23 -112
  96. metadata +248 -54
  97. data/README.rdoc +0 -18
  98. data/VERSION +0 -1
  99. data/doc/Stacked.html +0 -155
  100. data/doc/Stacked/Answer.html +0 -1394
  101. data/doc/Stacked/Badge.html +0 -480
  102. data/doc/Stacked/Base.html +0 -1124
  103. data/doc/Stacked/Comment.html +0 -1037
  104. data/doc/Stacked/NotImplemented.html +0 -162
  105. data/doc/Stacked/Posttimeline.html +0 -543
  106. data/doc/Stacked/Question.html +0 -1763
  107. data/doc/Stacked/Reputation.html +0 -606
  108. data/doc/Stacked/Tag.html +0 -267
  109. data/doc/Stacked/User.html +0 -2787
  110. data/doc/Stacked/Usertimeline.html +0 -630
  111. data/doc/_index.html +0 -246
  112. data/doc/file.README.html +0 -54
  113. data/doc/index.html +0 -54
  114. data/doc/method_list.html +0 -1203
  115. data/doc/top-level-namespace.html +0 -87
  116. data/lib/stacked/posttimeline.rb +0 -10
data/.gitignore CHANGED
@@ -1,6 +1,9 @@
1
+ .bundle
1
2
  .yardoc
2
3
  *.sw?
3
4
  .DS_Store
4
5
  coverage
5
6
  rdoc
6
7
  pkg
8
+ notes.md
9
+ stacked-*.gem
data/Gemfile CHANGED
@@ -1 +1,3 @@
1
- gem 'httparty', '0.4.5'
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ stacked (1.0.0)
5
+ activesupport (~> 3.0.3)
6
+ httparty (~> 0.7.3)
7
+ i18n (~> 0.5.0)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activesupport (3.0.3)
13
+ addressable (2.2.3)
14
+ crack (0.1.8)
15
+ diff-lcs (1.1.2)
16
+ httparty (0.7.3)
17
+ crack (= 0.1.8)
18
+ i18n (0.5.0)
19
+ rake (0.8.7)
20
+ rspec (2.4.0)
21
+ rspec-core (~> 2.4.0)
22
+ rspec-expectations (~> 2.4.0)
23
+ rspec-mocks (~> 2.4.0)
24
+ rspec-core (2.4.0)
25
+ rspec-expectations (2.4.0)
26
+ diff-lcs (~> 1.1.2)
27
+ rspec-mocks (2.4.0)
28
+ webmock (1.6.2)
29
+ addressable (>= 2.2.2)
30
+ crack (>= 0.1.7)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ activesupport (~> 3.0.3)
37
+ bundler (~> 1.0)
38
+ httparty (~> 0.7.3)
39
+ i18n (~> 0.5.0)
40
+ rake (~> 0.8)
41
+ rspec (~> 2.4)
42
+ stacked!
43
+ webmock (~> 1.6.2)
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Ryan Bigg
1
+ Copyright (c) 2009-2011 Ryan Bigg, Adam McDonald
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
@@ -1,37 +1,70 @@
1
- # Stacked - A Ruby wrapper for the Stack Overflow API (v0.5)
1
+ # Stacked - A Ruby wrapper for the Stack Exchange API (v1.0)
2
2
 
3
- This library is built around the Stack Overflow (private) API [described here][http://blog.stackoverflow.com/2010/03/stack-overflow-api-private-beta-starts/]. I am under the impression that it covers all the API methods described in [this comprehensive listing][http://dev.meta.stackoverflow.com/questions/34594/overall-api-method-list], but equally aware that this is a first draft and I am likely to make a mistake or four.
3
+ # Note: This code is being actively developed and will be merged with master when ready.
4
+
5
+ While a lot of the core code has remained unchanged, this fork has went through many updates to get it working with the latest version (1.0) of the Stack Exchange API. Many thanks to radar for this initial work on this project.
4
6
 
5
7
  ## Installation
6
8
 
7
- To install stacked:
9
+ # Currently installs outdated version of the gem
10
+ # sudo gem install stacked
8
11
 
9
- sudo gem install stacked
12
+ ## Usage
10
13
 
11
- To use it:
14
+ Stacked is configurable to work with any of the Stack Exchange sites. When setting up the client, just specify the site you wish to access, the API version number, and your api key. By default, Stacked will access Stack Overflow API version 1.0. Note: You must still supply your own api key in the config.
12
15
 
13
- require 'stacked'
14
- Stacked::Question.all
16
+ # Access Stack Overflow API v1.0
17
+ Stacked::Client.configure do |config|
18
+ config.api_key = 'yourapikey'
19
+ end
15
20
 
16
- To report breakages: http://github.com/radar/stacked/issues.
17
-
18
- ## Some notes
19
-
20
- Methods that are designed to take options in the API are designed that way in the wrapper also, as you'd expect. Take for example +Stacked::Question.all+ which you can pass any options you wish:
21
+ # Access Server Fault API v1.0
22
+ Stacked::Client.configure do |config|
23
+ config.site = 'serverfault.com',
24
+ config.version = '1.0',
25
+ config.api_key = 'yourapikey'
26
+ end
21
27
 
22
- Stacked::Question.all(:pagesize => 10)
28
+ Methods that are designed to take options in the API are designed that way in the wrapper also, as you'd expect. For more details, read the Stack Overflow API [documentation](http://api.stackoverflow.com/1.0/help).
23
29
 
24
- In this example the amount of questions returned is limited to 10.
25
-
26
- Other options include:
27
-
28
- * page - Specify the page when paginating through a collection.
29
- * body - Set this to true to return the body of the objects you're receiving. By default set to false for questions and answers.
30
- * comments - Set this to true to include the comments in the objects you're receiving.
31
- * fromdate - An integer timestamp of the time you wish to search from (default: 30 days ago, 90 days for reputation).
32
- * todate - An integer timestamp of the time you wish to search to (default: now)
33
- * tagged - A list of tags to scope this find by. Effective only on question methods.
30
+ require 'stacked'
31
+
32
+ # - - Questions / Answers / Comments
33
+
34
+ # Setup the client
35
+ Stacked::Client.configure do |config|
36
+ config.api_key = 'yourapikey' # required
37
+ end
38
+
39
+ # Returns 30 (default page size) questions based on activity (default sort option)
40
+ Stacked::Question.all
41
+
42
+ # Returns questions tagged with 'ruby', including the question body and comments
43
+ Stacked::Question.all(:tagged => 'ruby', :body => true, :comments => true)
44
+
45
+ # Returns a individual question by id
46
+ question = Stacked::Question.find(151338)
47
+
48
+ # Returns paged answers for the question
49
+ answers = question.answers
50
+
51
+ # Returns paged comments for the question
52
+ comments = question.comments
53
+
54
+ # You can also specify multiple ids as an array for all find requests
55
+ questions = Stacked::Question.find([151338, 4579074])
56
+
57
+ # Returns paged questions based on search criteria
58
+ Stacked::Question.search(:intitle => 'github', :tagged => 'ruby')
59
+
60
+ # - - Users
34
61
 
35
- There may be some options I have missed from this list. This is why it's a first draft. So you can tell me I'm missing options, then I can add them and make it a second draft. And so on.
62
+ # Returns the specified user
63
+ skeet = Stacked::User.find(22656)
64
+
65
+ # Returns all badges awarded to the user
66
+ skeet.badges
67
+
68
+ ## Documentation
36
69
 
37
-
70
+ For additional details, checkout the latest generated [documentation](http://raid5.github.com/stacked).
data/Rakefile CHANGED
@@ -1,51 +1,12 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
3
5
 
4
6
  begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "stacked"
8
- gem.summary = %Q{Ruby wrapper for the Stack Overflow API}
9
- gem.description = %Q{Ruby wrapper for the Stack Overflow API}
10
- gem.email = "ryan@getup.org.au"
11
- gem.homepage = "http://github.com/radar/stacked"
12
- gem.authors = ["Ryan Bigg"]
13
- gem.add_development_dependency "rspec"
14
- gem.add_dependency('httparty', '~> 0.4.5')
15
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
- end
7
+ require 'rspec/core/rake_task'
8
+ [:spec, :rcov].each { |task| RSpec::Core::RakeTask.new(task) }
9
+ task :default => :spec
17
10
  rescue LoadError
18
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
- end
20
-
21
- Jeweler::GemcutterTasks.new
22
-
23
- require 'spec/rake/spectask'
24
- Spec::Rake::SpecTask.new(:spec) do |spec|
25
- spec.libs << 'lib' << 'spec'
26
- spec.spec_files = FileList['spec/**/*_spec.rb']
27
- end
28
-
29
- Spec::Rake::SpecTask.new(:rcov) do |spec|
30
- spec.libs << 'lib' << 'spec'
31
- spec.pattern = 'spec/**/*_spec.rb'
32
- spec.rcov = true
33
- end
34
-
35
- task :spec => :check_dependencies
36
-
37
- task :default => :spec
38
-
39
- require 'rake/rdoctask'
40
- Rake::RDocTask.new do |rdoc|
41
- if File.exist?('VERSION')
42
- version = File.read('VERSION')
43
- else
44
- version = ""
45
- end
46
-
47
- rdoc.rdoc_dir = 'rdoc'
48
- rdoc.title = "stacked #{version}"
49
- rdoc.rdoc_files.include('README*')
50
- rdoc.rdoc_files.include('lib/**/*.rb')
11
+ raise 'RSpec could not be loaded. Run `bundle install` to get all development dependencies.'
51
12
  end
data/genddoc.sh CHANGED
@@ -4,8 +4,11 @@ rm -rf ../stacked-doc &&
4
4
  mkdir -p ../stacked-doc &&
5
5
  mv doc/* ../stacked-doc &&
6
6
  git checkout gh-pages &&
7
- rm -rf * &&
7
+ cd .. &&
8
+ rm -rf stacked/* &&
9
+ cd stacked/ &&
8
10
  mv ../stacked-doc/* . &&
11
+ rm -rf ../stacked-doc &&
9
12
  git add . &&
10
13
  git commit -m "Updated documentation." &&
11
14
  git push origin gh-pages &&
@@ -5,8 +5,9 @@ rescue LoadError
5
5
  Bundler.setup!
6
6
  end
7
7
 
8
- require 'active_support'
8
+ require 'active_support/all'
9
9
 
10
+ # The Stacked module.
10
11
  module Stacked
11
12
  # TODO: Use this coupled with autoload_under when AS 3.0 becomes "stable":
12
13
  # extend ActiveSupport::Autoload
@@ -20,23 +21,24 @@ module Stacked
20
21
  # Instead of:
21
22
  #
22
23
  # autoload :Base, 'stacked/base'
23
- class << self
24
- def autoload(klass)
25
- super(klass, "stacked/#{klass.to_s.underscore}")
26
- end
27
- end
24
+ extend ActiveSupport::Autoload
25
+
26
+ autoload :Client
28
27
  autoload :Answer
29
28
  autoload :Base
30
29
  autoload :Badge
31
30
  autoload :Comment
32
- autoload :Posttimeline
31
+ autoload :PostTimeline
32
+ autoload :Parser
33
33
  autoload :Question
34
- autoload :Reputation
34
+ autoload :RepChange
35
35
  autoload :Tag
36
36
  autoload :User
37
- autoload :Usertimeline
37
+ autoload :UserTimeline
38
38
 
39
+ # NotImplemented::StandardError class.
39
40
  class NotImplemented < StandardError
41
+ # Default message for trying to call all/find on unsupported resources.
40
42
  def message
41
43
  "The requested action is not available in the API."
42
44
  end
@@ -1,43 +1,26 @@
1
1
  module Stacked
2
+ # Stacked::Answer class.
2
3
  class Answer < Base
3
- attr_accessor :accepted,
4
- :answer_id,
5
- :body,
6
- :comments,
7
- :community_owned,
8
- :creation_date,
9
- :down_vote_count,
10
- :last_edit_date,
11
- :owner_display_name,
12
- :owner_user_id,
13
- :question_id,
14
- :score,
15
- :title,
16
- :up_vote_count,
17
- :view_count
18
-
4
+
19
5
  class << self
20
6
  def all(*args)
21
7
  raise Stacked::NotImplemented
22
8
  end
23
9
  end
24
10
 
25
- # A Stacked::User object representing the owner of the answer.
26
- def owner
27
- @owner ||= User.find(owner_user_id)
11
+ # Comments for the answer.
12
+ def comments(options={})
13
+ parse_comments(request(singular(answer_id) + "/comments", options))
14
+ end
15
+
16
+ # Helper method for creating Stacked::User object when initializing new Stacked::Answer objects.
17
+ def owner=(attributes)
18
+ @owner = User.new(attributes)
28
19
  end
29
20
 
30
21
  # A Stacked::Question object representing the question the answer is in response to.
31
22
  def question
32
23
  @question ||= Question.find(question_id)
33
24
  end
34
-
35
- alias_method :created_at, :creation_date
36
- alias_method :updated_at, :last_edit_date
37
- alias_method :id, :answer_id
38
- alias_method :up_votes, :up_vote_count
39
- alias_method :views, :view_count
40
- alias_method :user, :owner
41
25
  end
42
-
43
26
  end
@@ -1,17 +1,21 @@
1
1
  module Stacked
2
+ # Stacked::Badge class.
2
3
  class Badge < Base
3
- attr_accessor :award_count,
4
- :badge_id,
5
- :class,
6
- :description,
7
- :name
8
-
9
- collection :tags
10
-
11
- alias_method :id, :badge_id
12
-
13
4
  class << self
14
- alias_method :name, :all
5
+ # All users who have been awarded the specific badge.
6
+ def find(id, options = {})
7
+ parse_users(request(singular(id), options))
8
+ end
9
+
10
+ # All standard, non-tag-based badges.
11
+ def name(options={})
12
+ records(path + "/name", options)
13
+ end
14
+
15
+ # All tag-based badges
16
+ def tags(options={})
17
+ records(path + "/tags", options)
18
+ end
15
19
  end
16
20
 
17
21
  end
@@ -1,9 +1,11 @@
1
1
  require 'httparty'
2
- require 'pathname'
2
+ require 'zlib'
3
3
 
4
4
  module Stacked
5
+ # Stacked::Base class.
5
6
  class Base
6
7
  include HTTParty
8
+ extend Stacked::Parser
7
9
 
8
10
  delegate :request, :singular, :parse, :to => "self.class"
9
11
 
@@ -11,17 +13,32 @@ module Stacked
11
13
 
12
14
  # Return the stats provided by the API.
13
15
  def stats
14
- request(base + "stats")["stats"]
16
+ request(base + "stats")["statistics"].first
15
17
  end
16
18
 
17
- # All the first group (depends on pagesize) of records for current class.
19
+ # All the of records for current class (depends on pagesize).
18
20
  def all(options = {})
19
21
  records(path, options)
20
22
  end
21
23
 
22
- # A single record belonging to the current class.
23
- def find(id, options={})
24
- self.new(request(singular(id), options)[resource.singularize])
24
+ # A single (or multiple depending on number of ids) record belonging to the current class.
25
+ def find(*args)
26
+ # Determine ids (single or multiple)
27
+ ids = []
28
+ if args.first.instance_of? Fixnum
29
+ ids << args.first
30
+ elsif args.first.instance_of? Array
31
+ ids.concat(args.first)
32
+ end
33
+
34
+ # Options hash supplied? Merge in options
35
+ options = {}
36
+ if args.last.instance_of? Hash
37
+ options.merge!(args.last)
38
+ end
39
+
40
+ recs = records(path_with_ids(ids), options)
41
+ recs.size == 1 ? recs.first : recs
25
42
  end
26
43
 
27
44
  # All records for a given request path.
@@ -29,50 +46,37 @@ module Stacked
29
46
  parse(request(p, options)[resource])
30
47
  end
31
48
 
32
- # Raw Hash of request.
49
+ # Makes request to StackExchange server and decodes it from gzip.
33
50
  def request(p = path, options = {})
34
- get(p, :query => { :key => key }.merge!(options))
35
- end
36
-
37
- # Define collection methods, such as newest.
38
- def collection(*names)
39
- # Forgive me Matz for I have sinned.
40
- for name in names
41
- eval <<-EVAL
42
- def self.#{name}(options = {})
43
- records(path + "#{name}", options)
44
- end
45
- EVAL
46
- end
47
- end
48
-
49
- # Defines association methods for things such as comments on questions.
50
- def association(assoc)
51
- instance_eval do
52
- assoc = assoc.to_s
53
- define_method("#{assoc}=") do |records|
54
- instance_variable_set("@#{assoc}", records.map { |record| "Stacked::#{assoc.classify}".constantize.new(record) })
55
- end
56
-
57
- define_method(assoc) { instance_variable_get("@#{assoc}") }
58
- end
51
+ result = StringIO.new(get(p, :query => { :key => key }.merge!(options)).body)
52
+ JSON.parse(Zlib::GzipReader.new(result).read)
59
53
  end
60
54
 
61
55
  # The path to the singular resource.
62
56
  def singular(id)
63
- path + id.to_s
57
+ path + '/' + id.to_s
58
+ end
59
+
60
+ # The path to either a singular or multiple resources.
61
+ def path_with_ids(ids)
62
+ path + '/' + ids.join(';')
63
+ end
64
+
65
+ # Convert a user result into a collection of Stacked::User objects.
66
+ def parse_users(result)
67
+ parse(result['users'], "Stacked::User".constantize)
64
68
  end
65
69
 
66
70
  private
67
71
 
68
- # The root URL of the API,
72
+ # The root URL of the API.
69
73
  def base
70
- Pathname.new("http://api.stackoverflow.com/0.5/")
74
+ Stacked::Client.base_url
71
75
  end
72
76
 
73
- # The key to let us in.
77
+ # The api key to let us in.
74
78
  def key
75
- "knockknock"
79
+ Stacked::Client.api_key
76
80
  end
77
81
 
78
82
  # Convert the records into actual objects.
@@ -82,9 +86,7 @@ module Stacked
82
86
 
83
87
  # The path to this particular part of the API.
84
88
  # Example if the class is Stacked::Question:
85
- #
86
- # http://api.stackoverflow.com/0.5/questions
87
-
89
+ # http://api.stackoverflow.com/1.0/questions
88
90
  def path
89
91
  base + resource
90
92
  end
@@ -94,66 +96,31 @@ module Stacked
94
96
  self.to_s.demodulize.downcase.pluralize
95
97
  end
96
98
  end
97
-
98
- # Convert an answers result into a collection of Stacked::Answer objects.
99
- def parse_answers(result)
100
- parse_type(result, "answer")
101
- end
102
-
103
- # Convert a badges result into a collection of Stacked::Badge objects.
104
- def parse_badges(result)
105
- parse_type(result, "badge")
106
- end
107
-
108
- # Convert a comments result into a collection of Stacked::Comment objects.
109
- def parse_comments(result)
110
- parse_type(result, "comment")
111
- end
112
-
113
- # Convert a post timeline result into a collection of Stacked::Posttimeline objects.
114
- def parse_post_timeline(result)
115
- parse_type(result, "posttimeline")
116
- end
117
-
118
- # Convert a questions result into a collection of Stacked::Question objects.
119
- def parse_questions(result)
120
- parse_type(result, "question")
121
- end
122
-
123
- # Convert a reputation result into a collection of Stacked::Reputation objects.
124
- def parse_reputations(result)
125
- parse_type(result, "reputation")
126
- end
127
-
128
- # Convert a tags result into a collection of Stacked::Tag objects.
129
- def parse_tags(result)
130
- parse_type(result, "tag")
131
- end
132
-
133
- # Convert a user timeline result into a collection of Stacked::Usertimeline objects.
134
- def parse_user_timeline(result)
135
- parse_type(result, "usertimeline")
136
- end
137
99
 
138
- # Converts the specified result into objects of the +type+ class.
139
- def parse_type(result, type)
140
- parse(result[type.pluralize], "Stacked::#{type.classify}".constantize)
100
+ # Builds attr_accessor for each attribute found in the reponse.
101
+ def define_attributes(hash={})
102
+ hash.each_pair do |key, value|
103
+ self.class.send(:attr_writer, key) unless respond_to?("#{key}=".to_sym)
104
+ self.class.send(:attr_reader, key) unless respond_to?("#{key}".to_sym)
105
+ send "#{key}=".to_sym, value
106
+ end
141
107
  end
142
108
 
143
109
  public
144
110
 
145
- # Finds a post based on the +post_type+ and +post_id+
146
- def post
147
- "Stacked::#{post_type.classify}".constantize.find(post_id)
148
- end
149
-
150
111
  # Creates a new object of the given class based on the attributes passed in.
151
- def initialize(attributes)
152
- # p self
153
- # p attributes.keys.sort.map { |t| t.to_sym }
112
+ def initialize(attributes={})
113
+ define_attributes(attributes)
114
+
154
115
  attributes.each do |k, v|
155
- self.send("#{k}=", v)
116
+ attr_sym = "#{k}=".to_sym
117
+ self.send(attr_sym, v) if self.respond_to?(attr_sym)
156
118
  end
157
119
  end
120
+
121
+ # Finds a post based on the +post_type+ and +post_id+
122
+ def post
123
+ "Stacked::#{post_type.classify}".constantize.find(post_id)
124
+ end
158
125
  end
159
126
  end