koala 1.4.1 → 1.5.0rc1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,9 +1,26 @@
1
+ v1.5
2
+ New methods:
3
+ -- Added Koala::Utils.logger to enable debugging (thanks, KentonWhite!)
4
+ -- Expose fb_error_message and fb_error_code directly in APIError
5
+ Updated methods:
6
+ -- GraphCollection.parse_page_url now uses the URI library and can parse any address (thanks, bnorton!)
7
+ Internal improvements:
8
+ -- Update MultiJson dependency to support the Oj library (thanks, zinenko!)
9
+ -- Loosened Faraday dependency (thanks, rewritten and romanbsd!)
10
+ -- Fixed typos (thanks, nathanbertram!)
11
+ -- Switched uses of put_object to the more semantically accurate put_connections
12
+ -- Cleaned up gemspec
13
+ -- Handle invalid batch API responses better
14
+ Documentation:
15
+ -- Added HTTP Services description for Faraday 0.8/persistent connections (thanks, romanbsd!)
16
+ -- Remove documentation of the old pre-1.2 HTTP Service options
17
+
1
18
  v.1.4.1
2
19
  -- Update MultiJson to 1.3 and change syntax to silence warnings (thanks, eckz and masterkain!)
3
20
 
4
21
  v1.4
5
22
  New methods:
6
- -- OAuth#exchange_access_token(_info) allows you to extend access tokens you receive (thanks, etiennebarrie!)
23
+ -- OAuth#exchange_access_token(_info) allows you to extend access tokens you receive (thanks, etiennebarrie!)
7
24
  Updated methods:
8
25
  -- HTTPServices#encode_params sorts parameters to aid in URL comparison (thanks, sholden!)
9
26
  -- get_connections is now aliased as get_connection (use whichever makes sense to you)
data/koala.gemspec CHANGED
@@ -2,47 +2,26 @@
2
2
  $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
3
3
  require 'koala/version'
4
4
 
5
- Gem::Specification.new do |s|
6
- s.name = %q{koala}
7
- s.version = Koala::VERSION
8
-
9
- s.summary = %q{A lightweight, flexible library for Facebook with support for the Graph API, the REST API, realtime updates, and OAuth authentication.}
10
- s.description = %q{Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph and REST APIs, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services.}
11
- s.homepage = %q{http://github.com/arsduo/koala}
12
-
13
- s.authors = ["Alex Koppel"]
14
- s.email = %q{alex@alexkoppel.com}
15
-
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
-
19
- s.extra_rdoc_files = ["readme.md", "CHANGELOG"]
20
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala"]
21
-
22
- s.require_paths = ["lib"]
23
-
24
- s.rubygems_version = %q{1.4.2}
25
-
26
- s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
27
-
28
- if s.respond_to? :specification_version then
29
- s.specification_version = 3
30
-
31
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
32
- s.add_runtime_dependency(%q<multi_json>, ["~> 1.3.0"])
33
- s.add_runtime_dependency(%q<faraday>, ["~> 0.7.0"])
34
- s.add_development_dependency(%q<rspec>, ["~> 2.8.0rc1"])
35
- s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
36
- else
37
- s.add_dependency(%q<multi_json>, ["~> 1.3.0"])
38
- s.add_dependency(%q<rspec>, ["~> 2.8.0rc1"])
39
- s.add_dependency(%q<rake>, ["~> 0.8.7"])
40
- s.add_dependency(%q<faraday>, ["~> 0.7.0"])
41
- end
42
- else
43
- s.add_dependency(%q<multi_json>, ["~> 1.3.0"])
44
- s.add_dependency(%q<rspec>, ["~> 2.8.0rc1"])
45
- s.add_dependency(%q<rake>, ["~> 0.8.7"])
46
- s.add_dependency(%q<faraday>, ["~> 0.7.0"])
47
- end
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "koala"
7
+ gem.summary = "A lightweight, flexible library for Facebook with support for the Graph API, the REST API, realtime updates, and OAuth authentication."
8
+ gem.description = "Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph and REST APIs, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services."
9
+ gem.homepage = "http://github.com/arsduo/koala"
10
+ gem.version = Koala::VERSION
11
+
12
+ gem.authors = ["Alex Koppel"]
13
+ gem.email = "alex@alexkoppel.com"
14
+
15
+ gem.require_paths = ["lib"]
16
+ gem.files = `git ls-files`.split("\n")
17
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+
20
+ gem.extra_rdoc_files = ["readme.md", "CHANGELOG"]
21
+ gem.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala"]
22
+
23
+ gem.add_runtime_dependency(%q<multi_json>, ["~> 1.3"])
24
+ gem.add_runtime_dependency(%q<faraday>, ["~> 0.7"])
25
+ gem.add_development_dependency(%q<rspec>, ["~> 2.8"])
26
+ gem.add_development_dependency(%q<rake>, ["~> 0.8"])
48
27
  end
@@ -72,8 +72,7 @@ module Koala
72
72
  # Please use put_connections; in a future version of Koala (2.0?),
73
73
  # put_object will issue a POST directly to an individual object, not to a connection.
74
74
  def put_object(parent_object, connection_name, args = {}, options = {})
75
- raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "Write operations require an access token"}) unless @access_token
76
- graph_call("#{parent_object}/#{connection_name}", args, "post", options)
75
+ put_connections(parent_object, connection_name, args, options)
77
76
  end
78
77
 
79
78
  # Delete an object from the Graph if you have appropriate permissions.
@@ -115,7 +114,7 @@ module Koala
115
114
  # @note (see #get_connection)
116
115
  #
117
116
  # @example
118
- # graph.put_object("me", "feed", :message => "Hello, world")
117
+ # graph.put_connections("me", "feed", :message => "Hello, world")
119
118
  # => writes "Hello, world" to the active user's wall
120
119
  #
121
120
  # Most write operations require extended permissions. For example,
@@ -192,7 +191,7 @@ module Koala
192
191
  #
193
192
  # @return (see #put_connections)
194
193
  def put_picture(*picture_args)
195
- put_object(*parse_media_args(picture_args, "photos"))
194
+ put_connections(*parse_media_args(picture_args, "photos"))
196
195
  end
197
196
 
198
197
  # Upload a video. Functions exactly the same as put_picture.
@@ -200,11 +199,11 @@ module Koala
200
199
  def put_video(*video_args)
