koala 1.2.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/.gitignore +3 -1
  2. data/.rspec +1 -0
  3. data/.travis.yml +4 -0
  4. data/.yardopts +3 -0
  5. data/CHANGELOG +28 -0
  6. data/Gemfile +14 -0
  7. data/Guardfile +6 -0
  8. data/koala.gemspec +3 -3
  9. data/lib/koala/api/batch_operation.rb +83 -0
  10. data/lib/koala/api/graph_api.rb +476 -0
  11. data/lib/koala/{graph_batch_api.rb → api/graph_batch_api.rb} +22 -17
  12. data/lib/koala/api/graph_collection.rb +107 -0
  13. data/lib/koala/api/legacy.rb +26 -0
  14. data/lib/koala/{rest_api.rb → api/rest_api.rb} +34 -13
  15. data/lib/koala/api.rb +93 -0
  16. data/lib/koala/http_service/multipart_request.rb +41 -0
  17. data/lib/koala/http_service/response.rb +18 -0
  18. data/lib/koala/http_service/uploadable_io.rb +187 -0
  19. data/lib/koala/http_service.rb +69 -20
  20. data/lib/koala/oauth.rb +170 -36
  21. data/lib/koala/realtime_updates.rb +89 -51
  22. data/lib/koala/test_users.rb +122 -32
  23. data/lib/koala/utils.rb +11 -4
  24. data/lib/koala/version.rb +1 -1
  25. data/lib/koala.rb +16 -96
  26. data/readme.md +9 -9
  27. data/spec/cases/api_spec.rb +19 -12
  28. data/spec/cases/error_spec.rb +10 -0
  29. data/spec/cases/graph_api_batch_spec.rb +100 -58
  30. data/spec/cases/graph_collection_spec.rb +23 -7
  31. data/spec/cases/http_service_spec.rb +5 -26
  32. data/spec/cases/koala_spec.rb +22 -4
  33. data/spec/cases/legacy_spec.rb +115 -0
  34. data/spec/cases/multipart_request_spec.rb +7 -7
  35. data/spec/cases/oauth_spec.rb +134 -48
  36. data/spec/cases/realtime_updates_spec.rb +154 -47
  37. data/spec/cases/test_users_spec.rb +276 -219
  38. data/spec/cases/uploadable_io_spec.rb +1 -1
  39. data/spec/cases/utils_spec.rb +29 -5
  40. data/spec/fixtures/mock_facebook_responses.yml +41 -30
  41. data/spec/spec_helper.rb +3 -0
  42. data/spec/support/custom_matchers.rb +28 -0
  43. data/spec/support/graph_api_shared_examples.rb +192 -14
  44. data/spec/support/koala_test.rb +10 -1
  45. data/spec/support/mock_http_service.rb +2 -2
  46. data/spec/support/rest_api_shared_examples.rb +5 -165
  47. metadata +75 -99
  48. data/lib/koala/batch_operation.rb +0 -74
  49. data/lib/koala/graph_api.rb +0 -270
  50. data/lib/koala/graph_collection.rb +0 -59
  51. data/lib/koala/multipart_request.rb +0 -35
  52. data/lib/koala/uploadable_io.rb +0 -181
  53. data/spec/cases/graph_and_rest_api_spec.rb +0 -22
  54. data/spec/cases/graph_api_spec.rb +0 -22
  55. data/spec/cases/rest_api_spec.rb +0 -22
@@ -1,36 +1,27 @@
1
1
  module Koala
2
2
  module Facebook
3
- module RealtimeUpdateMethods
4
- # note: to subscribe to real-time updates, you must have an application access token
3
+ class RealtimeUpdates
4
+ # Manage realtime callbacks for changes to users' information.
5
+ # See http://developers.facebook.com/docs/reference/api/realtime.
6
+ #
7
+ # @note: to subscribe to real-time updates, you must have an application access token
8
+ # or provide the app secret when initializing your RealtimeUpdates object.
5
9
 
