fgraph 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History ADDED
@@ -0,0 +1,2 @@
1
+ 0.0.1 - May 9, 2010
2
+ * Initial release
data/License ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Herryanto Siatono
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,136 @@
1
+ = fgraph
2
+
3
+ * http://github.com/jugend/fgraph
4
+
5
+ == Description
6
+
7
+ Facebook Graph Ruby API implementation with Ruby magic (http://graph.facebook.com).
8
+
9
+ == Installation
10
+
11
+ sudo gem install fgraph
12
+
13
+ === Facebook Graph Cheat Sheet
14
+
15
+ sudo gem install cheat
16
+ cheat fbgraph
17
+
18
+ === Single object query
19
+
20
+ # Users: https://graph.facebook.com/btaylor (Bret Taylor)
21
+ FGraph.object('btaylor')
22
+
23
+ # Pages: https://graph.facebook.com/cocacola (Coca-Cola page)
24
+ FGraph.object('cocacola')
25
+
26
+ # Fields selection with metadata
27
+ FGraph.object('btaylor', :fields => 'id,name,picture', :metadata => 1)
28
+
29
+ # Page photos
30
+ FGraph.object('/cocacola/photos')
31
+ FGraph.object_photos('cocacola')
32
+
33
+ # Current user: https://graph.facebook.com/me?access_token=...
34
+ FGraph.me(:access_token => '...')
35
+
36
+ # Current user's friends: https://graph.facebook.com/me/friends?access_token=...
37
+ FGraph.me('friends', :access_token => '...')
38
+ FGraph.me_friends(:access_token => '...')
39
+
40
+ === Multiple objects query
41
+
42
+ # Multiple users select: https://graph.facebook.com?ids=arjun,vernal
43
+ FGraph.objects('arjun', 'vernel')
44
+
45
+ # Filter fields: https://graph.facebook.com?ids=arjun,vernal&fields=id,name,picture
46
+ FGraph.objects('arjun', 'vernel', :fields => 'id,name,picture')
47
+
48
+ === OAuth
49
+
50
+ OAuth authorization URL:
51
+ # https://graph.facebook.com/oauth/authorize?
52
+ # client_id=...&
53
+ # redirect_uri=http://www.example.com/oauth_redirect&
54
+ # scope=publish_stream
55
+ FGraph.oauth_authorize_url('[client id]', 'http://www.example.com/oauth_redirect', :scope =>
56
+ 'publish_stream')
57
+
58
+ OAuth Access Token:
59
+ # https://graph.facebook.com/oauth/access_token?
60
+ # client_id=...&
61
+ # client_secret=...&
62
+ # redirect_uri=http://www.example.com/oauth_redirect&
63
+ # code=...
64
+ FGraph.oauth_access_token('[client id]', '[client secret]',
65
+ :redirect_uri => ''http://www.example.com/oauth_redirect',
66
+ :code => '[authorization code]')
67
+
68
+ OAuth Application Access Token, required to access application anlytics data:
69
+ # https://graph.facebook.com/oauth/access_token?
70
+ # client_id=...&
71
+ # client_secret=...&
72
+ # type=client_cred
73
+ FGraph.oauth_access_token('[client id]', '[client secret]', :type => 'client_cred')
74
+
75
+ === Publish to Facebook Graph
76
+
77
+ # Post to user's feed.
78
+ # curl -F 'access_token=...' \
79
+ # -F 'message=Hello, Arjun. I like this new API.' \
80
+ # https://graph.facebook.com/arjun/feed
81
+ FGraph.publish('arjun/feed', :message => 'Hello, Arjun. I like this n ew API.',
82
+ :access_token => '...')
83
+ FGraph.publish_feed('arjun', :message => '...', :access_token => '... ')
84
+ FGraph.publish_feed('me', ':message => '...', :access_token => '...')
85
+
86
+ === Remove from Facebook Graph
87
+
88
+ # DELETE https://graph.facebook.com/ID?access_token=... HTTP/1.1
89
+ FGraph.remove('[ID]')
90
+ FGraph.remove('[ID]/likes')
91
+ FGraph.remove_likes('[ID]')
92
+
93
+ === Search
94
+
95
+ # https://graph.facebook.com/search?q=watermelon&type=post
96
+ FGraph.search('watermelon', :type => 'post')
97
+ FGraph.search_post('watermelon')
98
+
99
+ === Insights
100
+
101
+ # https://graph.facebook.com/app_id/insights?access_token=...
102
+ FGraph.insights('[app_id]', '[app_access_token]')
103
+
104
+ # https://graph.facebook.com/app_id/insights/application_api_call/day?access_token=...
105
+ FGraph.insights('[app_id]', '[app_access_token]', :metric_path => 'application_api_call/day')
106
+
107
+ === Pagination Options
108
+
109
+ * <tt>limit</tt> - max no of records
110
+ * <tt>offset</tt> - offset
111
+ * <tt>until</tt> - since (a unix timestamp or any date accepted by strtotime, e.g. yesterday)
112
+
113
+ == License
114
+
115
+ (The MIT License)
116
+
117
+ Copyright (c) 2010 Herryanto Siatono http://www.pluitsolutions.com
118
+
119
+ Permission is hereby granted, free of charge, to any person obtaining
120
+ a copy of this software and associated documentation files (the
121
+ 'Software'), to deal in the Software without restriction, including
122
+ without limitation the rights to use, copy, modify, merge, publish,
123
+ distribute, sublicense, and/or sell copies of the Software, and to
124
+ permit persons to whom the Software is furnished to do so, subject to
125
+ the following conditions:
126
+
127
+ The above copyright notice and this permission notice shall be
128
+ included in all copies or substantial portions of the Software.
129
+
130
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
131
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
132
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
133
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
134
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
135
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
136
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ require 'rake'
2
+ require 'jeweler'
3
+
4
+ begin
5
+ Jeweler::Tasks.new do |gem|
6
+ gem.name = "fgraph"
7
+ gem.summary = "Ruby Facebook Graph API"
8
+ gem.description = "Ruby Facebook Graph API"
9
+ gem.email = "herryanto@gmail.com"
10
+ gem.homepage = "http://github.com/jugend/fgraph"
11
+ gem.authors = ["Herryanto Siatono"]
12
+ gem.files = FileList["[A-Z]*", "{examples,lib,test}/**/*"]
13
+
14
+ gem.add_dependency("httparty", "~> 0.5.0")
15
+ # gem.add_dependency("hashie", "~> 0.2.0")
16
+
17
+ gem.add_development_dependency("shoulda", "~> 2.10.0")
18
+ gem.add_development_dependency("jnunemaker-matchy", "~> 0.4.0")
19
+ gem.add_development_dependency("mocha", "~> 0.9.0")
20
+ gem.add_development_dependency("fakeweb", "~> 1.2.0")
21
+ end
22
+ rescue LoadError
23
+ puts "Jeweler not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ Jeweler::GemcutterTasks.new
27
+
28
+ require "rake/testtask"
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << "test"
31
+ test.ruby_opts << "-rubygems"
32
+ test.pattern = "test/**/*_test.rb"
33
+ test.verbose = true
34
+ end
35
+
36
+ task :default => :test
37
+ task :test => :check_dependencies
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 0
5
+ :build:
@@ -0,0 +1,19 @@
1
+ # Retrieve your code by accessing Authorization URL From your browser,
2
+ # it should redirect to 'redirect_uri' with 'code' param.
3
+ # Replace the FACEBOOK_XXX constants accordingly.
4
+ #
5
+ # Authorization URL, access from your browser to get Authorization Code
6
+ # https://graph.facebook.com/oauth/authorize?client_id=878116c4a4a76f25e4beb97ab096cc92&redirect_uri=http%3A%2F%2Fbookjetty.pluitsolutions.com%2F&scope=publish_stream
7
+
8
+ FACEBOOK_APP_ID = '878116c4a4a76f25e4beb97ab096cc92'
9
+ FACEBOOK_APP_SECRET = '41f0e7ee8b6409dce1610de9926477c4'
10
+ FACEBOOK_OAUTH_REDIRECT_URI = 'http://bookjetty.pluitsolutions.com/'
11
+ FACEBOOK_OAUTH_CODE = '2.Dq5RDPHxhsgaeScc_fiigg__.3600.1273831200-756314021|4Eew6iuIg0x69N1d3Cr99gdVGwU.'
12
+ FACEBOOK_OAUTH_SCOPE = ''
13
+
14
+ require 'pp'
15
+ require 'rubygems'
16
+ require File.dirname(__FILE__) + '/../lib/fgraph'
17
+
18
+ pp FGraph.oauth_access_token(FACEBOOK_APP_ID, FACEBOOK_OAUTH_REDIRECT_URI,
19
+ FACEBOOK_APP_SECRET, FACEBOOK_OAUTH_CODE)
@@ -0,0 +1,16 @@
1
+ # Replace FACEBOOK_ACCESS_TOKEN with valid token with publish_stream extended permission
2
+ #
3
+ # Post to user's feed.
4
+ # curl -F 'access_token=...' -F 'message=Hello, Arjun. I like this new API.' https://graph.facebook.com/me/feed
5
+ # curl -F 'access_token=112157085478818|2.AlP5TBjZ9F6wOXPX_V0GTg__.3600.1273777200-756314021|NV7Dnuol59KbQr6W1axv6ZmytaI.' -F 'message=Hello, Arjun. I like this new API.' https://graph.facebook.com/me/feed
6
+ FACEBOOK_ACCESS_TOKEN = '112157085478818|2.Dq5RDPHxhsgaeScc_fiigg__.3600.1273831200-756314021|Tvm41skDwOdGR2O3Lz4owMVz1lM.'
7
+
8
+ require 'rubygems'
9
+ require 'pp'
10
+ require File.dirname(__FILE__) + '/../lib/fgraph'
11
+
12
+ # Post to current user's f eed
13
+ pp FGraph.publish_feed('me', :message => 'Hello. I like this new API.',
14
+ :access_token => FACEBOOK_ACCESS_TOKEN)
15
+
16
+ puts "Message successfully posted."
data/lib/fgraph.rb ADDED
@@ -0,0 +1,321 @@
1
+ require 'httparty'
2
+ require 'cgi'
3
+ require 'oauth2'
4
+ require 'fgraph/client'
5
+
6
+ module FGraph
7
+ include HTTParty
8
+ base_uri 'https://graph.facebook.com'
9
+ format :json
10
+
11
+ # Facebook Error
12
+ class FacebookError < StandardError
13
+ attr_reader :data
14
+
15
+ def initialize(data)
16
+ @data = data
17
+ super("(#{data['type']}) #{data['message']}")
18
+ end
19
+ end
20
+
21
+ class QueryParseError < FacebookError; end
22
+ class GraphMethodError < FacebookError; end
23
+ class OAuthError < FacebookError; end
24
+ class OAuthAccessTokenError < OAuthError; end
25
+
26
+ # Single object query.
27
+ #
28
+ # # Users: https://graph.facebook.com/btaylor (Bret Taylor)
29
+ # FGraph.object('btaylor')
30
+ #
31
+ # # Pages: https://graph.facebook.com/cocacola (Coca-Cola page)
32
+ # FGraph.object('cocacola')
33
+ #
34
+ # # Fields selection with metadata
35
+ # FGraph.object('btaylor', :fields => 'id,name,picture', :metadata => 1)
36
+ #
37
+ # # Page photos
38
+ # FGraph.object('/cocacola/photos')
39
+ # FGraph.object_photos('cocacola')
40
+ #
41
+ def self.object(id, options={})
42
+ perform_get("/#{id}", options)
43
+ end
44
+
45
+ # call-seq:
46
+ # FGraph.objects(id, id)
47
+ # FGraph.objects(id, id, options_hash)
48
+ #
49
+ # Multiple objects query.
50
+ #
51
+ # # Multiple users select: https://graph.facebook.com?ids=arjun,vernal
52
+ # FGraph.objects('arjun', 'vernel')
53
+ #
54
+ # # Filter fields: https://graph.facebook.com?ids=arjun,vernal&fields=id,name,picture
55
+ # FGraph.objects('arjun', 'vernel', :fields => 'id,name,picture')
56
+ #
57
+ def self.objects(*args)
58
+ options = args.last.is_a?(Hash) ? args.pop : {}
59
+ options = options.merge(:ids => args.join(','))
60
+ perform_get("/", options)
61
+ end
62
+
63
+ # call-seq:
64
+ # FGraph.me(category)
65
+ # FGraph.me(category, options_hash)
66
+ #
67
+ # Returns current user object details.
68
+ #
69
+ # <tt>category</tt> - <tt>friends|home|feed|likes|movies|books|notes|photos|videos|events|groups</tt>
70
+ #
71
+ # # Current user: https://graph.facebook.com/me?access_token=...
72
+ # FGraph.me(:access_token => '...')
73
+ #
74
+ # # Current user's friends: https://graph.facebook.com/me/friends?access_token=...
75
+ # FGraph.me('friends', :access_token => '...')
76
+ # FGraph.me_friends(:access_token => '...')
77
+ #
78
+ def self.me(*args)
79
+ options = args.last.is_a?(Hash) ? args.pop : {}
80
+ category = args.shift
81
+
82
+ path = "me"
83
+ path += "/#{category}" unless category.blank?
84
+ self.object(path, options)
85
+ end
86
+
87
+ # Request authorization from Facebok to fetch private data in the profile or permission to publish on a
88
+ # user's behalf. Returns Oauth Authorization URL, redirect to this URL to allow user to authorize your
89
+ # application from Facebook.
90
+ #
91
+ # <tt>client_id</tt> - Facebook API Key
92
+ # <tt>redirect_uri</tt> - Needs to begin with your app's Connect URL. For instance, if your Connect URL
93
+ # is http://www.example.com then your redirect URI could be http://www.example.com/oauth_redirect.
94
+ # <tt>scope (optional)</tt> -
95
+ #
96
+ # ==== Options
97
+ # * <tt>scope</tt> - Extended permission required to fetch private data or request permision to
98
+ # publish to Facebook on a user's behalf.
99
+ # * <tt>display</tt> - Other display type for authentication/authorization form, i.e. popup, touch.
100
+ #
101
+ # # https://graph.facebook.com/oauth/authorize?
102
+ # # client_id=...&
103
+ # # redirect_uri=http://www.example.com/oauth_redirect&
104
+ # # scope=publish_stream
105
+ #
106
+ # FGraph.oauth_authorize_url('[client id]', 'http://www.example.com/oauth_redirect', :scope =>
107
+ # 'publish_stream')
108
+ #
109
+ def self.oauth_authorize_url(client_id, redirect_uri, options={})
110
+ self.format_url('/oauth/authorize', {
111
+ :client_id => client_id,
112
+ :redirect_uri => redirect_uri
113
+ }.merge(options))
114
+ end
115
+
116
+ # Return OAuth access_token. There are two types of access token, user access token and application
117
+ # access token.
118
+ #
119
+ # User access_token requires <tt>code</tt> and and <tt>redirect_uri</tt> options. <tt>code</tt> is
120
+ # the autorization code appended as query string to redirect URI when accessing oauth authorization URL.
121
+ #
122
+ # # https://graph.facebook.com/oauth/access_token?
123
+ # # client_id=...&
124
+ # # client_secret=...&
125
+ # # redirect_uri=http://www.example.com/oauth_redirect&
126
+ # # code=...
127
+ # FGraph.oauth_access_token('[client id]', '[client secret]',
128
+ # :redirect_uri => ''http://www.example.com/oauth_redirect',
129
+ # :code => '[authorization code]')
130
+ #
131
+ # Application access token requires <tt>:type => 'client_cred'</td> option. Used to access application
132
+ # insights data.
133
+ #
134
+ # # https://graph.facebook.com/oauth/access_token?
135
+ # # client_id=...&
136
+ # # client_secret=...&
137
+ # # type=client_cred
138
+ # FGraph.oauth_access_token('[client id]', '[client secret]', :type => 'client_cred')
139
+ #
140
+ def self.oauth_access_token(client_id, client_secret, options={})
141
+ url = self.format_url('/oauth/access_token', {
142
+ :client_id => client_id,
143
+ :client_secret => client_secret
144
+ }.merge(options || {}))
145
+
146
+ response = self.perform_get(url)
147
+ response_hash = {}
148
+ response.split('&').each do |value|
149
+ value_pair = value.split('=')
150
+ response_hash[value_pair[0]] = value_pair[1]
151
+ end
152
+ response_hash
153
+ end
154
+
155
+ # Shortcut to retrieve application access token.
156
+ def self.oauth_app_access_token(client_id, client_secret)
157
+ self.oauth_access_token(client_id, client_secret, :type => 'client_cred')
158
+ end
159
+
160
+ # Publish to Facebook, you would need to be authorized and provide access token.
161
+ #
162
+ # # Post to user's feed.
163
+ # # curl -F 'access_token=...' \
164
+ # # -F 'message=Hello, Arjun. I like this new API.' \
165
+ # # https://graph.facebook.com/arjun/feed
166
+ # FGraph.publish('arjun/feed', :message => 'Hello, Arjun. I like this new API.',
167
+ # :access_token => '...')
168
+ # FGraph.publish_feed('arjun', :message => '...', :access_token => '...')
169
+ # FGraph.publish_feed('me', ':message => '...', :access_token => '...')
170
+ #
171
+ # ==== Options
172
+ #
173
+ # Method Description Options
174
+ # -------------------------------------------------------------------------------------
175
+ # /PROFILE_ID/feed write to the given profile's feed/wall :message, :picture,
176
+ # :link, :name, description
177
+ # /POST_ID/comments comment on the given post :message
178
+ # /POST_ID/likes like the given post none
179
+ # /PROFILE_ID/notes write a note on the given profile :message, :subject
180
+ # /PROFILE_ID/links write a link on the given profile :link, :message
181
+ # /EVENT_ID/attending attend the given event none
182
+ # /EVENT_ID/maybe maybe attend the given event none
183
+ # /EVENT_ID/declined decline the given event none
184
+ #
185
+ def self.publish(id, options={})
186
+ self.perform_post("/#{id}", options)
187
+ end
188
+
189
+ # Delete objects in the graph.
190
+ #
191
+ # # DELETE https://graph.facebook.com/ID?access_token=... HTTP/1.1
192
+ #
193
+ # FGraph.remove('[ID]')
194
+ # FGraph.remove('[ID]/likes')
195
+ # FGraph.remove_likes('[ID]')
196
+ #
197
+ def self.remove(id, options={})
198
+ self.perform_delete("/#{id}", options)
199
+ end
200
+
201
+ # Search over all public objects in the social graph.
202
+ #
203
+ # # https://graph.facebook.com/search?q=watermelon&type=post
204
+ # FGraph.search('watermelon', :type => 'post')
205
+ # FGraph.search_post('watermelon')
206
+ #
207
+ # ==== Options
208
+ # * <tt>type</tt> - <tt>album|event|group|link|note|page|photo|post|status|user|video</tt>
209
+ # * <tt>limit</tt> - max no of records
210
+ # * <tt>offset</tt> - offset
211
+ # * <tt>until</tt> - since (a unix timestamp or any date accepted by strtotime, e.g. yesterday)
212
+ def self.search(query, options={})
213
+ self.perform_get("/search", {
214
+ :q => query
215
+ }.merge(options|| {}))
216
+ end
217
+
218
+ # Download insights data for your application.
219
+ #
220
+ # # https://graph.facebook.com/app_id/insights?access_token=...
221
+ # FGraph.insights('[app_id]', '[app_access_token]')
222
+ #
223
+ # # https://graph.facebook.com/app_id/insights/application_api_call/day?access_token=...
224
+ # FGraph.insights('[app_id]', '[app_access_token]', :metric_path => 'application_api_call/day')
225
+ #
226
+ # ==== Options
227
+ # * <tt>metric_path</tt> - e.g. application_api_calls/day
228
+ # * <tt>since</tt> - since (a unix timestamp or any date accepted by strtotime, e.g. yesterday)
229
+ # * <tt>until</tt> - until (a unix timestamp or any date accepted by strtotime, e.g. yesterday)
230
+ def self.insights(app_id, app_access_token, options={})
231
+ metric_path = options.delete(:metric_path)
232
+
233
+ path = "/#{app_id}/insights"
234
+ path += "/#{metric_path}" if metric_path
235
+
236
+ self.perform_get(path, {
237
+ :access_token => app_access_token
238
+ }.merge(options || {}))
239
+ end
240
+
241
+ def self.perform_get(uri, options = {})
242
+ handle_response(get(uri, {:query => options}))
243
+ end
244
+
245
+ def self.perform_post(uri, options = {})
246
+ handle_response(post(uri, {:body => options}))
247
+ end
248
+
249
+ def self.perform_delete(uri, options = {})
250
+ handle_response(delete(uri, {:body => options}))
251
+ end
252
+
253
+ def self.handle_response(response)
254
+ # Check for error
255
+ return response unless response['error']
256
+
257
+ case response['error']['type']
258
+ when 'QueryParseException'
259
+ raise QueryParseError, response['error']
260
+ when 'GraphMethodException'
261
+ raise GraphMethodError, response['error']
262
+ when 'OAuthException'
263
+ raise OAuthError, response['error']
264
+ when 'OAuthAccessTokenException'
265
+ raise OAuthAccessTokenError, response['error']
266
+ else
267
+ raise FacebookError, response['error']
268
+ end
269
+ end
270
+
271
+ def self.format_url(path, options={})
272
+ url = self.base_uri.dup
273
+ url << path
274
+ unless options.blank?
275
+ url << "?"
276
+
277
+ option_count = 0
278
+
279
+ stringified_options = {}
280
+ options.each do |key, value|
281
+ stringified_options[key.to_s] = value
282
+ end
283
+ options = stringified_options
284
+
285
+ options.each do |option|
286
+ next if option[1].blank?
287
+ url << "&" if option_count > 0
288
+ url << "#{option[0]}=#{CGI.escape(option[1].to_s)}"
289
+ option_count += 1
290
+ end
291
+ end
292
+ url
293
+ end
294
+
295
+ def self.method_missing(name, *args, &block)
296
+ names = name.to_s.split('_')
297
+ super unless names.length > 1
298
+
299
+ case names.shift
300
+ when 'object'
301
+ # object_photos
302
+ self.object("#{args[0]}/#{names[0]}", args[1])
303
+ when 'me'
304
+ # me_photos
305
+ self.me(names[0], args[0])
306
+ when 'publish'
307
+ # publish_feed(id)
308
+ self.publish("#{args[0]}/#{names[0]}", args[1])
309
+ when 'remove'
310
+ # remove_feed(id)
311
+ self.remove("#{args[0]}/#{names[0]}", args[1])
312
+ when 'search'
313
+ # search_user(query)
314
+ options = args[1] || {}
315
+ options[:type] = names[0]
316
+ self.search(args[0], options)
317
+ else
318
+ super
319
+ end
320
+ end
321
+ end
@@ -0,0 +1,111 @@
1
+ require 'oauth2'
2
+
3
+ module FGraph
4
+
5
+ # Facebook proxy class to call Facebook Graph API methods with default options.
6
+ # Please refer to FGraph method documentation for more information.
7
+ class Client
8
+ attr_reader :oauth_client, :client_id, :client_secret, :options
9
+
10
+ # Initialize Client with default options, so options are not required to be passed
11
+ # when calling respective Facebook Graph API methods.
12
+ #
13
+ # ==== Options
14
+ # * <tt>client_id</tt> - Application API key
15
+ # * <tt>client_secret</tt> - Application Secret
16
+ # * <tt>app_id</tt> - Application ID
17
+ # * <tt>access_token</tt> - Access token, required to publish to Facebook Graph or access
18
+ # current user profile.
19
+ # * <tt>app_access_token</tt> - Application access token, required to access Facebook insights.
20
+ # Auto generated if client_id and client_secret option are provided.
21
+ def initialize(options={})
22
+ @options = options
23
+ end
24
+
25
+ def oauth_authorize_url(redirect_uri)
26
+ FGraph.oauth_authorize_url(self.options[:client_id], redirect_uri)
27
+ end
28
+
29
+ def oauth_access_token(redirect_uri, code)
30
+ FGraph.oauth_access_token(self.options[:client_id], self.options[:client_secret],
31
+ :redirect_uri => redirect_uri, :code => code)
32
+ end
33
+
34
+ def oauth_app_access_token
35
+ FGraph.oauth_app_access_token(self.options[:client_id], self.options[:client_secret])
36
+ end
37
+
38
+ def object(id, options={})
39
+ FGraph.object(id, {:access_token => self.options[:access_token]}.merge(options || {}))
40
+ end
41
+
42
+ def objects(*args)
43
+ return if args.blank?
44
+ options = args.last.is_a?(Hash) ? args.pop : {}
45
+ options[:access_token] = self.options[:access_token]
46
+ args << options
47
+
48
+ FGraph.objects(args)
49
+ end
50
+
51
+ def me(*args)
52
+ return if args.blank?
53
+ options = args.last.is_a?(Hash) ? args.pop : {}
54
+ options[:access_token] = self.options[:access_token]
55
+ args << options
56
+
57
+ FGraph.me(args)
58
+ end
59
+
60
+ def publish(id, options={})
61
+ FGraph.publish(id, {
62
+ :access_token => self.options[:access_token]
63
+ }.merge(options || {}))
64
+ end
65
+
66
+ def remove(id, options={})
67
+ FGraph.remove(id, {
68
+ :access_token => self.options[:access_token]
69
+ }.merge(options || {}))
70
+
71
+ end
72
+
73
+ def search(query, options={})
74
+ FGraph.search(query, options)
75
+ end
76
+
77
+ def insights(options={})
78
+ unless self.options[:app_access_token]
79
+ self.options[:app_access_token] = self.oauth_app_access_token
80
+ end
81
+ FGraph.insights(self.options[:app_id], self.options[:app_access_token], options)
82
+ end
83
+
84
+ def method_missing(name, *args, &block)
85
+ names = name.to_s.split('_')
86
+ super unless names.length > 1
87
+
88
+ case names.shift
89
+ when 'object'
90
+ # object_photos
91
+ self.object("#{args[0]}/#{names[0]}", args[1])
92
+ when 'me'
93
+ # me_photos
94
+ self.me(names[0], args[0])
95
+ when 'publish'
96
+ # publish_feed(id)
97
+ self.publish("#{args[0]}/#{names[0]}", args[1])
98
+ when 'remove'
99
+ # remove_feed(id)
100
+ self.remove("#{args[0]}/#{names[0]}", args[1])
101
+ when 'search'
102
+ # search_user(query)
103
+ options = args[1] || {}
104
+ options[:type] = names[0]
105
+ self.search(args[0], options)
106
+ else
107
+ super
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,155 @@
1
+ require 'test_helper'
2
+
3
+ class ClientTest < Test::Unit::TestCase
4
+ FACEBOOK_API_KEY = '878116c4a4b79f25e4beb97ab096cc92'
5
+ FACEBOOK_APP_SECRET = '41f0e7ee8b6501dca1610de9926477c4'
6
+ FACEBOOK_APP_ID = '112157085578818'
7
+ FACEBOOK_OAUTH_REDIRECT_URI = 'http://www.example.com/oauth_redirect'
8
+ FACEBOOK_OAUTH_CODE = '2.0eXhebBSDTpoe08qIaocNQ__.3600.1273748400-503153225|caqygNb5Gobz6lpj3HXjlthDxds.'
9
+ FACEBOOK_OAUTH_ACCESS_TOKEN = "115187085478818|rDIv_5zgjCSM_fWBv5Z-lQr5gFk."
10
+ FACEBOOK_OAUTH_APP_ACCESS_TOKEN = "112167085478818|rDIv_5zgjCSM_fWBv5Z-lQr5gFk."
11
+
12
+ def fb_client
13
+ FGraph::Client.new(
14
+ :client_id => FACEBOOK_API_KEY,
15
+ :client_secret => FACEBOOK_APP_SECRET,
16
+ :access_token => FACEBOOK_OAUTH_ACCESS_TOKEN
17
+ )
18
+ end
19
+
20
+ context "FGraph::Client#oauth_authorize_url" do
21
+ should "call FGraph.oauth_authorize_url with :client_id option" do
22
+ FGraph.expects(:oauth_authorize_url).with(FACEBOOK_API_KEY, FACEBOOK_OAUTH_REDIRECT_URI)
23
+ fb_client.oauth_authorize_url(FACEBOOK_OAUTH_REDIRECT_URI)
24
+ end
25
+ end
26
+
27
+ context "FGraph::Client#oauth_access_token" do
28
+ should "call FGraph.oauth_access_token with :client_id and :client_secret options" do
29
+ FGraph.expects(:oauth_access_token).with(FACEBOOK_API_KEY, FACEBOOK_APP_SECRET,
30
+ :redirect_uri => FACEBOOK_OAUTH_REDIRECT_URI, :code => FACEBOOK_OAUTH_CODE)
31
+
32
+ fb_client.oauth_access_token(FACEBOOK_OAUTH_REDIRECT_URI, FACEBOOK_OAUTH_CODE)
33
+ end
34
+ end
35
+
36
+ context "FGraph::Client#object" do
37
+ should "call FGraph.object with :access_token option" do
38
+ object_id = '12345'
39
+ FGraph.expects(:object).with(object_id,
40
+ :access_token => FACEBOOK_OAUTH_ACCESS_TOKEN,
41
+ :fields => 'user_photos'
42
+ )
43
+
44
+ fb_client.object(object_id, :fields => 'user_photos')
45
+ end
46
+
47
+ should "support #object_[category] method" do
48
+ client = fb_client
49
+ client.expects(:object).with('arun/photos', {:limit => 5})
50
+ client.object_photos('arun', {:limit => 5})
51
+ end
52
+ end
53
+
54
+ context "FGraph::Client#objects" do
55
+ should "call FGraph.objects with :access_token option" do
56
+ FGraph.expects(:objects).with(['1', '2', {
57
+ :access_token => FACEBOOK_OAUTH_ACCESS_TOKEN,
58
+ :fields => 'user_photos'
59
+ }])
60
+
61
+ fb_client.objects('1', '2', :fields => 'user_photos')
62
+ end
63
+ end
64
+
65
+ context "FGraph::Client#me" do
66
+ should "call FGraph.me with :access_token option" do
67
+ FGraph.expects(:me).with([{
68
+ :access_token => FACEBOOK_OAUTH_ACCESS_TOKEN,
69
+ :fields => 'user_photos'
70
+ }])
71
+
72
+ fb_client.me(:fields => 'user_photos')
73
+ end
74
+
75
+ should "support #me_[category] method" do
76
+ client = fb_client
77
+ client.expects(:me).with('photos', {:limit => 5})
78
+ client.me_photos(:limit => 5)
79
+ end
80
+ end
81
+
82
+ context "FGraph::Client#publish" do
83
+ should "call FGraph.publish with :access_token option" do
84
+ id = '1'
85
+ FGraph.expects(:publish).with(id, {
86
+ :access_token => FACEBOOK_OAUTH_ACCESS_TOKEN,
87
+ :message => 'hello'
88
+ })
89
+
90
+ fb_client.publish(id, :message => 'hello')
91
+ end
92
+
93
+ should "support publish_[category] method" do
94
+ client = fb_client
95
+ client.expects(:publish).with('me/feed', {:limit => 5})
96
+ client.publish_feed('me', {:limit => 5})
97
+ end
98
+ end
99
+
100
+ context "FGraph::Client#remove" do
101
+ should "call FGraph.remove with :access_token option" do
102
+ id = '1'
103
+ FGraph.expects(:remove).with(id, {
104
+ :access_token => FACEBOOK_OAUTH_ACCESS_TOKEN
105
+ })
106
+
107
+ fb_client.remove(id)
108
+ end
109
+
110
+ should "support remove_[category] method" do
111
+ client = fb_client
112
+ client.expects(:remove).with('12345/likes', {:limit => 5})
113
+ client.remove_likes('12345', :limit => 5)
114
+ end
115
+ end
116
+
117
+ context "FGraph::Client#search" do
118
+ should "call FGraph.search with options" do
119
+ query = 'watermelon'
120
+ options = {:limit => 5}
121
+ FGraph.expects(:search).with(query, options)
122
+
123
+ fb_client.search(query, options)
124
+ end
125
+
126
+ should "support dynamic method search_[type] method" do
127
+ client = fb_client
128
+ client.expects(:search).with('watermelon', {
129
+ :type => 'post'
130
+ })
131
+ client.search_post('watermelon')
132
+ end
133
+ end
134
+
135
+ context "FGraph::Client#insights" do
136
+ should "auto populate :app_id and :oauth_app_access_token" do
137
+ client = fb_client
138
+ client.options[:app_id] = FACEBOOK_APP_ID
139
+ client.options[:app_access_token] = FACEBOOK_OAUTH_APP_ACCESS_TOKEN
140
+
141
+ FGraph.expects(:insights).with(FACEBOOK_APP_ID, FACEBOOK_OAUTH_APP_ACCESS_TOKEN, {})
142
+ client.insights
143
+ end
144
+
145
+ should "auto retrieve :oauth_app_access_token option" do
146
+ client = fb_client
147
+
148
+ client.expects(:oauth_app_access_token).returns(FACEBOOK_OAUTH_APP_ACCESS_TOKEN)
149
+ FGraph.expects(:insights).with(nil, FACEBOOK_OAUTH_APP_ACCESS_TOKEN, {
150
+ :metric_path => 'application_api_calls/day'
151
+ })
152
+ client.insights(:metric_path => 'application_api_calls/day')
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,236 @@
1
+ require 'test_helper'
2
+
3
+ class FGraphTest < Test::Unit::TestCase
4
+ FACEBOOK_API_KEY = '878116c4a4b79f25e4beb97ab096cc92'
5
+ FACEBOOK_APP_SECRET = '41f0e7ee8b6501dca1610de9926477c4'
6
+ FACEBOOK_APP_ID = '112157085578818'
7
+ FACEBOOK_OAUTH_REDIRECT_URI = 'http://www.example.com/oauth_redirect'
8
+ FACEBOOK_OAUTH_CODE = '2.0eXhebBSDTpoe08qIaocNQ__.3600.1273748400-503153225|caqygNb5Gobz6lpj3HXjlthDxds.'
9
+ FACEBOOK_OAUTH_ACCESS_TOKEN = "115187085478818|rDIv_5zgjCSM_fWBv5Z-lQr5gFk."
10
+ FACEBOOK_OAUTH_APP_ACCESS_TOKEN = "112167085478818|rDIv_5zgjCSM_fWBv5Z-lQr5gFk."
11
+
12
+ context "FGraph.object" do
13
+ should "return object hash" do
14
+ stub_get('/cocacola', 'object_cocacola.json')
15
+ object = FGraph.object('cocacola')
16
+
17
+ object.should_not be_nil
18
+ object['name'].should == 'Coca-Cola'
19
+ end
20
+
21
+ should "call handle_response" do
22
+ stub_get('/cocacola', 'object_cocacola.json')
23
+ FGraph.expects(:handle_response).once
24
+ object = FGraph.object('cocacola')
25
+ end
26
+
27
+ should "parse options into get options" do
28
+ options = {:fields => 'id,name,picture'}
29
+ FGraph.expects(:perform_get).with('/cocacola', options)
30
+ FGraph.object('cocacola', options)
31
+ end
32
+ end
33
+
34
+ context "FGraph.objects" do
35
+ should "call perform_get with ids and query options" do
36
+ options = {:fields => 'id,name'}
37
+ FGraph.expects(:perform_get).with('/', options.merge(:ids => 'herry,john'))
38
+ FGraph.objects('herry', 'john', options)
39
+ end
40
+ end
41
+
42
+ context "FGraph.me" do
43
+ access_token = {:access_token => FACEBOOK_OAUTH_ACCESS_TOKEN}
44
+
45
+ should "get object with /me path" do
46
+ FGraph.expects(:object).with('me', access_token)
47
+ FGraph.me(access_token)
48
+ end
49
+
50
+ should "get object with /me/likes path" do
51
+ FGraph.expects(:object).with('me/likes', access_token)
52
+ FGraph.me('likes', access_token)
53
+ end
54
+ end
55
+
56
+ context "FGraph.oauth_authorize_url" do
57
+ should "should call format_url with appropriate hash" do
58
+ FGraph.expects(:format_url).with('/oauth/authorize', {
59
+ :client_id => FACEBOOK_API_KEY,
60
+ :redirect_uri => FACEBOOK_OAUTH_REDIRECT_URI
61
+ })
62
+
63
+ FGraph.oauth_authorize_url(FACEBOOK_API_KEY, FACEBOOK_OAUTH_REDIRECT_URI)
64
+ end
65
+
66
+ should "should call format_url with options" do
67
+ FGraph.expects(:format_url).with('/oauth/authorize', {
68
+ :client_id => FACEBOOK_API_KEY,
69
+ :redirect_uri => FACEBOOK_OAUTH_REDIRECT_URI,
70
+ :scope => 'user_photos'
71
+ })
72
+
73
+ FGraph.oauth_authorize_url(FACEBOOK_API_KEY, FACEBOOK_OAUTH_REDIRECT_URI,
74
+ :scope => 'user_photos')
75
+ end
76
+ end
77
+
78
+ context "FGraph.oauth_access_token" do
79
+ should "return user access token and expires" do
80
+ stub_get(FGraph.format_url('/oauth/access_token', {
81
+ :client_id => FACEBOOK_API_KEY,
82
+ :client_secret => FACEBOOK_APP_SECRET,
83
+ :redirect_uri => FACEBOOK_OAUTH_REDIRECT_URI,
84
+ :code => FACEBOOK_OAUTH_CODE
85
+ }), 'access_token.txt')
86
+
87
+ token = FGraph.oauth_access_token(FACEBOOK_API_KEY, FACEBOOK_APP_SECRET,
88
+ :redirect_uri => FACEBOOK_OAUTH_REDIRECT_URI,
89
+ :code => FACEBOOK_OAUTH_CODE)
90
+
91
+ token['access_token'].should == 'thisisanaccesstoken'
92
+ token['expires'].should == '4000'
93
+ end
94
+ end
95
+
96
+ context "FGraph.publish" do
97
+ options = { :message => 'test message'}
98
+
99
+ should "call perform_post" do
100
+ FGraph.expects(:perform_post).with("/me/feed", options)
101
+ FGraph.publish('me/feed', options)
102
+ end
103
+
104
+ should "have publish_[category] method" do
105
+ FGraph.expects(:publish).with('me/feed', options)
106
+ FGraph.publish_feed('me', options)
107
+ end
108
+ end
109
+
110
+ context "FGraph.delete" do
111
+ options = {}
112
+
113
+ should "call perform_delete" do
114
+ FGraph.expects(:perform_delete).with('/12345', options)
115
+ FGraph.remove('12345', options)
116
+ end
117
+
118
+ should "support remove_[category] method" do
119
+ FGraph.expects(:remove).with('12345/likes', options)
120
+ FGraph.remove_likes('12345', options)
121
+ end
122
+ end
123
+
124
+ context "FGraph.search" do
125
+ should "call perform_get('/search')" do
126
+ FGraph.expects(:perform_get).with('/search', {
127
+ :q => 'watermelon',
128
+ :type => 'post'
129
+ })
130
+
131
+ FGraph.search('watermelon', :type => 'post')
132
+ end
133
+
134
+ should "support dynamic method search_[type] method" do
135
+ FGraph.expects(:search).with('watermelon', {
136
+ :type => 'post'
137
+ })
138
+
139
+ FGraph.search_post('watermelon')
140
+ end
141
+ end
142
+
143
+ context "Facebook.insights" do
144
+ should "call perform_get('/[app_id]/insights')" do
145
+ FGraph.expects(:perform_get).with("/#{FACEBOOK_APP_ID}/insights", {
146
+ :access_token => FACEBOOK_OAUTH_APP_ACCESS_TOKEN
147
+ })
148
+
149
+ FGraph.insights(FACEBOOK_APP_ID, FACEBOOK_OAUTH_APP_ACCESS_TOKEN)
150
+ end
151
+
152
+ should "process :metric_path option" do
153
+ FGraph.expects(:perform_get).with("/#{FACEBOOK_APP_ID}/insights/application_api_call/day", {
154
+ :access_token => FACEBOOK_OAUTH_APP_ACCESS_TOKEN
155
+ })
156
+
157
+ FGraph.insights(FACEBOOK_APP_ID, FACEBOOK_OAUTH_APP_ACCESS_TOKEN, {
158
+ :metric_path => 'application_api_call/day'
159
+ })
160
+ end
161
+ end
162
+
163
+ context "FGraph.method_missing" do
164
+ options = options = {:filter => 'id,name,picture'}
165
+
166
+ should "auto map object_[category] method" do
167
+ FGraph.expects(:object).with('arun/photos', options)
168
+ FGraph.object_photos('arun', options)
169
+ end
170
+
171
+ should "auto map me_[category] method" do
172
+ FGraph.expects(:me).with('photos', options)
173
+ FGraph.me_photos(options)
174
+ end
175
+
176
+ should "raise no method error if missing method name does not start with object_ or me_" do
177
+ lambda do
178
+ FGraph.xyz_photos
179
+ end.should raise_error(NoMethodError)
180
+ end
181
+ end
182
+
183
+ context "FGraph.format_url" do
184
+ should "return URL without query string" do
185
+ formatted_url = FGraph.format_url('/test')
186
+ formatted_url.should == "https://graph.facebook.com/test"
187
+ end
188
+
189
+ should "return URL with query string with escaped value" do
190
+ formatted_url = FGraph.format_url('/test', {:username => 'john lim'})
191
+ formatted_url.should == "https://graph.facebook.com/test?username=john+lim"
192
+ end
193
+
194
+ should "return URL with multiple options" do
195
+ formatted_url = FGraph.format_url('/test', {:username => 'john', :age => 20})
196
+ formatted_url.should =~ /username=john/
197
+ formatted_url.should =~ /age=20/
198
+ formatted_url.should =~ /&/
199
+ end
200
+
201
+ should "return URL without empty options" do
202
+ formatted_url = FGraph.format_url('/test', {:username => 'john', :age => nil})
203
+ formatted_url.should == "https://graph.facebook.com/test?username=john"
204
+ end
205
+ end
206
+
207
+ context "FGraph.handle_response" do
208
+ should "raise QueryParseError" do
209
+ lambda do
210
+ object = FGraph.handle_response(response_error('QueryParseException'))
211
+ end.should raise_error(FGraph::QueryParseError)
212
+ end
213
+
214
+ should "raise GraphMethodError" do
215
+ lambda do
216
+ object = FGraph.handle_response(response_error('GraphMethodException'))
217
+ end.should raise_error(FGraph::GraphMethodError)
218
+ end
219
+
220
+ should "raise OAuthError" do
221
+ lambda do
222
+ object = FGraph.handle_response(response_error('OAuthException'))
223
+ end.should raise_error(FGraph::OAuthError)
224
+ end
225
+
226
+ should "raise OAuthAccessTokenError" do
227
+ lambda do
228
+ object = FGraph.handle_response(response_error('OAuthAccessTokenException'))
229
+ end.should raise_error(FGraph::OAuthAccessTokenError)
230
+ end
231
+ end
232
+
233
+ def response_error(type, msg=nil)
234
+ {'error' => { 'type' => type, 'message' => msg}}
235
+ end
236
+ end
@@ -0,0 +1 @@
1
+ access_token=thisisanaccesstoken&expires=4000
@@ -0,0 +1,10 @@
1
+ {
2
+ "id": "40796308305",
3
+ "name": "Coca-Cola",
4
+ "picture": "http://profile.ak.fbcdn.net/object3/1853/100/s40796308305_2334.jpg",
5
+ "link": "http://www.facebook.com/coca-cola",
6
+ "category": "Consumer_products",
7
+ "username": "coca-cola",
8
+ "products": "Coca-Cola is the most popular and biggest-selling soft drink in history, as well as the best-known product in the world.\n\nCreated in Atlanta, Georgia, by Dr. John S. Pemberton, Coca-Cola was first offered as a fountain beverage by mixing Coca-Cola syrup with carbonated water. Coca-Cola was introduced in 1886, patented in 1887, registered as a trademark in 1893 and by 1895 it was being sold in every state and territory in the United States. In 1899, The Coca-Cola Company began franchised bottling operations in the United States.\n\nCoca-Cola might owe its origins to the United States, but its popularity has made it truly universal. Today, you can find Coca-Cola in virtually every part of the world.",
9
+ "fan_count": 5445797
10
+ }
@@ -0,0 +1,34 @@
1
+ require 'test/unit'
2
+ require 'shoulda'
3
+ require 'matchy'
4
+ require 'mocha'
5
+ require 'fakeweb'
6
+ require 'pp'
7
+
8
+ # FakeWeb.allow_net_connect = true
9
+ # FakeWeb.allow_net_connect = false
10
+
11
+ require File.dirname(__FILE__) + '/../lib/fgraph'
12
+
13
+ def stub_get(url, filename, status=nil)
14
+ options = {:body => read_fixture(filename)}
15
+ options.merge!({:status => status}) unless status.nil?
16
+ FakeWeb.register_uri(:get, graph_url(url), options)
17
+ end
18
+
19
+ def stub_post(url, filename)
20
+ FakeWeb.register_uri(:post, graph_url(url), :body => read_fixture(filename))
21
+ end
22
+
23
+ def stub_put(url, filename)
24
+ FakeWeb.register_uri(:put, graph_url(url), :body => read_fixture(filename))
25
+ end
26
+
27
+ def read_fixture(filename)
28
+ return "" if filename == ""
29
+ File.read(File.dirname(__FILE__) + "/fixtures/" + filename)
30
+ end
31
+
32
+ def graph_url(url)
33
+ url =~ /^http/ ? url : "http://graph.facebook.com#{url}"
34
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fgraph
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Herryanto Siatono
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-20 00:00:00 +08:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: httparty
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 5
30
+ - 0
31
+ version: 0.5.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: shoulda
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 2
43
+ - 10
44
+ - 0
45
+ version: 2.10.0
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: jnunemaker-matchy
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ - 4
58
+ - 0
59
+ version: 0.4.0
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: mocha
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ - 9
72
+ - 0
73
+ version: 0.9.0
74
+ type: :development
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: fakeweb
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 1
85
+ - 2
86
+ - 0
87
+ version: 1.2.0
88
+ type: :development
89
+ version_requirements: *id005
90
+ description: Ruby Facebook Graph API
91
+ email: herryanto@gmail.com
92
+ executables: []
93
+
94
+ extensions: []
95
+
96
+ extra_rdoc_files:
97
+ - README.rdoc
98
+ files:
99
+ - History
100
+ - License
101
+ - README.rdoc
102
+ - Rakefile
103
+ - VERSION.yml
104
+ - examples/get_access_token.rb
105
+ - examples/publish_feed.rb
106
+ - lib/fgraph.rb
107
+ - lib/fgraph/client.rb
108
+ - test/fgraph/client_test.rb
109
+ - test/fgraph_test.rb
110
+ - test/fixtures/access_token.txt
111
+ - test/fixtures/object_cocacola.json
112
+ - test/test_helper.rb
113
+ has_rdoc: true
114
+ homepage: http://github.com/jugend/fgraph
115
+ licenses: []
116
+
117
+ post_install_message:
118
+ rdoc_options:
119
+ - --charset=UTF-8
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ requirements: []
137
+
138
+ rubyforge_project:
139
+ rubygems_version: 1.3.6
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: Ruby Facebook Graph API
143
+ test_files:
144
+ - test/fgraph/client_test.rb
145
+ - test/fgraph_test.rb
146
+ - test/test_helper.rb
147
+ - examples/get_access_token.rb
148
+ - examples/publish_feed.rb