201
200
  args = parse_media_args(video_args, "videos")
202
201
  args.last[:video] = true
203
- put_object(*args)
202
+ put_connections(*args)
204
203
  end
205
204
 
206
205
  # Write directly to the user's wall.
207
- # Convenience method equivalent to put_object(id, "feed").
206
+ # Convenience method equivalent to put_connections(id, "feed").
208
207
  #
209
208
  # To get wall posts, use get_connections(user, "feed")
210
209
  # To delete a wall post, use delete_object(post_id)
@@ -227,7 +226,7 @@ module Koala
227
226
  # @see #put_connections
228
227
  # @return (see #put_connections)
229
228
  def put_wall_post(message, attachment = {}, target_id = "me", options = {})
230
- self.put_object(target_id, "feed", attachment.merge({:message => message}), options)
229
+ put_connections(target_id, "feed", attachment.merge({:message => message}), options)
231
230
  end
232
231
 
233
232
  # Comment on a given object.
@@ -243,7 +242,7 @@ module Koala
243
242
  # @return (see #put_connections)
244
243
  def put_comment(id, message, options = {})
245
244
  # Writes the given comment on the given post.
246
- self.put_object(id, "comments", {:message => message}, options)
245
+ put_connections(id, "comments", {:message => message}, options)
247
246
  end
248
247
 
249
248
  # Like a given object.
@@ -257,7 +256,7 @@ module Koala
257
256
  # @return (see #put_connections)
258
257
  def put_like(id, options = {})
259
258
  # Likes the given post.
260
- self.put_object(id, "likes", {}, options)
259
+ put_connections(id, "likes", {}, options)
261
260
  end
262
261
 
263
262
  # Unlike a given object.
@@ -447,7 +446,7 @@ module Koala
447
446
 
448
447
  def parse_media_args(media_args, method)
449
448
  # photo and video uploads can accept different types of arguments (see above)
450
- # so here, we parse the arguments into a form directly usable in put_object
449
+ # so here, we parse the arguments into a form directly usable in put_connections
451
450
  raise KoalaError.new("Wrong number of arguments for put_#{method == "photos" ? "picture" : "video"}") unless media_args.size.between?(1, 5)
452
451
 
453
452
  args_offset = media_args[1].kind_of?(Hash) || media_args.size == 1 ? 0 : 1
@@ -41,7 +41,7 @@ module Koala
41
41
  end
42
42
 
43
43
  # redefine the graph_call and check_response methods
44
- # so we can use this API inside the batch block just like any regular Graph API
44
+ # so we can use this API inside the batch block just like any regular Graph API
45
45
  alias_method :graph_call_outside_batch, :graph_call
46
46
  alias_method :graph_call, :graph_call_in_batch
47
47
 
@@ -59,6 +59,12 @@ module Koala
59
59
  })
60
60
 
61
61
  batch_result = graph_call_outside_batch('/', args, 'post', http_options) do |response|
62
+ unless response
63
+ # Facebook sometimes reportedly returns an empty body at times
64
+ # see https://github.com/arsduo/koala/issues/184
65
+ raise APIError.new({"type" => "BadFacebookResponse", "message" => "Facebook returned invalid batch response: #{response.inspect}"})
66
+ end
67
+
62
68
  # map the results with post-processing included
63
69
  index = 0 # keep compat with ruby 1.8 - no with_index for map
64
70
  response.map do |call_result|
@@ -92,7 +98,7 @@ module Koala
92
98
  end
93
99
  end
94
100
  end
95
-
101
+
96
102
  # turn any results that are pageable into GraphCollections
97
103
  batch_result.inject([]) {|processed_results, raw| processed_results << GraphCollection.evaluate(raw, @original_api)}
98
104
  end
@@ -87,10 +87,11 @@ module Koala
87
87
  #
88
88
  # @return an array of parameters that can be provided via graph_call(*parsed_params)
89
89
  def self.parse_page_url(url)