6
- def self.included(base)
7
- # make the attributes readable
8
- base.class_eval do
9
- attr_reader :api, :app_id, :app_access_token, :secret
10
-
11
- # parses the challenge params and makes sure the call is legitimate
12
- # returns the challenge string to be sent back to facebook if true
13
- # returns false otherwise
14
- # this is a class method, since you don't need to know anything about the app
15
- # saves a potential trip fetching the app access token
16
- def self.meet_challenge(params, verify_token = nil, &verification_block)
17
- if params["hub.mode"] == "subscribe" &&
18
- # you can make sure this is legitimate through two ways
19
- # if your store the token across the calls, you can pass in the token value
20
- # and we'll make sure it matches
21
- (verify_token && params["hub.verify_token"] == verify_token) ||
22
- # alternately, if you sent a specially-constructed value (such as a hash of various secret values)
23
- # you can pass in a block, which we'll call with the verify_token sent by Facebook
24
- # if it's legit, return anything that evaluates to true; otherwise, return nil or false
25
- (verification_block && yield(params["hub.verify_token"]))
26
- params["hub.challenge"]
27
- else
28
- false
29
- end
30
- end
31
- end
32
- end
10
+ # The application API interface used to communicate with Facebook.
11
+ # @return [Koala::Facebook::API]
12
+ attr_reader :api
13
+ attr_reader :app_id, :app_access_token, :secret
33
14
 
15
+ # Create a new RealtimeUpdates instance.
16
+ # If you don't have your app's access token, provide the app's secret and
17
+ # Koala will make a request to Facebook for the appropriate token.
18
+ #
19
+ # @param options initialization options.
20
+ # @option options :app_id the application's ID.
21
+ # @option options :app_access_token an application access token, if known.
22
+ # @option options :secret the application's secret.
23
+ #
24
+ # @raise ArgumentError if the application ID and one of the app access token or the secret are not provided.
34
25
  def initialize(options = {})
35
26
  @app_id = options[:app_id]
36
27
  @app_access_token = options[:app_access_token]
@@ -45,45 +36,92 @@ module Koala
45
36
  @app_access_token = oauth.get_app_access_token
46
37
  end
47
38
 
48
- @graph_api = API.new(@app_access_token)
39
+ @api = API.new(@app_access_token)
49
40
  end
50
41
 
51
- # subscribes for realtime updates
52
- # your callback_url must be set up to handle the verification request or the subscription will not be set up
53
- # http://developers.facebook.com/docs/api/realtime
54
- def subscribe(object, fields, callback_url, verify_token)
42
+ # Subscribe to realtime updates for certain fields on a given object (user, page, etc.).
43
+ # See {http://developers.facebook.com/docs/reference/api/realtime the realtime updates documentation}
44
+ # for more information on what objects and fields you can register for.
45
+ #
46
+ # @note Your callback_url must be set up to handle the verification request or the subscription will not be set up.
47
+ #
48
+ # @param object a Facebook ID (name or number)
49
+ # @param fields the fields you want your app to be updated about
50
+ # @param callback_url the URL Facebook should ping when an update is available
51
+ # @param verify_token a token included in the verification request, allowing you to ensure the call is genuine
52
+ # (see the docs for more information)
53
+ # @param options (see Koala::HTTPService.make_request)
54
+ #
55
+ # @return true if successful, false (or an APIError) otherwise.
56
+ def subscribe(object, fields, callback_url, verify_token, options = {})
55
57
  args = {
56
58
  :object => object,
57
59
  :fields => fields,
58
60
  :callback_url => callback_url,
59
- :verify_token => verify_token
60
- }
61
+ }.merge(verify_token ? {:verify_token => verify_token} : {})
61
62
  # a subscription is a success if Facebook returns a 200 (after hitting your server for verification)
62
- @graph_api.graph_call(subscription_path, args, 'post', :http_component => :status) == 200
63
+ @api.graph_call(subscription_path, args, 'post', options.merge(:http_component => :status)) == 200
63
64
  end
