koala 3.0.0.beta1 → 3.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/changelog.md +19 -3
- data/koala.gemspec +3 -0
- data/lib/koala/api.rb +47 -19
- data/lib/koala/api/{graph_api.rb → graph_api_methods.rb} +9 -59
- data/lib/koala/api/graph_batch_api.rb +107 -62
- data/lib/koala/http_service/request.rb +1 -5
- data/lib/koala/http_service/response.rb +6 -0
- data/lib/koala/test_users.rb +5 -4
- data/lib/koala/version.rb +1 -1
- data/spec/cases/api_spec.rb +79 -51
- data/spec/cases/graph_api_batch_spec.rb +22 -22
- data/spec/cases/graph_api_spec.rb +15 -10
- data/spec/cases/graph_collection_spec.rb +3 -3
- data/spec/cases/http_service/response_spec.rb +24 -0
- data/spec/cases/test_users_spec.rb +11 -0
- data/spec/fixtures/cat.m4v +0 -0
- data/spec/fixtures/facebook_data.yml +1 -1
- data/spec/fixtures/mock_facebook_responses.yml +25 -28
- data/spec/fixtures/vcr_cassettes/app_test_accounts.yml +97 -0
- data/spec/integration/graph_collection_spec.rb +8 -5
- data/spec/support/graph_api_shared_examples.rb +142 -199
- data/spec/support/koala_test.rb +2 -4
- data/spec/support/mock_http_service.rb +3 -3
- metadata +23 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18d5d8c95bece65d5f4bab2640d75645dc5fb343
|
4
|
+
data.tar.gz: 6ec125b20dea63584e6dd69fc02ecd08f0800ce2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31a10322d86c4c49bd877ad5891cde67db496e506c6b8936d8cf3e67b6bc82e6faed1fe1e93f02dcd123ea8aee77026adc681a3b197006335e7d2f8aac40d968
|
7
|
+
data.tar.gz: f8d69365d42baf15acead1fcc5e38e334084dc49539358189aee046bf611d9c7761ec4ffeac690b07d3a647116ef81ac1e0fdfa2bc1d11010c5ae30dc239a189
|
data/.travis.yml
CHANGED
data/changelog.md
CHANGED
@@ -1,28 +1,44 @@
|
|
1
1
|
v3.0.0
|
2
2
|
======
|
3
3
|
|
4
|
-
Key breaking changes
|
4
|
+
**Key breaking changes:**
|
5
5
|
|
6
|
+
* Koala now requires Ruby 2.1+ (or equivalent for JRuby, etc.)
|
7
|
+
* API#api now returns a Koala::HTTPService::Response object; graph_call handles further processing
|
8
|
+
* GraphBatchAPI no longer inherits from API (the interface is otherwise unchanged)
|
9
|
+
* Empty response bodies in batch API calls will raise a JSON::ParserError rather than returning nil
|
6
10
|
* HTTPService.make_request now requires an HTTPService::Request object (Koala.make_request does
|
7
11
|
not)
|
8
12
|
* HTTPService behavior *should not* change, but in edge cases might. (If so, please let me know.)
|
9
|
-
*
|
13
|
+
* API#search now requires a "type"/:type argument, matching Facebook's behavior (improving their
|
14
|
+
cryptic error message)
|
15
|
+
|
16
|
+
Updated features:
|
17
|
+
|
18
|
+
* TestUser#befriend will provide the appsecret_proof if a secret is set (thanks, kwasimensah!)
|
19
|
+
* API#search now requires an object type parameter to be included, matching Facebook's API (#575)
|
10
20
|
|
11
21
|
Removed features:
|
12
22
|
|
13
23
|
* Removed support for the Rest API, since Facebook removed support for it (#568)
|
14
24
|
* Removed support for FQL, which Facebook removed on August 8, 2016 (#569)
|
15
25
|
* Removed legacy duplication of serveral constants in the Koala module (#569)
|
26
|
+
* Removed API#get_comments_for_urls, which pointed to a no-longer-extant endpoint(#570)
|
16
27
|
|
17
28
|
Internal improvements:
|
18
29
|
|
19
30
|
* Completely rewrote HTTPService.make_request and several others, extracting most logic into
|
20
31
|
HTTPService::Request (#566)
|
32
|
+
* API#api now returns a Koala::HTTPService::Response object (#584)
|
33
|
+
* GraphBatchAPI no longer inherits from API (#580)
|
34
|
+
* GraphBatchAPI has been refactored to be simpler and more readable (thanks, acuppy!) (#551)
|
21
35
|
* Use the more secure JSON.parse instead of JSON.load (thanks, lautis!) (#567)
|
36
|
+
* Use JSON's quirks_mode option to remove hacky JSON hack (#573 -- thanks sakuro for the
|
37
|
+
suggestion!)
|
22
38
|
|
23
39
|
Testing improvements:
|
24
40
|
|
25
|
-
* Fixed a bunch of failing specs
|
41
|
+
* Fixed a bunch of failing mocked specs
|
26
42
|
|
27
43
|
v2.5.0
|
28
44
|
======
|
data/koala.gemspec
CHANGED
@@ -21,6 +21,9 @@ Gem::Specification.new do |gem|
|
|
21
21
|
gem.extra_rdoc_files = ["readme.md", "changelog.md"]
|
22
22
|
gem.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala"]
|
23
23
|
|
24
|
+
gem.required_ruby_version = '>= 2.1'
|
25
|
+
|
24
26
|
gem.add_runtime_dependency("faraday")
|
25
27
|
gem.add_runtime_dependency("addressable")
|
28
|
+
gem.add_runtime_dependency("json", ">= 2.0")
|
26
29
|
end
|
data/lib/koala/api.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# graph_batch_api and legacy are required at the bottom, since they depend on API being defined
|
2
|
-
require 'koala/api/
|
2
|
+
require 'koala/api/graph_api_methods'
|
3
3
|
require 'koala/api/graph_collection'
|
4
4
|
require 'openssl'
|
5
5
|
|
@@ -24,6 +24,45 @@ module Koala
|
|
24
24
|
|
25
25
|
include GraphAPIMethods
|
26
26
|
|
27
|
+
# Make a call directly to the Graph API.
|
28
|
+
# (See any of the other methods for example invocations.)
|
29
|
+
#
|
30
|
+
# @param path the Graph API path to query (no leading / needed)
|
31
|
+
# @param args (see #get_object)
|
32
|
+
# @param verb the type of HTTP request to make (get, post, delete, etc.)
|
33
|
+
# @options (see #get_object)
|
34
|
+
#
|
35
|
+
# @yield response when making a batch API call, you can pass in a block
|
36
|
+
# that parses the results, allowing for cleaner code.
|
37
|
+
# The block's return value is returned in the batch results.
|
38
|
+
# See the code for {#get_picture} for examples.
|
39
|
+
# (Not needed in regular calls; you'll probably rarely use this.)
|
40
|
+
#
|
41
|
+
# @raise [Koala::Facebook::APIError] if Facebook returns an error
|
42
|
+
#
|
43
|
+
# @return the result from Facebook
|
44
|
+
def graph_call(path, args = {}, verb = "get", options = {}, &post_processing)
|
45
|
+
# enable appsecret_proof by default
|
46
|
+
options = {:appsecret_proof => true}.merge(options) if @app_secret
|
47
|
+
response = api(path, args, verb, options)
|
48
|
+
|
49
|
+
error = GraphErrorChecker.new(response.status, response.body, response.headers).error_if_appropriate
|
50
|
+
raise error if error
|
51
|
+
|
52
|
+
# if we want a component other than the body (e.g. redirect header for images), provide that
|
53
|
+
http_component = options[:http_component]
|
54
|
+
desired_data = if options[:http_component]
|
55
|
+
http_component == :response ? response : response.send(http_component)
|
56
|
+
else
|
57
|
+
# turn this into a GraphCollection if it's pageable
|
58
|
+
API::GraphCollection.evaluate(response.data, self)
|
59
|
+
end
|
60
|
+
|
61
|
+
# now process as appropriate for the given call (get picture header, etc.)
|
62
|
+
post_processing ? post_processing.call(desired_data) : desired_data
|
63
|
+
end
|
64
|
+
|
65
|
+
|
27
66
|
# Makes a request to the appropriate Facebook API.
|
28
67
|
# @note You'll rarely need to call this method directly.
|
29
68
|
#
|
@@ -42,14 +81,10 @@ module Koala
|
|
42
81
|
# @option options [Boolean] :beta use Facebook's beta tier
|
43
82
|
# @option options [Boolean] :use_ssl force SSL for this request, even if it's tokenless.
|
44
83
|
# (All API requests with access tokens use SSL.)
|
45
|
-
# @param error_checking_block a block to evaluate the response status for additional JSON-encoded errors
|
46
|
-
#
|
47
|
-
# @yield The response for evaluation
|
48
|
-
#
|
49
84
|
# @raise [Koala::Facebook::ServerError] if Facebook returns an error (response status >= 500)
|
50
85
|
#
|
51
|
-
# @return
|
52
|
-
def api(path, args = {}, verb = "get", options = {}
|
86
|
+
# @return a Koala::HTTPService::Response object representing the returned Facebook data
|
87
|
+
def api(path, args = {}, verb = "get", options = {})
|
53
88
|
# we make a copy of args so the modifications (added access_token & appsecret_proof)
|
54
89
|
# do not affect the received argument
|
55
90
|
args = args.dup
|
@@ -58,6 +93,7 @@ module Koala
|
|
58
93
|
# This is explicitly needed in batch requests so GraphCollection
|
59
94
|
# results preserve any specific access tokens provided
|
60
95
|
args["access_token"] ||= @access_token || @app_access_token if @access_token || @app_access_token
|
96
|
+
|
61
97
|
if options.delete(:appsecret_proof) && args["access_token"] && @app_secret
|
62
98
|
args["appsecret_proof"] = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), @app_secret, args["access_token"])
|
63
99
|
end
|
@@ -75,18 +111,7 @@ module Koala
|
|
75
111
|
raise Koala::Facebook::ServerError.new(result.status.to_i, result.body)
|
76
112
|
end
|
77
113
|
|
78
|
-
|
79
|
-
|
80
|
-
# if we want a component other than the body (e.g. redirect header for images), return that
|
81
|
-
if component = options[:http_component]
|
82
|
-
component == :response ? result : result.send(options[:http_component])
|
83
|
-
else
|
84
|
-
# parse the body as JSON and run it through the error checker (if provided)
|
85
|
-
# Note: Facebook sometimes sends results like "true" and "false", which are valid[RFC7159]
|
86
|
-
# but unsupported by Ruby's stdlib[RFC4627] and cause JSON.parse to fail -- so we account for
|
87
|
-
# that by wrapping the result in []
|
88
|
-
JSON.parse("[#{result.body.to_s}]")[0]
|
89
|
-
end
|
114
|
+
result
|
90
115
|
end
|
91
116
|
|
92
117
|
private
|
@@ -112,6 +137,9 @@ module Koala
|
|
112
137
|
def preserve_form_arguments?(options)
|
113
138
|
options[:format] == :json || options[:preserve_form_arguments] || Koala.config.preserve_form_arguments
|
114
139
|
end
|
140
|
+
|
141
|
+
def check_response(http_status, body, headers)
|
142
|
+
end
|
115
143
|
end
|
116
144
|
end
|
117
145
|
end
|
@@ -32,7 +32,6 @@ module Koala
|
|
32
32
|
# for the active user from the cookie provided by Facebook.
|
33
33
|
# See the Koala and Facebook documentation for more information.
|
34
34
|
module GraphAPIMethods
|
35
|
-
|
36
35
|
# Objects
|
37
36
|
|
38
37
|
# Get information about a Facebook object.
|
@@ -107,7 +106,7 @@ module Koala
|
|
107
106
|
# @return true if successful, false (or an APIError) if not
|
108
107
|
def delete_object(id, options = {}, &block)
|
109
108
|
# Deletes the object with the given ID from the graph.
|
110
|
-
raise AuthenticationError.new(nil, nil, "Delete requires an access token") unless
|
109
|
+
raise AuthenticationError.new(nil, nil, "Delete requires an access token") unless access_token
|
111
110
|
graph_call(id, {}, "delete", options, &block)
|
112
111
|
end
|
113
112
|
|
@@ -157,7 +156,7 @@ module Koala
|
|
157
156
|
# @return a hash containing the new object's id
|
158
157
|
def put_connections(id, connection_name, args = {}, options = {}, &block)
|
159
158
|
# Posts a certain connection
|
160
|
-
raise AuthenticationError.new(nil, nil, "Write operations require an access token") unless
|
159
|
+
raise AuthenticationError.new(nil, nil, "Write operations require an access token") unless access_token
|
161
160
|
|
162
161
|
graph_call("#{id}/#{connection_name}", args, "post", options, &block)
|
163
162
|
end
|
@@ -175,7 +174,7 @@ module Koala
|
|
175
174
|
# @return (see #delete_object)
|
176
175
|
def delete_connections(id, connection_name, args = {}, options = {}, &block)
|
177
176
|
# Deletes a given connection
|
178
|
-
raise AuthenticationError.new(nil, nil, "Delete requires an access token") unless
|
177
|
+
raise AuthenticationError.new(nil, nil, "Delete requires an access token") unless access_token
|
179
178
|
graph_call("#{id}/#{connection_name}", args, "delete", options, &block)
|
180
179
|
end
|
181
180
|
|
@@ -336,7 +335,7 @@ module Koala
|
|
336
335
|
# @return (see #delete_object)
|
337
336
|
def delete_like(id, options = {}, &block)
|
338
337
|
# Unlikes a given object for the logged-in user
|
339
|
-
raise AuthenticationError.new(nil, nil, "Unliking requires an access token") unless
|
338
|
+
raise AuthenticationError.new(nil, nil, "Unliking requires an access token") unless access_token
|
340
339
|
graph_call("#{id}/likes", {}, "delete", options, &block)
|
341
340
|
end
|
342
341
|
|
@@ -344,14 +343,16 @@ module Koala
|
|
344
343
|
# See {http://developers.facebook.com/docs/reference/api/#searching Facebook documentation} for more information.
|
345
344
|
#
|
346
345
|
# @param search_terms the query to search for
|
347
|
-
# @param args additional arguments, such as
|
346
|
+
# @param args object type and any additional arguments, such as fields, etc.
|
348
347
|
# @param options (see #get_object)
|
349
348
|
# @param block (see Koala::Facebook::API#api)
|
350
349
|
#
|
351
350
|
# @return [Koala::Facebook::API::GraphCollection] an array of search results
|
352
351
|
def search(search_terms, args = {}, options = {}, &block)
|
353
|
-
|
354
|
-
|
352
|
+
# Normally we wouldn't enforce Facebook API behavior, but the API fails with cryptic error
|
353
|
+
# messages if you fail to include a type term. For a convenience method, that is valuable.
|
354
|
+
raise ArgumentError, "type must be includedin args when searching" unless args[:type] || args["type"]
|
355
|
+
graph_call("search", args.merge("q" => search_terms), "get", options, &block)
|
355
356
|
end
|
356
357
|
|
357
358
|
# Convenience Methods
|
@@ -391,21 +392,6 @@ module Koala
|
|
391
392
|
block ? block.call(access_token_info) : access_token_info
|
392
393
|
end
|
393
394
|
|
394
|
-
# Fetches the comments from fb:comments widgets for a given set of URLs (array or comma-separated string).
|
395
|
-
# See https://developers.facebook.com/blog/post/490.
|
396
|
-
#
|
397
|
-
# @param urls the URLs for which you want comments
|
398
|
-
# @param args (see #get_object)
|
399
|
-
# @param options (see #get_object)
|
400
|
-
# @param block (see Koala::Facebook::API#api)
|
401
|
-
#
|
402
|
-
# @returns a hash of urls => comment arrays
|
403
|
-
def get_comments_for_urls(urls = [], args = {}, options = {}, &block)
|
404
|
-
return [] if urls.empty?
|
405
|
-
args.merge!(:ids => urls.respond_to?(:join) ? urls.join(",") : urls)
|
406
|
-
get_object("comments", args, options, &block)
|
407
|
-
end
|
408
|
-
|
409
395
|
# App restrictions require you to JSON-encode the restriction value. This
|
410
396
|
# is neither obvious nor intuitive, so this convenience method is
|
411
397
|
# provided.
|
@@ -479,44 +465,8 @@ module Koala
|
|
479
465
|
end
|
480
466
|
end
|
481
467
|
|
482
|
-
# Make a call directly to the Graph API.
|
483
|
-
# (See any of the other methods for example invocations.)
|
484
|
-
#
|
485
|
-
# @param path the Graph API path to query (no leading / needed)
|
486
|
-
# @param args (see #get_object)
|
487
|
-
# @param verb the type of HTTP request to make (get, post, delete, etc.)
|
488
|
-
# @options (see #get_object)
|
489
|
-
#
|
490
|
-
# @yield response when making a batch API call, you can pass in a block
|
491
|
-
# that parses the results, allowing for cleaner code.
|
492
|
-
# The block's return value is returned in the batch results.
|
493
|
-
# See the code for {#get_picture} for examples.
|
494
|
-
# (Not needed in regular calls; you'll probably rarely use this.)
|
495
|
-
#
|
496
|
-
# @raise [Koala::Facebook::APIError] if Facebook returns an error
|
497
|
-
#
|
498
|
-
# @return the result from Facebook
|
499
|
-
def graph_call(path, args = {}, verb = "get", options = {}, &post_processing)
|
500
|
-
# enable appsecret_proof by default
|
501
|
-
options = {:appsecret_proof => true}.merge(options) if @app_secret
|
502
|
-
result = api(path, args, verb, options) do |response|
|
503
|
-
error = check_response(response.status, response.body, response.headers)
|
504
|
-
raise error if error
|
505
|
-
end
|
506
|
-
|
507
|
-
# turn this into a GraphCollection if it's pageable
|
508
|
-
result = API::GraphCollection.evaluate(result, self)
|
509
|
-
|
510
|
-
# now process as appropriate for the given call (get picture header, etc.)
|
511
|
-
post_processing ? post_processing.call(result) : result
|
512
|
-
end
|
513
|
-
|
514
468
|
private
|
515
469
|
|
516
|
-
def check_response(http_status, body, headers)
|
517
|
-
GraphErrorChecker.new(http_status, body, headers).error_if_appropriate
|
518
|
-
end
|
519
|
-
|
520
470
|
def parse_media_args(media_args, method)
|
521
471
|
# photo and video uploads can accept different types of arguments (see above)
|
522
472
|
# so here, we parse the arguments into a form directly usable in put_connections
|
@@ -4,13 +4,12 @@ require 'koala/api/batch_operation'
|
|
4
4
|
module Koala
|
5
5
|
module Facebook
|
6
6
|
# @private
|
7
|
-
class GraphBatchAPI
|
7
|
+
class GraphBatchAPI
|
8
8
|
# inside a batch call we can do anything a regular Graph API can do
|
9
9
|
include GraphAPIMethods
|
10
10
|
|
11
11
|
attr_reader :original_api
|
12
12
|
def initialize(api)
|
13
|
-
super(api.access_token, api.app_secret)
|
14
13
|
@original_api = api
|
15
14
|
end
|
16
15
|
|
@@ -18,7 +17,9 @@ module Koala
|
|
18
17
|
@batch_calls ||= []
|
19
18
|
end
|
20
19
|
|
21
|
-
|
20
|
+
# Enqueue a call into the batch for later processing.
|
21
|
+
# See API#graph_call
|
22
|
+
def graph_call(path, args = {}, verb = 'get', options = {}, &post_processing)
|
22
23
|
# normalize options for consistency
|
23
24
|
options = Koala::Utils.symbolize_hash(options)
|
24
25
|
|
@@ -34,73 +35,117 @@ module Koala
|
|
34
35
|
nil # batch operations return nothing immediately
|
35
36
|
end
|
36
37
|
|
37
|
-
# redefine the graph_call method so we can use this API inside the batch block
|
38
|
-
# just like any regular Graph API
|
39
|
-
alias_method :graph_call_outside_batch, :graph_call
|
40
|
-
alias_method :graph_call, :graph_call_in_batch
|
41
|
-
|
42
38
|
# execute the queued batch calls
|
43
39
|
def execute(http_options = {})
|
44
|
-
return []
|
40
|
+
return [] if batch_calls.empty?
|
41
|
+
|
45
42
|
# Turn the call args collected into what facebook expects
|
46
|
-
args = {}
|
47
|
-
|
48
|
-
args.merge!
|
49
|
-
|
50
|
-
})
|
43
|
+
args = { 'batch' => batch_args }
|
44
|
+
batch_calls.each do |call|
|
45
|
+
args.merge! call.files || {}
|
46
|
+
end
|
51
47
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
48
|
+
original_api.graph_call('/', args, 'post', http_options, &handle_response)
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle_response
|
52
|
+
lambda do |response|
|
53
|
+
raise bad_response if response.nil?
|
54
|
+
response.map(&generate_results)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def generate_results
|
59
|
+
index = 0
|
60
|
+
lambda do |call_result|
|
61
|
+
batch_op = batch_calls[index]; index += 1
|
62
|
+
post_process = batch_op.post_processing
|
58
63
|
|
59
|
-
#
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
else
|
71
|
-
{}
|
72
|
-
end
|
73
|
-
|
74
|
-
if (error = check_response(call_result['code'], call_result['body'].to_s, parsed_headers))
|
75
|
-
raw_result = error
|
76
|
-
else
|
77
|
-
# (see note in regular api method about JSON parsing)
|
78
|
-
body = JSON.parse("[#{call_result['body'].to_s}]")[0]
|
79
|
-
|
80
|
-
# Get the HTTP component they want
|
81
|
-
raw_result = case batch_op.http_options[:http_component]
|
82
|
-
when :status
|
83
|
-
call_result["code"].to_i
|
84
|
-
when :headers
|
85
|
-
# facebook returns the headers as an array of k/v pairs, but we want a regular hash
|
86
|
-
parsed_headers
|
87
|
-
else
|
88
|
-
body
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# turn any results that are pageable into GraphCollections
|
94
|
-
# and pass to post-processing callback if given
|
95
|
-
result = GraphCollection.evaluate(raw_result, @original_api)
|
96
|
-
if batch_op.post_processing
|
97
|
-
batch_op.post_processing.call(result)
|
98
|
-
else
|
99
|
-
result
|
100
|
-
end
|
64
|
+
# turn any results that are pageable into GraphCollections
|
65
|
+
result = GraphCollection.evaluate(
|
66
|
+
result_from_response(call_result, batch_op),
|
67
|
+
original_api
|
68
|
+
)
|
69
|
+
|
70
|
+
# and pass to post-processing callback if given
|
71
|
+
if post_process
|
72
|
+
post_process.call(result)
|
73
|
+
else
|
74
|
+
result
|
101
75
|
end
|
102
76
|
end
|
103
77
|
end
|
78
|
+
|
79
|
+
def bad_response
|
80
|
+
# Facebook sometimes reportedly returns an empty body at times
|
81
|
+
BadFacebookResponse.new(200, '', 'Facebook returned an empty body')
|
82
|
+
end
|
83
|
+
|
84
|
+
def result_from_response(response, options)
|
85
|
+
return nil if response.nil?
|
86
|
+
|
87
|
+
headers = coerced_headers_from_response(response)
|
88
|
+
error = error_from_response(response, headers)
|
89
|
+
component = options.http_options[:http_component]
|
90
|
+
|
91
|
+
error || result_from_component({
|
92
|
+
:component => component,
|
93
|
+
:response => response,
|
94
|
+
:headers => headers
|
95
|
+
})
|
96
|
+
end
|
97
|
+
|
98
|
+
def coerced_headers_from_response(response)
|
99
|
+
headers = response.fetch('headers', [])
|
100
|
+
|
101
|
+
headers.each_with_object({}) do |h, memo|
|
102
|
+
memo.merge! h.fetch('name') => h.fetch('value')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def error_from_response(response, headers)
|
107
|
+
code = response['code']
|
108
|
+
body = response['body'].to_s
|
109
|
+
|
110
|
+
GraphErrorChecker.new(code, body, headers).error_if_appropriate
|
111
|
+
end
|
112
|
+
|
113
|
+
def batch_args
|
114
|
+
calls = batch_calls.map do |batch_op|
|
115
|
+
batch_op.to_batch_params(access_token, app_secret)
|
116
|
+
end
|
117
|
+
|
118
|
+
JSON.dump calls
|
119
|
+
end
|
120
|
+
|
121
|
+
def json_body(response)
|
122
|
+
# quirks_mode is needed because Facebook sometimes returns a raw true or false value --
|
123
|
+
# in Ruby 2.4 we can drop that.
|
124
|
+
JSON.parse(response.fetch('body'), quirks_mode: true)
|
125
|
+
end
|
126
|
+
|
127
|
+
def result_from_component(options)
|
128
|
+
component = options.fetch(:component)
|
129
|
+
response = options.fetch(:response)
|
130
|
+
headers = options.fetch(:headers)
|
131
|
+
|
132
|
+
# Get the HTTP component they want
|
133
|
+
case component
|
134
|
+
when :status then response['code'].to_i
|
135
|
+
# facebook returns the headers as an array of k/v pairs, but we want a regular hash
|
136
|
+
when :headers then headers
|
137
|
+
# (see note in regular api method about JSON parsing)
|
138
|
+
else json_body(response)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def access_token
|
143
|
+
original_api.access_token
|
144
|
+
end
|
145
|
+
|
146
|
+
def app_secret
|
147
|
+
original_api.app_secret
|
148
|
+
end
|
104
149
|
end
|
105
150
|
end
|
106
151
|
end
|