90
- match = url.match(/.com\/(.*)\?(.*)/)
91
- base = match[1]
92
- args = match[2]
93
- params = CGI.parse(args)
90
+ uri = URI.parse(url)
91
+
92
+ base = uri.path.sub(/^\//, '')
93
+ params = CGI.parse(uri.query)
94
+
94
95
  new_params = {}
95
96
  params.each_pair do |key,value|
96
97
  new_params[key] = value.join ","
data/lib/koala/api.rb CHANGED
@@ -12,12 +12,12 @@ module Koala
12
12
  def initialize(access_token = nil)
13
13
  @access_token = access_token
14
14
  end
15
-
15
+
16
16
  attr_reader :access_token
17
17
 
18
18
  include GraphAPIMethods
19
19
  include RestAPIMethods
20
-
20
+
21
21
  # Makes a request to the appropriate Facebook API.
22
22
  # @note You'll rarely need to call this method directly.
23
23
  #
@@ -27,17 +27,17 @@ module Koala
27
27
  # @param path the server path for this request (leading / is prepended if not present)
28
28
  # @param args arguments to be sent to Facebook
29
29
  # @param verb the HTTP method to use
30
- # @param options request-related options for Koala and Faraday.
30
+ # @param options request-related options for Koala and Faraday.
31
31
  # See https://github.com/arsduo/koala/wiki/HTTP-Services for additional options.
32
32
  # @option options [Symbol] :http_component which part of the response (headers, body, or status) to return
33
33
  # @option options [Boolean] :beta use Facebook's beta tier
34
- # @option options [Boolean] :use_ssl force SSL for this request, even if it's tokenless.
34
+ # @option options [Boolean] :use_ssl force SSL for this request, even if it's tokenless.
35
35
  # (All API requests with access tokens use SSL.)
36
- # @param error_checking_block a block to evaluate the response status for additional JSON-encoded errors
36
+ # @param error_checking_block a block to evaluate the response status for additional JSON-encoded errors
37
37
  #
38
38
  # @yield The response body for evaluation
39
39
  #
40
- # @raise [Koala::Facebook::APIError] if Facebook returns an error (response status >= 500)
40
+ # @raise [Koala::Facebook::APIError] if Facebook returns an error (response status >= 500)
41
41
  #
42
42
  # @return the body of the response from Facebook (unless another http_component is requested)
43
43
  def api(path, args = {}, verb = "get", options = {}, &error_checking_block)
@@ -69,11 +69,11 @@ module Koala
69
69
  end
70
70
  end
71
71
  end
72
-
72
+
73
73
  class APIError < StandardError
74
- attr_accessor :fb_error_type, :raw_response
74
+ attr_accessor :fb_error_type, :fb_error_code, :fb_error_message, :raw_response
75
75
 
76
- # Creates a new APIError.
76
+ # Creates a new APIError.
77
77
  #
78
78
  # Assigns the error type (as reported by Facebook) to #fb_error_type
79
79
  # and the raw error response available to #raw_response.
@@ -82,6 +82,8 @@ module Koala
82
82
  def initialize(details = {})
83
83
  self.raw_response = details
84
84
  self.fb_error_type = details["type"]
85
+ self.fb_error_code = details["code"]
86
+ self.fb_error_message = details["message"]
85
87
  super("#{fb_error_type}: #{details["message"]}")
86
88
  end
87
89
  end
@@ -4,7 +4,7 @@ require 'koala/http_service/uploadable_io'
4
4
  require 'koala/http_service/response'
5
5
 
6
6
  module Koala
7
- module HTTPService
7
+ module HTTPService
8
8
  class << self
9
9
  # A customized stack of Faraday middleware that will be used to make each request.
10
10
  attr_accessor :faraday_middleware
@@ -13,9 +13,9 @@ module Koala
13
13
  end
14
14
 
15
15
  @http_options ||= {}
16
-
17
- # Koala's default middleware stack.
18
- # We encode requests in a Facebook-compatible multipart request,
16
+
17
+ # Koala's default middleware stack.
18
+ # We encode requests in a Facebook-compatible multipart request,
19
19
  # and use whichever adapter has been configured for this application.
20
20
  DEFAULT_MIDDLEWARE = Proc.new do |builder|
21
21
  builder.use Koala::HTTPService::MultipartRequest
@@ -30,7 +30,7 @@ module Koala
30
30
  # @option options :video use the server designated for video uploads
31
31
  # @option options :beta use the beta tier
32
32
  # @option options :use_ssl force https, even if not needed
33
- #
33
+ #
34
34
  # @return a complete server address with protocol
35
35
  def self.server(options = {})
36
36
  server = "#{options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER}"
@@ -48,9 +48,9 @@ module Koala
48
48
  #
49
49
  # @param path the server path for this request
50
50
  # @param args (see Koala::Facebook::API#api)
51
- # @param verb the HTTP method to use.
51
+ # @param verb the HTTP method to use.
52
52
  # If not get or post, this will be turned into a POST request with the appropriate :method
53
- # specified in the arguments.
53
+ # specified in the arguments.
54
54
  # @param options (see Koala::Facebook::API#api)
55
55
  #
56
56
  # @raise an appropriate connection error if unable to make the request to Facebook
@@ -63,23 +63,30 @@ module Koala
63
63
  # turn all the keys to strings (Faraday has issues with symbols under 1.8.7) and resolve UploadableIOs
64
64
  params = args.inject({}) {|hash, kv| hash[kv.first.to_s] = kv.last.is_a?(UploadableIO) ? kv.last.to_upload_io : kv.last; hash}
65
65
 
66
- # figure out our options for this request
66
+ # figure out our options for this request
67
67
  request_options = {:params => (verb == "get" ? params : {})}.merge(http_options || {}).merge(process_options(options))
68
68
  request_options[:use_ssl] = true if args["access_token"] # require https if there's a token
69
+ if request_options[:use_ssl]
70
+ ssl = (request_options[:ssl] ||= {})
71
+ ssl[:verify] = true unless ssl.has_key?(:verify)
72
+ end
69
73
 
70
74
  # set up our Faraday connection
71
75
  # we have to manually assign params to the URL or the
72
76
  conn = Faraday.new(server(request_options), request_options, &(faraday_middleware || DEFAULT_MIDDLEWARE))
73
77
 
74
78
  response = conn.send(verb, path, (verb == "post" ? params : {}))
79
+
80
+ # Log URL information
81
+ Koala::Utils.debug "#{verb.upcase}: #{path} params: #{params.inspect}"
75
82
  Koala::HTTPService::Response.new(response.status.to_i, response.body, response.headers)
76
83
  end
77
84
 
78
- # Encodes a given hash into a query string.
85
+ # Encodes a given hash into a query string.
79
86
  # This is used mainly by the Batch API nowadays, since Faraday handles this for regular cases.
80
- #
87
+ #
81
88
  # @param params_hash a hash of values to CGI-encode and appropriately join
82
- #
89
+ #
83
90
  # @example
84
91
  # Koala.http_service.encode_params({:a => 2, :b => "My String"})
85
92
  # => "a=2&b=My+String"
@@ -91,10 +98,10 @@ module Koala
91
98
  "#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
92
99
  end).join("&")
93
100
  end
94
-
101
+
95
102
  # deprecations
96
103
  # not elegant or compact code, but temporary
97
-
104
+
98
105
  # @private
99
106
  def self.always_use_ssl
100
107
  Koala::Utils.deprecate("HTTPService.always_use_ssl is now HTTPService.http_options[:use_ssl]; always_use_ssl will be removed in a future version.")
@@ -106,7 +113,7 @@ module Koala
106
113
  Koala::Utils.deprecate("HTTPService.always_use_ssl is now HTTPService.http_options[:use_ssl]; always_use_ssl will be removed in a future version.")
107
114
  http_options[:use_ssl] = value
108
115
  end
109
-
116
+
110
117
  # @private
111
118
  def self.timeout
112
119
  Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
@@ -118,7 +125,7 @@ module Koala
118
125
  Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
119
126
  http_options[:timeout] = value
120
127
  end
121
-
128
+
122
129
  # @private
123
130
  def self.timeout
124
131
  Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
@@ -130,7 +137,7 @@ module Koala
130
137
  Koala::Utils.deprecate("HTTPService.timeout is now HTTPService.http_options[:timeout]; .timeout will be removed in a future version.")
131
138
  http_options[:timeout] = value
132
139
  end
133
-
140
+
134
141
  # @private
135
142
  def self.proxy
136
143
  Koala::Utils.deprecate("HTTPService.proxy is now HTTPService.http_options[:proxy]; .proxy will be removed in a future version.")
@@ -142,7 +149,7 @@ module Koala
142
149
  Koala::Utils.deprecate("HTTPService.proxy is now HTTPService.http_options[:proxy]; .proxy will be removed in a future version.")