64
65
 
65
- # removes subscription for object
66
- # if object is nil, it will remove all subscriptions
67
- def unsubscribe(object = nil)
68
- args = {}
69
- args[:object] = object if object
70
- @graph_api.graph_call(subscription_path, args, 'delete', :http_component => :status) == 200
66
+ # Unsubscribe from updates for a particular object or from updates.
67
+ #
68
+ # @param object the object whose subscriptions to delete.
69
+ # If no object is provided, all subscriptions will be removed.
70
+ # @param options (see Koala::HTTPService.make_request)
71
+ #
72
+ # @return true if the unsubscription is successful, false (or an APIError) otherwise.
73
+ def unsubscribe(object = nil, options = {})
74
+ @api.graph_call(subscription_path, object ? {:object => object} : {}, "delete", options.merge(:http_component => :status)) == 200
71
75
  end
72
76
 
73
- def list_subscriptions
74
- @graph_api.graph_call(subscription_path)
77
+ # List all active subscriptions for this application.
78
+ #
79
+ # @param options (see Koala::HTTPService.make_request)
80
+ #
81
+ # @return [Array] a list of active subscriptions
82
+ def list_subscriptions(options = {})
83
+ @api.graph_call(subscription_path, {}, "get", options)
75
84
  end
76
85
 
77
- def graph_api
78
- Koala::Utils.deprecate("the TestUsers.graph_api accessor is deprecated and will be removed in a future version; please use .api instead.")
79
- @api
86
+ # As a security measure (to prevent DDoS attacks), Facebook sends a verification request to your server
87
+ # after you request a subscription.
88
+ # This method parses the challenge params and makes sure the call is legitimate.
89
+ #
90
+ # @param params the request parameters sent by Facebook. (You can pass in a Rails params hash.)
91
+ # @param verify_token the verify token sent in the {#subscribe subscription request}, if you provided one
92
+ #
93
+ # @yield verify_token if you need to compute the verification token
94
+ # (for instance, if your callback URL includes a record ID, which you look up
95
+ # and use to calculate a hash), you can pass meet_challenge a block, which
96
+ # will receive the verify_token received back from Facebook.
97
+ #
98
+ # @return the challenge string to be sent back to Facebook, or false if the request is invalid.
99
+ def self.meet_challenge(params, verify_token = nil, &verification_block)
100
+ if params["hub.mode"] == "subscribe" &&
101
+ # you can make sure this is legitimate through two ways
102
+ # if your store the token across the calls, you can pass in the token value
103
+ # and we'll make sure it matches
104
+ (verify_token && params["hub.verify_token"] == verify_token) ||
105
+ # alternately, if you sent a specially-constructed value (such as a hash of various secret values)
106
+ # you can pass in a block, which we'll call with the verify_token sent by Facebook
107
+ # if it's legit, return anything that evaluates to true; otherwise, return nil or false
108
+ (verification_block && yield(params["hub.verify_token"]))
109
+ params["hub.challenge"]
110
+ else
111
+ false
112
+ end
80
113
  end
81
-
82
- protected
83
-
114
+
115
+ # The Facebook subscription management URL for your application.
84
116
  def subscription_path
85
117
  @subscription_path ||= "#{@app_id}/subscriptions"
86
118
  end
119
+
120
+ # @private
121
+ def graph_api
122
+ Koala::Utils.deprecate("the TestUsers.graph_api accessor is deprecated and will be removed in a future version; please use .api instead.")
123
+ @api
124
+ end
87
125
  end
88
126
  end
89
127
  end
@@ -2,15 +2,34 @@ require 'koala'
2
2
 
3
3
  module Koala
4
4
  module Facebook
