fgraph 0.1.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.
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