143
150
  http_options[:proxy] = value
144
151
  end
145
-
152
+
146
153
  # @private
147
154
  def self.ca_path
148
155
  Koala::Utils.deprecate("HTTPService.ca_path is now (HTTPService.http_options[:ssl] ||= {})[:ca_path]; .ca_path will be removed in a future version.")
@@ -154,7 +161,7 @@ module Koala
154
161
  Koala::Utils.deprecate("HTTPService.ca_path is now (HTTPService.http_options[:ssl] ||= {})[:ca_path]; .ca_path will be removed in a future version.")
155
162
  (http_options[:ssl] ||= {})[:ca_path] = value
156
163
  end
157
-
164
+
158
165
  # @private
159
166
  def self.ca_file
160
167
  Koala::Utils.deprecate("HTTPService.ca_file is now (HTTPService.http_options[:ssl] ||= {})[:ca_file]; .ca_file will be removed in a future version.")
@@ -179,14 +186,14 @@ module Koala
179
186
  (http_options[:ssl] ||= {})[:verify_mode] = value
180
187
  end
181
188
 
182
- private
183
-
189
+ private
190
+
184
191
  def self.process_options(options)
185
192
  if typhoeus_options = options.delete(:typhoeus_options)
186
193
  Koala::Utils.deprecate("typhoeus_options should now be included directly in the http_options hash. Support for this key will be removed in a future version.")
187
194
  options = options.merge(typhoeus_options)
188
195
  end
189
-
196
+
190
197
  if ca_file = options.delete(:ca_file)
191
198
  Koala::Utils.deprecate("http_options[:ca_file] should now be passed inside (http_options[:ssl] = {}) -- that is, http_options[:ssl][:ca_file]. Support for this key will be removed in a future version.")
192
199
  (options[:ssl] ||= {})[:ca_file] = ca_file
@@ -201,11 +208,11 @@ module Koala
201
208
  Koala::Utils.deprecate("http_options[:verify_mode] should now be passed inside (http_options[:ssl] = {}) -- that is, http_options[:ssl][:verify_mode]. Support for this key will be removed in a future version.")
202
209
  (options[:ssl] ||= {})[:verify_mode] = verify_mode
203
210
  end
204
-
211
+
205
212
  options
206
- end
213
+ end
207
214
  end
208
-
215
+
209
216
  # @private
210
217
  module TyphoeusService
211
218
  def self.deprecated_interface
data/lib/koala/oauth.rb CHANGED
@@ -325,6 +325,7 @@ module Koala
325
325
 
326
326
  components.merge(token_info) if token_info
327
327
  else
328
+ Koala::Utils.logger.warn("Signed cookie didn't contain Facebook OAuth code! Components: #{components}")
328
329
  nil
329
330
  end
330
331
  end
data/lib/koala/utils.rb CHANGED
@@ -1,12 +1,27 @@
1
1
  module Koala
2
2
  module Utils
3
3
 
4
+ # Utility methods used by Koala.
5
+ require 'logger'
6
+ require 'forwardable'
7
+
8
+ extend Forwardable
9
+ extend self
10
+
11
+ def_delegators :logger, :debug, :info, :warn, :error, :fatal, :level, :level=
12
+
13
+ # The Koala logger, an instance of the standard Ruby logger, pointing to STDOUT by default.
14
+ # In Rails projects, you can set this to Rails.logger.
15
+ attr_accessor :logger
16
+ self.logger = Logger.new(STDOUT)
17
+ self.logger.level = Logger::ERROR
18
+
4
19
  # @private
5
20
  DEPRECATION_PREFIX = "KOALA: Deprecation warning: "
6
21
 
7
- # Prints a deprecation message.
22
+ # Prints a deprecation message.
8
23
  # Each individual message will only be printed once to avoid spamming.
9
- def self.deprecate(message)
24
+ def deprecate(message)
10
25
  @posted_deprecations ||= []
11
26
  unless @posted_deprecations.include?(message)
12
27
  # only include each message once
data/lib/koala/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Koala
2
- VERSION = "1.4.1"
2
+ VERSION = "1.5.0rc1"
3
3
  end
data/readme.md CHANGED
@@ -23,17 +23,17 @@ Or in Bundler:
23
23
  Graph API
24
24
  ----
25
25
  The Graph API is the simple, slick new interface to Facebook's data. Using it with Koala is quite straightforward:
26
-
26
+
27
27
  @graph = Koala::Facebook::API.new(oauth_access_token)
28
28
  # in 1.1 or earlier, use GraphAPI instead of API
29
-
29
+
30
30
  profile = @graph.get_object("me")
31
31
  friends = @graph.get_connections("me", "friends")
32
- @graph.put_object("me", "feed", :message => "I am writing on my wall!")
33
-
32
+ @graph.put_connections("me", "feed", :message => "I am writing on my wall!")
33
+
34
34
  # three-part queries are easy too!
35
35
  @graph.get_connections("me", "mutualfriends/#{friend_id}")
36
-
36
+
37
37
  # you can even use the new Timeline API
38
38
  # see https://developers.facebook.com/docs/beta/opengraph/tutorial/
39
39
  @graph.put_connections("me", "namespace:action", :object => object_url)
@@ -70,7 +70,7 @@ Fortunately, Koala supports the REST API using the very same interface; to use t
70
70
 
71
71
  @rest = Koala::Facebook::API.new(oauth_access_token)
72
72
  # in 1.1 or earlier, use RestAPI instead of API
73
-
73
+
74
74
  @rest.fql_query(my_fql_query) # convenience method
75
75
  @rest.fql_multiquery(fql_query_hash) # convenience method
76
76
  @rest.rest_call("stream.publish", arguments_hash) # generic version
@@ -79,11 +79,11 @@ Of course, you can use the Graph API methods on the same object -- the power of
79
79
 
80
80
  @api = Koala::Facebook::API.new(oauth_access_token)
81
81
  # in 1.1 or earlier, use GraphAndRestAPI instead of API
82
-
82
+
83
83
  @api = Koala::Facebook::API.new(oauth_access_token)
84
84
  fql = @api.fql_query(my_fql_query)
85
85
  @api.put_wall_post(process_result(fql))
86
-
86
+
87
87
 
88
88
  OAuth
89
89
  -----