5
- module TestUserMethods
6
-
7
- def self.included(base)
8
- base.class_eval do
9
- # make the Graph API accessible in case someone wants to make other calls to interact with their users
10
- attr_reader :api, :app_id, :app_access_token, :secret
11
- end
12
- end
13
-
5
+
6
+ # Create and manage test users for your application.
7
+ # A test user is a user account associated with an app created for the purpose
8
+ # of testing the functionality of that app.
9
+ # You can use test users for manual or automated testing --
10
+ # Koala's live test suite uses test users to verify the library works with Facebook.
11
+ #
12
+ # @note the test user API is fairly slow compared to other interfaces
13
+ # (which makes sense -- it's creating whole new user accounts!).
14
+ #
15
+ # See http://developers.facebook.com/docs/test_users/.
16
+ class TestUsers
17
+
18
+ # The application API interface used to communicate with Facebook.
19
+ # @return [Koala::Facebook::API]
20
+ attr_reader :api
21
+ attr_reader :app_id, :app_access_token, :secret
22
+
23
+ # Create a new TestUsers instance.
24
+ # If you don't have your app's access token, provide the app's secret and
25
+ # Koala will make a request to Facebook for the appropriate token.
26
+ #
27
+ # @param options initialization options.
28
+ # @option options :app_id the application's ID.
29
+ # @option options :app_access_token an application access token, if known.
30
+ # @option options :secret the application's secret.
31
+ #
32
+ # @raise ArgumentError if the application ID and one of the app access token or the secret are not provided.
14
33
  def initialize(options = {})
15
34
  @app_id = options[:app_id]
16
35
  @app_access_token = options[:app_access_token]
@@ -24,35 +43,94 @@ module Koala
24
43
  oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
25
44
  @app_access_token = oauth.get_app_access_token
26
45
  end
46
+
27
47
  @api = API.new(@app_access_token)
28
48
  end
29
49
 
50
+ # Create a new test user.
51
+ #
52
+ # @param installed whether the user has installed your app
53
+ # @param permissions a comma-separated string or array of permissions the user has granted (if installed)
54
+ # @param args any additional arguments for the create call (name, etc.)
55
+ # @param options (see Koala::Facebook::API#api)
56
+ #
57
+ # @return a hash of information for the new user (id, access token, login URL, etc.)
30
58
  def create(installed, permissions = nil, args = {}, options = {})
31
59
  # Creates and returns a test user
32
60
  args['installed'] = installed
33
61
  args['permissions'] = (permissions.is_a?(Array) ? permissions.join(",") : permissions) if installed
34
- @api.graph_call(accounts_path, args, "post", options)
62
+ @api.graph_call(test_user_accounts_path, args, "post", options)
35
63
  end
36
64
 
37
- def list
38
- @api.graph_call(accounts_path)
65
+ # List all test users for the app.
66
+ #
67
+ # @param options (see Koala::Facebook::API#api)
68
+ #
69
+ # @return an array of hashes of user information (id, access token, etc.)
70
+ def list(options = {})
71
+ @api.graph_call(test_user_accounts_path, {}, "get", options)
39
72
  end
40
73
 
41
- def delete(test_user)
74
+ # Delete a test user.
75
+ #
76
+ # @param test_user the user to delete; can be either a Facebook ID or the hash returned by {#create}
77
+ # @param options (see Koala::Facebook::API#api)
78
+ #
79
+ # @return true if successful, false (or an {Koala::Facebook::APIError APIError}) if not
80
+ def delete(test_user, options = {})
42
81
  test_user = test_user["id"] if test_user.is_a?(Hash)
43
- @api.delete_object(test_user)
82
+ @api.delete_object(test_user, options)
44
83
  end
45
84
 
46
- def delete_all
47
- list.each {|u| delete u}
85
+ # Deletes all test users in batches of 50.
86
+ #
87
+ # @note if you have a lot of test users (> 20), this operation can take a long time.
88
+ #
89
+ # @param options (see Koala::Facebook::API#api)
90
+ #
91
+ # @return a list of the test users that have been deleted
92
+ def delete_all(options = {})
93
+ # ideally we'd save a call by checking next_page_params, but at the time of writing
94
+ # Facebook isn't consistently returning full pages after the first one
95
+ previous_list = nil
96
+ while (test_user_list = list(options)).length > 0
97
+ # avoid infinite loops if Facebook returns buggy users you can't delete
98
+ # see http://developers.facebook.com/bugs/223629371047398
99
+ break if test_user_list == previous_list
100
+
101
+ test_user_list.each_slice(50) do |users|
102
+ self.api.batch(options) {|batch_api| users.each {|u| batch_api.delete_object(u["id"]) }}
103
+ end
104
+
105
+ previous_list = test_user_list
106
+ end
48
107
  end
49
108
 
50
- def update(test_user, args = {}, http_options = {})
109
+ # Updates a test user's attributes.
110
+ #
111
+ # @note currently, only name and password can be changed;
112
+ # see {http://developers.facebook.com/docs/test_users/ the Facebook documentation}.
113
+ #
114
+ # @param test_user the user to update; can be either a Facebook ID or the hash returned by {#create}
115
+ # @param args the updates to make
116
+ # @param options (see Koala::Facebook::API#api)
117
+ #
118
+ # @return true if successful, false (or an {Koala::Facebook::APIError APIError}) if not
119
+ def update(test_user, args = {}, options = {})
51
120
  test_user = test_user["id"] if test_user.is_a?(Hash)
52
- @api.graph_call(test_user, args, "post", http_options)
121
+ @api.graph_call(test_user, args, "post", options)
53
122
  end
54
123
 
55
- def befriend(user1_hash, user2_hash)
124
+ # Make two test users friends.
125
+ #
126
+ # @note there's no way to unfriend test users; you can always just create a new one.
127
+ #
128
+ # @param user1_hash one of the users to friend; the hash must contain both ID and access token (as returned by {#create})
129
+ # @param user2_hash the other user to friend
130
+ # @param options (see Koala::Facebook::API#api)
131
+ #
132
+ # @return true if successful, false (or an {Koala::Facebook::APIError APIError}) if not
133
+ def befriend(user1_hash, user2_hash, options = {})
56
134
  user1_id = user1_hash["id"] || user1_hash[:id]
57
135
  user2_id = user2_hash["id"] || user2_hash[:id]
58
136
  user1_token = user1_hash["access_token"] || user1_hash[:access_token]
@@ -67,35 +145,47 @@ module Koala
67
145
  u1_graph_api = API.new(user1_token)
68
146
  u2_graph_api = API.new(user2_token)
69
147
 
70
- u1_graph_api.graph_call("#{user1_id}/friends/#{user2_id}", {}, "post") &&
71
- u2_graph_api.graph_call("#{user2_id}/friends/#{user1_id}", {}, "post")
148
+ u1_graph_api.graph_call("#{user1_id}/friends/#{user2_id}", {}, "post", options) &&
149
+ u2_graph_api.graph_call("#{user2_id}/friends/#{user1_id}", {}, "post", options)
72
150
  end
73
151
 
74
- def create_network(network_size, installed = true, permissions = '')
75
- users = (0...network_size).collect { create(installed, permissions) }
152
+ # Create a network of test users, all of whom are friends and have the same permissions.
153
+ #
154
+ # @note this call slows down dramatically the more users you create
155
+ # (test user calls are slow, and more users => more 1-on-1 connections to be made).
156
+ # Use carefully.
157
+ #
158
+ # @param network_size how many users to create
159
+ # @param installed whether the users have installed your app (see {#create})
160
+ # @param permissions what permissions the users have granted (see {#create})
161
+ # @param options (see Koala::Facebook::API#api)
162
+ #
163
+ # @return the list of users created
164
+ def create_network(network_size, installed = true, permissions = '', options = {})
165
+ users = (0...network_size).collect { create(installed, permissions, options) }
76
166
  friends = users.clone