@@ -91,7 +91,7 @@ You can use the Graph and REST APIs without an OAuth access token, but the real
91
91
 
92
92
  @oauth = Koala::Facebook::OAuth.new(app_id, app_secret, callback_url)
93
93
 
94
- If your application uses Koala and the Facebook [JavaScript SDK](http://github.com/facebook/connect-js) (formerly Facebook Connect), you can use the OAuth class to parse the cookies:
94
+ If your application uses Koala and the Facebook [JavaScript SDK](http://github.com/facebook/facebook-js-sdk) (formerly Facebook Connect), you can use the OAuth class to parse the cookies:
95
95
 
96
96
  @oauth.get_user_from_cookies(cookies) # gets the user's ID
97
97
  @oauth.get_user_info_from_cookies(cookies) # parses and returns the entire hash
@@ -166,7 +166,7 @@ Koala uses Faraday to make HTTP requests, which means you have complete control
166
166
  }
167
167
  # or on a per-request basis
168
168
  @api.get_object(id, args_hash, { :timeout => 10 })
169
-
169
+
170
170
  The <a href="https://github.com/arsduo/koala/wiki/HTTP-Services">HTTP Services wiki page</a> has more information on what options are available, as well as on how to configure your own Faraday middleware stack (for instance, to implement request logging).
171
171
 
172
172
  See examples, ask questions
@@ -5,24 +5,27 @@ describe Koala::Facebook::APIError do
5
5
  Koala::Facebook::APIError.new.should be_a(StandardError)
6
6
  end
7
7
 
8
- it "has an accessor for fb_error_type" do
9
- Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(:fb_error_type)
10
- Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(:fb_error_type=)
11
- end
12
-
13
- it "has an accessor for raw_response" do
14
- Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(:raw_response)
15
- Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(:raw_response=)
8
+ [:fb_error_type, :fb_error_code, :fb_error_message, :raw_response].each do |accessor|
9
+ it "has an accessor for #{accessor}" do
10
+ Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(accessor)
11
+ Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(:"#{accessor}=")
12
+ end
16
13
  end
17
14
 
18
15
  it "sets raw_response to the provided error details" do
19
16
  error_response = {"type" => "foo", "other_details" => "bar"}
20
17
  Koala::Facebook::APIError.new(error_response).raw_response.should == error_response
21
18
  end
22
-
23
- it "sets fb_error_type to details['type']" do
24
- type = "foo"
25
- Koala::Facebook::APIError.new("type" => type).fb_error_type.should == type
19
+
20
+ {
21
+ :fb_error_type => 'type',
22
+ :fb_error_message => 'message',
23
+ :fb_error_code => 'code'
24
+ }.each_pair do |accessor, key|
25
+ it "sets #{accessor} to details['#{key}']" do
26
+ value = "foo"
27
+ Koala::Facebook::APIError.new(key => value).send(accessor).should == value
28
+ end
26
29
  end
27
30
 
28
31
  it "sets the error message details['type']: details['message']" do
@@ -381,6 +381,13 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
381
381
  }.to raise_exception(Koala::Facebook::APIError)
382
382
  end
383
383
 
384
+ it "raises an APIError if the body is empty" do
385
+ Koala.stub(:make_request).and_return(Koala::HTTPService::Response.new(200, "", {}))
386
+ expect {
387
+ Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
388
+ }.to raise_exception(Koala::Facebook::APIError)
389
+ end
390
+
384
391
  context "with the old style" do
385
392
  before :each do
386
393
  Koala.stub(:make_request).and_return(Koala::HTTPService::Response.new(200, '{"error":190,"error_description":"Error validating access token."}', {}))
@@ -13,11 +13,11 @@ describe Koala::Facebook::GraphCollection do
13
13
  it "subclasses Array" do
14
14
  Koala::Facebook::GraphCollection.ancestors.should include(Array)
15
15
  end
16
-
16
+
17
17
  it "creates an array-like object" do
18
18
  Koala::Facebook::GraphCollection.new(@result, @api).should be_an(Array)
19
19
  end
20
-
20
+
21
21
  it "contains the result data" do
22
22
  @result["data"].each_with_index {|r, i| @collection[i].should == r}
23
23
  end
@@ -26,19 +26,19 @@ describe Koala::Facebook::GraphCollection do
26
26
  @collection.methods.map(&:to_sym).should include(:paging)
27
27
  @collection.methods.map(&:to_sym).should_not include(:paging=)
28
28
  end
29
-
29
+
30
30
  it "sets paging to results['paging']" do
31
31
  @collection.paging.should == @result["paging"]
32
32
  end
33
-
33
+
34
34
  it "sets raw_response to the original results" do
35
35
  @collection.raw_response.should == @result
36
36
  end
37
-
37
+
38
38
  it "sets the API to the provided API" do
39
39
  @collection.api.should == @api
40
40
  end
41
-
41
+
42
42
  describe "when getting a whole page" do
43
43
  before(:each) do