77
167
  users.each do |user|
78
168
  # Remove this user from list of friends
79
169
  friends.delete_at(0)
80
170
  # befriend all the others
81
171
  friends.each do |friend|
82
- befriend(user, friend)
172
+ befriend(user, friend, options)
83
173
  end
84
174
  end
85
175
  return users
86
176
  end
87
-
177
+
178
+ # The Facebook test users management URL for your application.
179
+ def test_user_accounts_path
180
+ @test_user_accounts_path ||= "/#{@app_id}/accounts/test-users"
181
+ end
182
+
183
+ # @private
184
+ # Legacy accessor for before GraphAPI was unified into API
88
185
  def graph_api
89
186
  Koala::Utils.deprecate("the TestUsers.graph_api accessor is deprecated and will be removed in a future version; please use .api instead.")
90
187
  @api
91
188
  end
92
-
93
- protected
94
-
95
- def accounts_path
96
- @accounts_path ||= "/#{@app_id}/accounts/test-users"
97
- end
98
-
99
189
  end # TestUserMethods
100
190
  end # Facebook
101
191
  end # Koala
data/lib/koala/utils.rb CHANGED
@@ -1,10 +1,17 @@
1
1
  module Koala
2
2
  module Utils
3
+
4
+ # @private
5
+ DEPRECATION_PREFIX = "KOALA: Deprecation warning: "
6
+
7
+ # Prints a deprecation message.
8
+ # Each individual message will only be printed once to avoid spamming.
3
9
  def self.deprecate(message)
4
- begin
5
- send(:warn, "KOALA: Deprecation warning: #{message}")
6
- rescue Exception => err
7
- puts "Unable to issue Koala deprecation warning! #{err.message}"
10
+ @posted_deprecations ||= []
11
+ unless @posted_deprecations.include?(message)
12
+ # only include each message once
13
+ Kernel.warn("#{DEPRECATION_PREFIX}#{message}")
14
+ @posted_deprecations << message
8
15
  end
9
16
  end
10
17
  end
data/lib/koala/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Koala
2
- VERSION = "1.2.1"
2
+ VERSION = "1.3.0"
3
3
  end
data/lib/koala.rb CHANGED
@@ -1,121 +1,40 @@
1
- require 'cgi'
1
+ # useful tools
2
2
  require 'digest/md5'
3
-
4
3
  require 'multi_json'
5
4
 
6
- # OpenSSL and Base64 are required to support signed_request
7
- require 'openssl'
8
- require 'base64'
9
-
10
5
  # include koala modules
6
+ require 'koala/api'
11
7
  require 'koala/oauth'
12
- require 'koala/graph_api'
13
- require 'koala/graph_batch_api'
14
- require 'koala/batch_operation'
15
- require 'koala/graph_collection'
16
- require 'koala/rest_api'
17
8
  require 'koala/realtime_updates'
18
9
  require 'koala/test_users'
19
10
 
20
11
  # HTTP module so we can communicate with Facebook
21
12
  require 'koala/http_service'
22
- require 'koala/multipart_request'
23
-
24
- # add KoalaIO class
25
- require 'koala/uploadable_io'
26
13
 
27
14
  # miscellaneous
28
15
  require 'koala/utils'
29
16
  require 'koala/version'
30
17
 
31
18
  module Koala
32
-
33
- module Facebook
34
- # Ruby client library for the Facebook Platform.
35
- # Copyright 2010-2011 Alex Koppel
36
- # Contributors: Alex Koppel, Chris Baclig, Rafi Jacoby, and the team at Context Optional
37
- # http://github.com/arsduo/koala
38
-
39
- # APIs
40
- class API
41
- # initialize with an access token
42
- def initialize(access_token = nil)
43
- @access_token = access_token
44
- end
45
- attr_reader :access_token
46
-
47
- include GraphAPIMethods
48
- include RestAPIMethods
49
-
50
- def api(path, args = {}, verb = "get", options = {}, &error_checking_block)
51
- # Fetches the given path in the Graph API.
52
- args["access_token"] = @access_token || @app_access_token if @access_token || @app_access_token
53
-
54
- # add a leading /
55
- path = "/#{path}" unless path =~ /^\//
56
-
57
- # make the request via the provided service
58
- result = Koala.make_request(path, args, verb, options)
59
-
60
- # Check for any 500 errors before parsing the body
61
- # since we're not guaranteed that the body is valid JSON
62
- # in the case of a server error
63
- raise APIError.new({"type" => "HTTP #{result.status.to_s}", "message" => "Response body: #{result.body}"}) if result.status >= 500
64
-
65
- # parse the body as JSON and run it through the error checker (if provided)
66
- # Note: Facebook sometimes sends results like "true" and "false", which aren't strictly objects
67
- # and cause MultiJson.decode to fail -- so we account for that by wrapping the result in []
68
- body = MultiJson.decode("[#{result.body.to_s}]")[0]
69
- yield body if error_checking_block
70
-
71
- # if we want a component other than the body (e.g. redirect header for images), return that
72
- options[:http_component] ? result.send(options[:http_component]) : body
73
- end
74
- end
75
-
76
- # special enhanced APIs
77
- class GraphBatchAPI < API
78
- include GraphBatchAPIMethods
79
- end
80
-
81
- class RealtimeUpdates
82
- include RealtimeUpdateMethods
83
- end
84
-
85
- class TestUsers
86
- include TestUserMethods
87
- end
88
-
89
- # legacy support for old APIs
90
- class OldAPI < API;
91
- def initialize(*args)
92
- Koala::Utils.deprecate("#{self.class.name} is deprecated and will be removed in a future version; please use the API class instead.")
93
- super
94
- end
95
- end
96
- class GraphAPI < OldAPI; end
97
- class RestAPI < OldAPI; end
98
- class GraphAndRestAPI < OldAPI; end
99
-
100
- # Errors
101
-
102
- class APIError < StandardError
103
- attr_accessor :fb_error_type
104
- def initialize(details = {})
105
- self.fb_error_type = details["type"]
106
- super("#{fb_error_type}: #{details["message"]}")
107
- end
108
- end
109
- end
110
-
19
+ # A Ruby client library for the Facebook Platform.
20
+ # See http://github.com/arsduo/koala/wiki for a general introduction to Koala
21
+ # and the Graph API.
22
+
111
23
  class KoalaError < StandardError; end
112
24
 
113
-
114
- # finally, the few things defined on the Koala module itself
25
+ # Making HTTP requests
115
26
  class << self
27
+ # Control which HTTP service framework Koala uses.
28
+ # Primarily used to switch between the mock-request framework used in testing
29
+ # and the live framework used in real life (and live testing).
30
+ # In theory, you could write your own HTTPService module if you need different functionality,
31
+ # but since the switch to {https://github.com/arsduo/koala/wiki/HTTP-Services Faraday} almost all such goals can be accomplished with middleware.
116
32
  attr_accessor :http_service
117
33
  end
118
34
 
35
+ # @private
36
+ # For current HTTPServices, switch the service as expected.
37
+ # For deprecated services (Typhoeus and Net::HTTP), print a warning and set the default Faraday adapter appropriately.
119
38
  def self.http_service=(service)
120
39
  if service.respond_to?(:deprecated_interface)
121
40
  # if this is a deprecated module, support the old interface
@@ -128,6 +47,7 @@ module Koala
128
47
  end
129
48
  end
130
49
 
50
+ # An convenenient alias to Koala.http_service.make_request.
131
51
  def self.make_request(path, args, verb, options = {})
132
52
  http_service.make_request(path, args, verb, options)
133
53
  end
data/readme.md CHANGED
@@ -6,13 +6,8 @@ Koala
6
6
 
7
7
  * Lightweight: Koala should be as light and simple as Facebook’s own libraries, providing API accessors and returning simple JSON.