44
44
  @second_page = {
@@ -87,16 +87,22 @@ describe Koala::Facebook::GraphCollection do
87
87
  @collection.parse_page_url(stub("url")).should == parsed_content
88
88
  end
89
89
  end
90
-
91
- describe ".parse_page_url" do
90
+
91
+ describe ".parse_page_url" do
92
92
  it "should return the base as the first array entry" do
93
93
  base = "url_path"
94
- Koala::Facebook::GraphCollection.parse_page_url("anything.com/#{base}?anything").first.should == base
94
+ Koala::Facebook::GraphCollection.parse_page_url("http://facebook.com/#{base}?anything").first.should == base
95
95
  end
96
96
 
97
97
  it "should return the arguments as a hash as the last array entry" do
98
98
  args_hash = {"one" => "val_one", "two" => "val_two"}
99
- Koala::Facebook::GraphCollection.parse_page_url("anything.com/anything?#{args_hash.map {|k,v| "#{k}=#{v}" }.join("&")}").last.should == args_hash
99
+ Koala::Facebook::GraphCollection.parse_page_url("http://facebook.com/anything?#{args_hash.map {|k,v| "#{k}=#{v}" }.join("&")}").last.should == args_hash
100
+ end
101
+
102
+ it "works with non-.com addresses" do
103
+ base = "url_path"
104
+ args_hash = {"one" => "val_one", "two" => "val_two"}
105
+ Koala::Facebook::GraphCollection.parse_page_url("http://facebook.com/#{base}?#{args_hash.map {|k,v| "#{k}=#{v}" }.join("&")}").should == [base, args_hash]
100
106
  end
101
107
  end
102
108
  end
@@ -106,22 +112,22 @@ describe Koala::Facebook::GraphCollection do
106
112
  result = []
107
113
  Koala::Facebook::GraphCollection.evaluate(result, @api).should == result
108
114
  end
109
-
115
+
110
116
  it "returns the original result if it's provided a nil result" do
111
117
  result = nil
112
118
  Koala::Facebook::GraphCollection.evaluate(result, @api).should == result
113
119
  end
114
-
120
+
115
121
  it "returns the original result if the result doesn't have a data key" do
116
122
  result = {"paging" => {}}
117
123
  Koala::Facebook::GraphCollection.evaluate(result, @api).should == result
118
124
  end
119
-
125
+
120
126
  it "returns the original result if the result's data key isn't an array" do
121
127
  result = {"data" => {}, "paging" => {}}
122
128
  Koala::Facebook::GraphCollection.evaluate(result, @api).should == result
123
129
  end
124
-
130
+
125
131
  it "returns a new GraphCollection of the result if it has an array data key and a paging key" do
126
132
  result = {"data" => [], "paging" => {}}
127
133
  expected = :foo
@@ -10,7 +10,7 @@ describe "Koala::HTTPService" do
10
10
  Koala::HTTPService.should respond_to(:http_options)
11
11
  Koala::HTTPService.should respond_to(:http_options=)
12
12
  end
13
-
13
+
14
14
  it "sets http_options to {} by default" do
15
15
  Koala::HTTPService.http_options.should == {}
16
16
  end
@@ -123,10 +123,10 @@ describe "Koala::HTTPService" do
123
123
  val.should == CGI.escape(args[key])
124
124
  end
125
125
  end
126
-
126
+
127
127
  it "encodes parameters in alphabetical order" do
128
128
  args = {:b => '2', 'a' => '1'}
129
-
129
+
130
130
  result = Koala::HTTPService.encode_params(args)
131
131
  result.split('&').map{|key_val| key_val.split('=')[0]}.should == ['a', 'b']
132
132
  end
@@ -184,33 +184,44 @@ describe "Koala::HTTPService" do
184
184
  Faraday.should_receive(:new).with(anything, hash_including(http_options.merge(options))).and_return(@mock_connection)
185
185
  Koala::HTTPService.make_request("anything", {}, "get", options)
186
186
  end
187
-
187
+
188
188
  it "forces use_ssl to true if an access token is present" do
189
189
  options = {:use_ssl => false}
190
190
  Koala::HTTPService.stub(:http_options).and_return(:use_ssl => false)
191
- Faraday.should_receive(:new).with(anything, hash_including(:use_ssl => true)).and_return(@mock_connection)
191
+ Faraday.should_receive(:new).with(anything, hash_including(:use_ssl => true, :ssl => {:verify => true})).and_return(@mock_connection)
192
192
  Koala::HTTPService.make_request("anything", {"access_token" => "foo"}, "get", options)
193
193
  end
194
-
194
+
195
+ it "defaults verify to true if use_ssl is true" do
196
+ Faraday.should_receive(:new).with(anything, hash_including(:ssl => {:verify => true})).and_return(@mock_connection)
197
+ Koala::HTTPService.make_request("anything", {"access_token" => "foo"}, "get")
198
+ end
199
+
200
+ it "allows you to set other verify modes if you really want" do
201
+ options = {:ssl => {:verify => :foo}}
202
+ Faraday.should_receive(:new).with(anything, hash_including(options)).and_return(@mock_connection)
203
+ Koala::HTTPService.make_request("anything", {"access_token" => "foo"}, "get", options)
204
+ end
205
+
195
206
  it "calls server with the composite options" do
196
207
  options = {:a => 2, :c => "3"}
197
208
  http_options = {:a => :a}
198
209
  Koala::HTTPService.stub(:http_options).and_return(http_options)
199
210
  Koala::HTTPService.should_receive(:server).with(hash_including(http_options.merge(options))).and_return("foo")
200
- Koala::HTTPService.make_request("anything", {}, "get", options)
211
+ Koala::HTTPService.make_request("anything", {}, "get", options)
201
212
  end
202
213
 
203
214
  it "uses the default builder block if HTTPService.faraday_middleware block is not defined" do
204
- Koala::HTTPService.stub(:faraday_middleware).and_return(nil)
215
+ Koala::HTTPService.stub(:faraday_middleware).and_return(nil)
205
216
  Faraday.should_receive(:new).with(anything, anything, &Koala::HTTPService::DEFAULT_MIDDLEWARE).and_return(@mock_connection)
206
- Koala::HTTPService.make_request("anything", {}, "get")
217
+ Koala::HTTPService.make_request("anything", {}, "get")
207
218
  end
208
-
219
+
209
220
  it "uses the defined HTTPService.faraday_middleware block if defined" do
210
221
  block = Proc.new { }
211
222
  Koala::HTTPService.should_receive(:faraday_middleware).and_return(block)
212
223
  Faraday.should_receive(:new).with(anything, anything, &block).and_return(@mock_connection)
213
- Koala::HTTPService.make_request("anything", {}, "get")
224
+ Koala::HTTPService.make_request("anything", {}, "get")
214
225
  end
215
226
  end
216
227
 
@@ -244,6 +255,21 @@ describe "Koala::HTTPService" do
244
255
  @mock_connection.should_receive(:get).with(anything, {}).and_return(@mock_http_response)
245
256
  Koala::HTTPService.make_request("anything", args, "get")
246
257
  end
258
+
259
+ it "logs verb, url and params to debug" do
260
+ args = {"a" => :b, "c" => 3}
261
+ log_message_stem = "GET: anything params: "
262
+ Koala::Utils.logger.should_receive(:debug) do |log_message|
263
+ # unordered hashes are a bane
264
+ # Ruby in 1.8 modes tends to return different hash orderings,
265
+ # which makes checking the content of the stringified hash hard
266
+ # it's enough just to ensure that there's hash content in the string, I think
267
+ log_message.should include(log_message_stem)
268
+ log_message.match(/\{.*\}/).should_not be_nil
269
+ end
270
+
271
+ Koala::HTTPService.make_request("anything", args, "get")
272
+ end
247
273
  end
248
274
 
249
275
  describe "for POSTs" do
@@ -262,6 +288,20 @@ describe "Koala::HTTPService" do
262
288
  @mock_connection.should_receive(:post).with(anything, hash_including("source" => upload_io)).and_return(@mock_http_response)
263
289
  Koala::HTTPService.make_request("anything", {:source => u}, "post")
264
290
  end
291
+
292
+ it "logs verb, url and params to debug" do
293
+ args = {"a" => :b, "c" => 3}
294
+ log_message_stem = "POST: anything params: "
295
+ Koala::Utils.logger.should_receive(:debug) do |log_message|
296
+ # unordered hashes are a bane
297
+ # Ruby in 1.8 modes tends to return different hash orderings,
298
+ # which makes checking the content of the stringified hash hard
299
+ # it's enough just to ensure that there's hash content in the string, I think
300
+ log_message.should include(log_message_stem)
301
+ log_message.match(/\{.*\}/).should_not be_nil
302
+ end
303
+ Koala::HTTPService.make_request("anything", args, "post")
304
+ end
265
305
  end
266
306
  end
267
307
 
@@ -274,11 +314,11 @@ describe "Koala::HTTPService" do
274
314
  after :each do
275
315
  Koala.http_service = @service
276
316
  end
277
-
317
+
278
318
  {
279
319
  :timeout => :timeout,
280
320
  :always_use_ssl => :use_ssl,
281
- :proxy => :proxy
321
+ :proxy => :proxy
282
322
  }.each_pair do |deprecated_method, parameter|
283
323
  describe ".#{deprecated_method}" do
284
324
  context "read" do
@@ -287,13 +327,13 @@ describe "Koala::HTTPService" do
287
327
  Koala::HTTPService.http_options[parameter] = value
288
328
  Koala::HTTPService.send(deprecated_method).should == value
289
329
  end
290
-
330
+
291
331
  it "generates a deprecation warning" do
292
332
  Koala::Utils.should_receive(:deprecate)
293
333
  Koala::HTTPService.send(deprecated_method)
294
334
  end
295
335
  end
296
-
336
+
297
337
  context "write" do
298
338
  it "writes to http_options[:#{parameter}]" do
299
339
  Koala::HTTPService.http_options[parameter] = nil
@@ -301,7 +341,7 @@ describe "Koala::HTTPService" do
301
341
  Koala::HTTPService.send(:"#{deprecated_method}=", value)
302
342
  Koala::HTTPService.http_options[parameter].should == value
303
343
  end
304
-
344
+
305
345
  it "generates a deprecation warning" do
306
346
  Koala::Utils.should_receive(:deprecate)
307
347
  Koala::HTTPService.send(:"#{deprecated_method}=", 2)
@@ -309,7 +349,7 @@ describe "Koala::HTTPService" do
309
349
  end
310
350
  end
311
351
  end
312
-
352
+
313
353
  # ssl options
314
354
  [:ca_path, :ca_file, :verify_mode].each do |deprecated_method|
315
355
  describe ".#{deprecated_method}" do
@@ -319,7 +359,7 @@ describe "Koala::HTTPService" do
319
359
  Koala::HTTPService.http_options[:ssl] = {deprecated_method => value}
320
360
  Koala::HTTPService.send(deprecated_method).should == value
321
361
  end
322
-
362
+
323
363
  it "returns nil if http_options[:ssl] is not defined" do
324
364
  Koala::HTTPService.send(deprecated_method).should be_nil
325
365
  end
@@ -329,8 +369,8 @@ describe "Koala::HTTPService" do
329
369
  Koala::HTTPService.send(deprecated_method)
330
370
  end
331
371
  end
332
-
333
- context "write" do
372
+
373
+ context "write" do
334
374
  it "defines http_options[:ssl] if not defined" do
335
375
  Koala::HTTPService.http_options[:ssl] = nil
336
376
  value = "foo"
@@ -344,14 +384,14 @@ describe "Koala::HTTPService" do
344
384
  Koala::HTTPService.http_options[:ssl].should
345
385
  Koala::HTTPService.http_options[:ssl][deprecated_method].should == value
346
386
  end
347
-
387
+
348
388
  it "does not redefine http_options[:ssl] if already defined" do
349
389
  hash = {:a => 2}
350
390
  Koala::HTTPService.http_options[:ssl] = hash
351
391
  Koala::HTTPService.send(:"#{deprecated_method}=", 3)
352
392
  Koala::HTTPService.http_options[:ssl].should include(hash)
353
393
  end
354
-
394
+
355
395
  it "generates a deprecation warning" do
356
396
  Koala::Utils.should_receive(:deprecate)
357
397
  Koala::HTTPService.send(:"#{deprecated_method}=", 2)
@@ -359,7 +399,7 @@ describe "Koala::HTTPService" do
359
399
  end
360
400
  end
361
401
  end
362
-
402
+
363
403
  describe "per-request options" do
364
404
  before :each do
365
405
  # Setup stubs for make_request to execute without exceptions
@@ -372,18 +412,18 @@ describe "Koala::HTTPService" do
372
412
  @mock_connection.stub(:post).and_return(@mock_http_response)
373
413
  Faraday.stub(:new).and_return(@mock_connection)
374
414
  end
375
-
415
+
376
416
  describe ":typhoeus_options" do
377
417
  it "merges any typhoeus_options into options" do
378
418
  typhoeus_options = {:a => 2}
379
419
  Faraday.should_receive(:new).with(anything, hash_including(typhoeus_options)).and_return(@mock_connection)
380
- Koala::HTTPService.make_request("anything", {}, "get", :typhoeus_options => typhoeus_options)
420
+ Koala::HTTPService.make_request("anything", {}, "get", :typhoeus_options => typhoeus_options)
381
421
  end
382
-
422
+
383
423
  it "deletes the typhoeus_options key" do
384
424
  typhoeus_options = {:a => 2}
385
425
  Faraday.should_receive(:new).with(anything, hash_not_including(:typhoeus_options => typhoeus_options)).and_return(@mock_connection)
386
- Koala::HTTPService.make_request("anything", {}, "get", :typhoeus_options => typhoeus_options)
426
+ Koala::HTTPService.make_request("anything", {}, "get", :typhoeus_options => typhoeus_options)
387
427
  end
388
428
  end
389
429
 
@@ -400,7 +440,7 @@ describe "Koala::HTTPService" do
400
440
  Koala::HTTPService.make_request("anything", {}, "get", :ca_path => ca_path)
401
441
  end
402
442
  end
403
-
443
+
404
444
  describe ":ca_file" do
405
445
  it "sets any ca_file into options[:ssl]" do
406
446
  ca_file = :foo
@@ -414,7 +454,7 @@ describe "Koala::HTTPService" do
414
454
  Koala::HTTPService.make_request("anything", {}, "get", :ca_file => ca_file)
415
455
  end
416
456
  end
417
-
457
+
418
458
  describe ":verify_mode" do
419
459
  it "sets any verify_mode into options[:ssl]" do
420
460
  verify_mode = :foo
@@ -98,6 +98,12 @@ describe "Koala::Facebook::OAuth" do
98
98
  @oauth.stub(:parse_signed_request).and_return({})
99
99
  @oauth.get_user_info_from_cookies(@cookie).should be_nil
100
100
  end
101
+
102
+ it "logs a warning" do
103
+ @oauth.stub(:parse_signed_request).and_return({})
104
+ Koala::Utils.logger.should_receive(:warn)
105
+ @oauth.get_user_info_from_cookies(@cookie)
106
+ end
101
107
  end
102
108
 
103
109
  context "if the code is present" do
@@ -31,4 +31,25 @@ describe Koala::Utils do
31
31
  Koala::Utils.deprecate(message)
32
32
  end
33
33
  end
34
+
35
+ describe ".logger" do
36
+ it "has an accessor for logger" do
37
+ Koala::Utils.methods.map(&:to_sym).should include(:logger)
38
+ Koala::Utils.methods.map(&:to_sym).should include(:logger=)
39
+ end
40
+
41
+ it "defaults to the standard ruby logger with level set to ERROR" do |variable|
42
+ Koala::Utils.logger.should be_kind_of(Logger)
43
+ Koala::Utils.logger.level.should == Logger::ERROR
44
+ end
45
+
46
+ logger_methods = [:debug, :info, :warn, :error, :fatal]
47
+
48
+ logger_methods.each do |logger_method|
49
+ it "should delegate #{logger_method} to the attached logger" do
50
+ Koala::Utils.logger.should_receive(logger_method)
51
+ Koala::Utils.send(logger_method, "Test #{logger_method} message")
52
+ end
53
+ end
54
+ end
34
55
  end
@@ -42,11 +42,11 @@ graph_api:
42
42
 
43
43
  # OAuth error response
44
44
  oauth_error: &oauth_error
45
- no_token: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
45
+ no_token: '{"error": {"code"=>2500, "type": "OAuthException", "message": "Error validating verification code."}}'
46
46
 
47
47
  # Subscription error response
48
48
  verification_error: &verification_error
49
- with_token: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
49
+ with_token: '{"error": {"code"=>2500, "type": "OAuthException", "message": "Error validating verification code."}}'
50
50
 
51
51
  test_user_uninstalled: &test_user_uninstalled
52
52
  post:
@@ -592,10 +592,13 @@ shared_examples_for "Koala GraphAPI without an access token" do
592
592
  end
593
593
 
594
594
  it "can't put an object" do
595
+ lambda { @result = @api.put_connections(KoalaTest.user2, "feed", :message => "Hello, world") }.should raise_error(Koala::Facebook::APIError)
596
+ # legacy put_object syntax
595
597
  lambda { @result = @api.put_object(KoalaTest.user2, "feed", :message => "Hello, world") }.should raise_error(Koala::Facebook::APIError)
596
598
  end
597
599
 
598
- # these are not strictly necessary as the other put methods resolve to put_object, but are here for completeness
600
+ # these are not strictly necessary as the other put methods resolve to put_connections,
601
+ # but are here for completeness
599
602
  it "can't post to a feed" do
600
603
  (lambda do
601
604
  attachment = {:name => "OAuth Playground", :link => "http://oauth.twoalex.com/"}
@@ -1,7 +1,7 @@
1
1
  module KoalaTest
2
2
  # directly taken from Rails 3.1's OrderedHash
3
3
  # see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/ordered_hash.rb
4
-
4
+
5
5
  # The order of iteration over hashes in Ruby 1.8 is undefined. For example, you do not know the
6
6
  # order in which +keys+ will return keys, or +each+ yield pairs. <tt>ActiveSupport::OrderedHash</tt>
7
7
  # implements a hash that preserves insertion order, as in Ruby 1.9:
@@ -192,10 +192,6 @@ module KoalaTest
192
192
  OrderedHash[self.to_a.map!{|key_value_pair| key_value_pair.reverse}]
193
193
  end
194
194
 
195
- def inspect
196
- "#<OrderedHash #{super}>"
197
- end
198
-
199
195
  private
200
196
  def sync_keys!
201
197
  @keys.delete_if {|k| !has_key?(k)}
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: koala
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
5
- prerelease:
4
+ version: 1.5.0rc1
5
+ prerelease: 5
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alex Koppel
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-19 00:00:00.000000000 Z
12
+ date: 2012-04-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 1.3.0
21
+ version: '1.3'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 1.3.0
29
+ version: '1.3'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: faraday
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 0.7.0
37
+ version: '0.7'
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 0.7.0
45
+ version: '0.7'
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: rspec
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 2.8.0rc1
53
+ version: '2.8'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 2.8.0rc1
61
+ version: '2.8'
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rake
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: 0.8.7
69
+ version: '0.8'
70
70
  type: :development
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +74,7 @@ dependencies:
74
74
  requirements:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: 0.8.7
77
+ version: '0.8'
78
78
  description: Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write
79
79
  access to the social graph via the Graph and REST APIs, as well as support for realtime
80
80
  updates and OAuth and Facebook Connect authentication. Koala is fully tested and
@@ -163,13 +163,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
163
  version: '0'
164
164
  segments:
165
165
  - 0
166
- hash: -3018714754119846442
166
+ hash: 2822012277760002951
167
167
  required_rubygems_version: !ruby/object:Gem::Requirement
168
168
  none: false
169
169
  requirements:
170
- - - ! '>='
170
+ - - ! '>'
171
171
  - !ruby/object:Gem::Version
172
- version: '1.2'
172
+ version: 1.3.1
173
173
  requirements: []
174
174
  rubyforge_project:
175
175
  rubygems_version: 1.8.21