8
8
  * Fast: Koala should, out of the box, be quick. Out of the box, we use Facebook's faster read-only servers when possible and if available, the Typhoeus gem to make snappy Facebook requests. Of course, that brings us to our next topic:
9
- * Flexible: Koala should be useful to everyone, regardless of their current configuration. (We support JRuby, Rubinius, and REE as well as vanilla Ruby, and use the Faraday library to provide complete flexibility over how HTTP requests are made.)
10
- * Tested: Koala should have complete test coverage, so you can rely on it. (Our test coverage is complete and can be run against either mocked responses or the live Facebook servers.)
11
-
12
- Facebook Changes on October 1, 2011
13
- ---
14
-
15
- Koala 1.2 supports all of Facebook's new authentication schemes, which were introduced on October 1, 2011. If you have the appropriate calls to get_user_info_from_cookies (apps using the Javascript SDK) and/or parse_signed_params (for Canvas and tab apps), your application should work without a hitch. For more information, see Facebook's [OAuth 2.0 and HTTPS Migration](https://developers.facebook.com/docs/oauth2-https-migration/) guide.
9
+ * Flexible: Koala should be useful to everyone, regardless of their current configuration. We support JRuby, Rubinius, and REE as well as vanilla Ruby (1.8.7, 1.9.2, and 1.9.3), and use the Faraday library to provide complete flexibility over how HTTP requests are made.
10
+ * Tested: Koala should have complete test coverage, so you can rely on it. Our test coverage is complete and can be run against either mocked responses or the live Facebook servers; we're also on [Travis CI](travis-ci.org/arsduo/koala/).
16
11
 
17
12
  Installation
18
13
  ---
@@ -35,7 +30,10 @@ The Graph API is the simple, slick new interface to Facebook's data. Using it w
35
30
  profile = @graph.get_object("me")
36
31
  friends = @graph.get_connections("me", "friends")
37
32
  @graph.put_object("me", "feed", :message => "I am writing on my wall!")
38
-
33
+
34
+ # three-part queries are easy too!
35
+ @graph.get_connection("me", "mutualfriends/#{friend_id}")
36
+
39
37
  # you can even use the new Timeline API
40
38
  # see https://developers.facebook.com/docs/beta/opengraph/tutorial/
41
39
  @graph.put_connections("me", "namespace:action", :object => object_url)
@@ -131,7 +129,7 @@ Koala makes it easy to interact with your applications using the RealtimeUpdates
131
129
  You can do just about anything with your real-time update subscriptions using the RealtimeUpdates class:
132
130
 
133
131
  # Add/modify a subscription to updates for when the first_name or last_name fields of any of your users is changed
134
- @updates.subscribe("user", "first_name, last_name", callback_token, verify_token)
132
+ @updates.subscribe("user", "first_name, last_name", callback_url, verify_token)
135
133
 
136
134
  # Get an array of your current subscriptions (one hash for each object you've subscribed to)
137
135
  @updates.list_subscriptions
@@ -179,6 +177,8 @@ Some resources to help you as you play with Koala and the Graph API:
179
177
  * The <a href="http://groups.google.com/group/koala-users">Koala users group</a> on Google Groups, the place for your Koala and API questions
180
178
  * Facebook's <a href="http://developers.facebook.com/tools/explorer/">Graph API Explorer</a>, where you can play with the Graph API in your browser
181
179
  * The Koala-powered <a href="http://oauth.twoalex.com" target="_blank">OAuth Playground</a>, where you can easily generate OAuth access tokens and any other data needed to test out the APIs or OAuth
180
+ * Follow Koala on <a href="http://www.facebook.com/pages/Koala/315368291823667">Facebook</a> and <a href="https://twitter.com/#!/koala_fb">Twitter</a> for SDK updates and occasional news about Facebook API changes.
181
+
182
182
 
183
183
  Testing
184
184
  -----