rfacebook 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,117 +1,8 @@
1
- ============================== FACEBOOK RAILS CONTROLLER EXTENSIONS NOTES ==============================
1
+ ============================== DOCUMENTATION ==============================
2
2
 
3
- Rails Applications:
4
-
5
- First, set up your Facebook Developer account properly. By properly,
6
- I mean that you need to set your callback URL to be the root of your
7
- Rails application. For example:
8
-
9
- Callback URL >>> http://www.mycrazywebsite.com/ ***NOTE: trailing slash is necessary
10
- Canvas Page URL >>> http://apps.facebook.com/mycrazywebsite
11
-
12
- Then, whenever a user visits
13
-
14
- http://apps.facebook.com/mycrazywebsite/someRailsController/someAction
15
-
16
- ...the Facebook API will call:
17
-
18
- http://www.mycrazywebsite.com/someRailsController/someAction
19
-
20
-
21
- You can get this behavior by installing the new RFacebook gem. After
22
- installing the gem, make your ApplicationController look like this:
23
-
24
- require "facebook_rails_controller_extensions"
25
-
26
- class ApplicationController < ActionController::Base
27
-
28
- # additions to integrate Facebook into controllers
29
- include RFacebook::RailsControllerExtensions
30
-
31
- def facebook_api_key
32
- return "YOUR API KEY HERE"
33
- end
34
-
35
- def facebook_api_secret
36
- return "YOUR API SECRET HERE"
37
- end
38
-
39
- end
40
-
41
- You will have access to 2 new items in your controllers:
42
-
43
- (1) "fbsession"
44
- Contains a FacebookWebSession. Will return false for "is_valid?" if you haven't forced the user to log in.
45
-
46
-
47
- (2) "fbparams"
48
- Contains all the params that are prefixed with "fb_sig_". You shouldn't ever *really* need this, but its there just in case.
49
-
50
-
51
- And, you have a few new filters to try out:
52
-
53
- (1) require_facebook_login
54
- (2) require_facebook_install
55
-
56
- For example, one of my Rails controllers looks like this:
57
-
58
- class FacebookController < ApplicationController
59
-
60
- before_filter :require_facebook_install # require users to install the application (less intrusive is to require_facebook_login)
61
-
62
- def index
63
- xml = fbsession.users_getInfo(:uids => [fbsession.session_user_id], :fields => ["first_name", "last_name"])
64
- @firstName = xml.at("first_name").inner_html
65
- @lastName = xml.at("last_name").inner_html
66
- end
67
-
68
-
69
- end
70
-
71
-
72
-
73
- ============================== FACEBOOK PLATFORM NOTES ==============================
74
-
75
-
76
- ============================== IMPORTANT NOTES ==============================
77
-
78
-
79
- ** THIS IS ESPECIALLY IMPORTANT FOR PEOPLE WHO USED THE OLD CLIENT WHEN IT WAS CALLED "RBook" **
80
-
81
- [1] The RBook name was already taken, so now you need to change any "RBook" references to "RFacebook"
82
-
83
- [2] The desktop app login process is much simpler now:
84
-
85
- fbsession = RFacebook::FacebookDesktopSession.new(APIKEY, APISECRET)
86
- puts fbsession.get_login_url # tell the user to login at this url
87
- # ...after the user logs in...
88
- fbsession.activate
89
-
90
- [3] The "init_with_token" method is now "activate_with_token" (it is a little less confusing with this naming)
91
-
92
- [4] A helpful "NotActivatedException" will be raised if you forget to activate your session in one of the following ways:
93
-
94
- Web: you must call either "activate_with_token" or "activate_with_previous_session"
95
- Desktop: you must call either "activate" or "activate_with_previous_session"
96
-
97
- [5] Infinite sessions are now supported (web and desktop)...
98
-
99
- Web:
100
-
101
- (a) Save the session key to a file or something
102
- (i.e. "keyToSave = fbsession.session_key")
103
-
104
- (b) Normally, you would redirect the user to "get_login_url" and then call "activate_with_token" after the callback.
105
- With an infinite session, skip these two steps and call "fbsession.activate_with_previous_session(keyToSave)" instead.
106
-
107
- Desktop:
108
-
109
- (a) Save the session key and session secret to a file or something
110
- (i.e. "keyToSave = fbsession.session_key" and "secretToSave = fbsession.session_secret")
111
-
112
- (b) Normally, you would redirect the user to "get_login_url" and then call "activate".
113
- With an infinite session, skip these two steps and call "fbsession.activate_with_previous_session(keyToSave, secretToSave)" instead.
3
+ Please see the RFacebook homepage for usage information and other help.
114
4
 
5
+ http://rfacebook.rubyforge.org
115
6
 
116
7
 
117
8
  ============================== LICENSE ==============================
@@ -153,8 +153,8 @@ class FacebookWebSession < FacebookSession
153
153
  # key - the session key to use
154
154
  def activate_with_previous_session(key, uid=nil, expires=nil)
155
155
 
156
- # TODO: what is a good way to handle expiration?
157
- # low priority since the API will give an error code for me...
156
+ # set the expiration
157
+ @session_expires = expires
158
158
 
159
159
  # set the session key
160
160
  @session_key = key
data/lib/facepricot.rb CHANGED
@@ -81,6 +81,7 @@ module RFacebook
81
81
 
82
82
  def initialize(xml)
83
83
  @doc = Hpricot.XML(xml)
84
+ @raw_xml = xml
84
85
  end
85
86
 
86
87
  def method_missing(methodSymbol, *params)
@@ -99,6 +100,10 @@ module RFacebook
99
100
  return FacepricotChain.new(@doc.containers[0])
100
101
  end
101
102
 
103
+ def raw_xml
104
+ return @raw_xml
105
+ end
106
+
102
107
  def to_s
103
108
  return @doc.containers[0].inner_html
104
109
  end
@@ -110,7 +115,6 @@ module RFacebook
110
115
  include FacepricotChaining
111
116
 
112
117
  def initialize(hpricotDoc)
113
- # TODO: does this fix the Hpricot HTML entity escaping problem?
114
118
  super(hpricotDoc.inner_html.gsub("&amp;", "&"))
115
119
  @doc = hpricotDoc
116
120
  end
@@ -29,7 +29,6 @@
29
29
 
30
30
  require "facebook_web_session"
31
31
  require "rfacebook_on_rails/status_manager"
32
- require "rfacebook_on_rails/templates/debug_panel"
33
32
 
34
33
  module RFacebook
35
34
  module Rails
@@ -46,51 +45,58 @@ module RFacebook
46
45
  # SECTION: Template Methods (must be implemented by concrete subclass)
47
46
 
48
47
  def facebook_api_key
49
- raise APIKeyNeededStandardError
48
+ raise APIKeyNeededStandardError, "RFACEBOOK ERROR: when using the RFacebook on Rails plugin, please be sure that you have a facebook.yml file with 'key' defined"
50
49
  end
51
50
 
52
51
  def facebook_api_secret
53
- raise APISecretNeededStandardError
52
+ raise APISecretNeededStandardError, "RFACEBOOK ERROR: when using the RFacebook on Rails plugin, please be sure that you have a facebook.yml file with 'secret' defined"
54
53
  end
55
54
 
56
55
  def facebook_canvas_path
57
- raise APICanvasPathNeededStandardError
56
+ raise APICanvasPathNeededStandardError, "RFACEBOOK ERROR: when using the RFacebook on Rails plugin, please be sure that you have a facebook.yml file with 'canvas_path' defined"
58
57
  end
59
58
 
60
59
  def facebook_callback_path
61
- raise APICallbackNeededStandardError
60
+ raise APICallbackNeededStandardError, "RFACEBOOK ERROR: when using the RFacebook on Rails plugin, please be sure that you have a facebook.yml file with 'callback_path' defined"
62
61
  end
63
62
 
64
63
  def finish_facebook_login
65
- raise APIFinisherNeededStandardError
64
+ raise APIFinisherNeededStandardError, "RFACEBOOK ERROR: in an external Facebook application, you should define finish_facebook_login in your controller (often this is used to redirect to a 'login success' page, but it can also simply do nothing)"
66
65
  end
67
66
 
68
67
 
69
68
 
70
69
  # SECTION: Special Variables
71
70
 
71
+ # Function: fbparams
72
+ # Accessor for all params beginning with "fb_sig_"
73
+ #
74
+ # Returns:
75
+ # A Hash of those parameters, with the fb_sig_ stripped from the keys
72
76
  def fbparams
73
77
 
74
- dup_params = (self.params || {}).dup
75
-
76
78
  # try to get fbparams from the params hash
77
79
  if (!@fbparams || @fbparams.length <= 0)
80
+ dup_params = (self.params || {}).dup
78
81
  @fbparams = rfacebook_session_holder.get_fb_sig_params(dup_params)
79
82
  end
80
83
 
81
84
  # else, try to get fbparams from the cookies hash
82
- # TODO: we don't write anything into the cookie, so this is kind of pointless right now
83
- if (@fbparams.length <= 0)
84
- @fbparams = rfacebook_session_holder.get_fb_sig_params(cookies)
85
+ if (!@fbparams || @fbparams.length <= 0)
86
+ dup_cookies = (self.cookies || {}).dup
87
+ @fbparams = rfacebook_session_holder.get_fb_sig_params(dup_cookies)
85
88
  end
86
-
87
- # TODO: fb_sig_params now includes all friend ids by default, so we can avoid an API call to friends.get
88
- # we should extend FacebookWebSession for Rails to make this optimization
89
-
89
+
90
90
  return @fbparams
91
91
 
92
92
  end
93
93
 
94
+ # Function: fbsession
95
+ # Accessor for a FacebookWebSession that has been activated, either in the Canvas
96
+ # (via fb_sig parameters) or in an external app (via an auth_token).
97
+ #
98
+ # Returns:
99
+ # A FacebookWebSession. You may want to check is_valid? before using it.
94
100
  def fbsession
95
101
 
96
102
  # if we are in the canvas, iframe, or mock ajax, we should be able to activate the session here
@@ -132,11 +138,11 @@ module RFacebook
132
138
  end
133
139
 
134
140
  def in_facebook_canvas?
135
- return (params["fb_sig_in_canvas"] != nil)
141
+ return (params["fb_sig_in_canvas"] != nil)# and params["fb_sig_in_canvas"] == "1")
136
142
  end
137
143
 
138
144
  def in_facebook_frame?
139
- return (params["fb_sig_in_iframe"] != nil or params["fb_sig_in_canvas"] != nil)
145
+ return (params["fb_sig_in_iframe"] != nil)# and params["fb_sig_in_iframe"] == "1")
140
146
  end
141
147
 
142
148
  def in_mock_ajax?
@@ -144,23 +150,38 @@ module RFacebook
144
150
  end
145
151
 
146
152
  def in_external_app?
153
+ # FIXME: once you click away in an iframe app, you are considered to be an external app
154
+ # TODO: read up on the RFacebook hacks for avoiding nested iframes
147
155
  return (!params[:fb_sig] and !in_facebook_frame?)
148
156
  end
149
157
 
158
+ def added_facebook_application?
159
+ return fbparams["added"].to_i == 1
160
+ end
161
+
150
162
  # SECTION: before_filters
151
163
 
152
164
  def handle_facebook_login
153
-
154
- if (!in_facebook_canvas? and !rfacebook_session_holder.is_valid?)
165
+
166
+ if !in_facebook_canvas?
155
167
 
156
168
  if params["auth_token"]
157
169
 
158
170
  # activate with the auth token
159
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: creating a new Facebook session from auth_token"
160
- rfacebook_session_holder.activate_with_token(params["auth_token"])
171
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: attempting to create a new Facebook session from auth_token"
172
+ staleToken = false
173
+ begin
174
+
175
+ # try to use the auth_token
176
+ rfacebook_session_holder.activate_with_token(params["auth_token"])
177
+
178
+ rescue StandardError => e
179
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: Tried to use a stale auth_token"
180
+ staleToken = true
181
+ end
161
182
 
162
183
  # template method call upon success
163
- if rfacebook_session_holder.is_valid?
184
+ if (rfacebook_session_holder.is_valid? and !staleToken)
164
185
  RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: Login was successful, calling finish_facebook_login"
165
186
  if in_external_app?
166
187
  finish_facebook_login
@@ -178,15 +199,13 @@ module RFacebook
178
199
 
179
200
  # warning logs
180
201
  if !rfacebook_session_holder.is_valid?
181
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK WARNING: Facebook session could not be activated (from handle_facebook_login)"
182
- elsif params["auth_token"]
183
- # TODO: ignoring is proper when we have already used the auth_token (we could try to reauth and swallow the exception)
184
- # however, we probably want to re-auth if the new auth_token is valid (new user, old user probably logged out)
185
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: received a new auth_token, but we already have a valid session (ignored new auth_token)"
202
+ RAILS_DEFAULT_LOGGER.info "** RFACEBOOK WARNING: Facebook session could not be activated (from handle_facebook_login)"
186
203
  end
187
204
 
188
205
  end
189
206
 
207
+ return true
208
+
190
209
  end
191
210
 
192
211
  def require_facebook_login
@@ -214,45 +233,80 @@ module RFacebook
214
233
  elsif (!fbparams or fbparams.size == 0)
215
234
 
216
235
  RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK WARNING: Failed to activate due to a bad API key or API secret"
217
- render_text facebook_debug_panel
236
+ render :text => facebook_debug_panel
218
237
  return false
219
238
 
220
239
  else
221
240
 
222
241
  RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: Redirecting to login for canvas app"
223
- render :text => "<fb:redirect url=\"#{sess.get_login_url(:canvas=>true)}\" />"
242
+ redirect_to sess.get_login_url(:canvas=>true)
224
243
  return false
225
244
 
226
245
  end
227
246
  end
228
247
  end
229
-
248
+
249
+ return true
230
250
  end
231
251
 
232
252
  def require_facebook_install
233
- sess = fbsession
234
- if (in_facebook_canvas? and (!sess.is_valid? or (fbparams["added"].to_i != 1)))
235
- render :text => "<fb:redirect url=\"#{sess.get_install_url}\" />"
253
+ if (in_facebook_canvas? or in_facebook_frame?)
254
+ if (!fbsession.is_valid? or !added_facebook_application?)
255
+ redirect_to fbsession.get_install_url
256
+ return false
257
+ end
258
+ else
259
+ RAILS_DEFAULT_LOGGER.info "** RFACEBOOK WARNING: require_facebook_install is not intended for external applications, using require_facebook_login instead"
260
+ return require_facebook_login
236
261
  end
262
+ return true
237
263
  end
238
264
 
239
265
  # SECTION: Facebook Debug Panel
240
266
 
241
267
  def render_with_facebook_debug_panel(options={})
242
- # oldLayout = options[:layout]
243
- # options[:layout] = false
244
268
  begin
245
269
  renderedOutput = render_to_string(options)
246
- rescue # TODO: don't catch-all here, just the exceptions that we originate
247
- renderedOutput = "Errors prevented this page from rendering properly."
270
+ rescue Exception => e
271
+ # TODO: make the backtrace rendering better (Evan Weaver's solution seems good, hopefully he'll allow usage of facebook_exceptions)
272
+ prettyBacktrace = e.backtrace.map do |line|
273
+ cleanLine = line.gsub(RAILS_ROOT, "").gsub("<", "&lt;").gsub(">", "&gt;")
274
+ pieces = cleanLine.split("\n")
275
+ if (pieces and pieces.size> 0)
276
+ cleanLine = "<ul>"
277
+ pieces.each do |piece|
278
+ if matches = /.*[\/\\]+((.*)\:([0-9]+)\:\s*in\s*\`(.*)\')/.match(piece)
279
+ oldPiece = piece
280
+ filename = matches[2]
281
+ line = matches[3]
282
+ method = matches[4]
283
+ piece = "<div class='summary'><strong>#{filename}</strong>:<em>#{line}</em> in <strong>#{method}</strong></div>"
284
+ piece += "<div class='rawsummary'>#{oldPiece}</div>"
285
+ end
286
+ cleanLine += "<li>#{piece}</li>"
287
+ end
288
+ cleanLine += "</ul>"
289
+ end
290
+ "<tr><td>#{cleanLine}</td></tr>"
291
+ end
292
+ renderedOutput = "
293
+ <div class='RFacebook'>
294
+ <div class='backtrace'>
295
+ <table>
296
+ <tr><td>
297
+ <h1>RFacebook <span style='font-weight: normal; color: #6D84B4'>exception backtrace</span></h1>
298
+ </td></tr>
299
+ #{prettyBacktrace}
300
+ </table>
301
+ </div>
302
+ </div>"
248
303
  end
249
- # options[:text] = "#{facebook_debug_panel}#{renderedOutput}"
250
- # options[:layout] = oldLayout
251
304
  render_text "#{facebook_debug_panel}#{renderedOutput}"
252
305
  end
253
306
 
254
307
  def facebook_debug_panel(options={})
255
- return ERB.new(RFacebook::Rails::DEBUG_PANEL_ERB_TEMPLATE).result(Proc.new{}) # TODO: should use File.dirname(__FILE__) + 'templates/debug_panel.rhtml' instead
308
+ template = File.read(File.dirname(__FILE__) + "/templates/debug_panel.rhtml")
309
+ return ERB.new(template).result(Proc.new{})
256
310
  end
257
311
 
258
312
  def facebook_status_manager
@@ -287,12 +341,79 @@ module RFacebook
287
341
  if (!in_facebook_canvas? and rfacebook_session_holder.is_valid?)
288
342
  RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: persisting Facebook session information into Rails session"
289
343
  session[:rfacebook_session] = @rfacebook_session_holder.dup
290
- session[:rfacebook_session].logger = nil # pstore can't serialize the Rails logger
344
+ session[:rfacebook_session].logger = nil # some session stores can't serialize the Rails logger
291
345
  end
292
346
  end
293
347
 
294
348
 
295
- # SECTION: URL Management
349
+ # SECTION: URL Management
350
+
351
+ def url_for__RFACEBOOK(options={}, *parameters)
352
+
353
+ # error check
354
+ if !options
355
+ RAILS_DEFAULT_LOGGER.info "** RFACEBOOK WARNING: options cannot be nil in call to url_for"
356
+ end
357
+
358
+ # use special URL rewriting when inside the canvas
359
+ # setting the mock_ajax option to true will override this
360
+ # and force usage of regular Rails rewriting
361
+ if (in_facebook_canvas? and !options[:mock_ajax]) #TODO: do something separate for in_facebook_frame?
362
+
363
+ if options.is_a? Hash
364
+ options[:only_path] = true
365
+ end
366
+
367
+ # try to get a regular URL
368
+ path = url_for__ALIASED(options, *parameters)
369
+
370
+ # replace anything that references the callback with the
371
+ # Facebook canvas equivalent (apps.facebook.com/*)
372
+ if (path.starts_with?(self.facebook_callback_path) or "#{path}/".starts_with?(self.facebook_callback_path))
373
+ path.sub!(self.facebook_callback_path, self.facebook_canvas_path)
374
+ path = "http://apps.facebook.com#{path}"
375
+ elsif (path.starts_with?("http://www.facebook.com") or path.starts_with?("https://www.facebook.com"))
376
+ # be sure that URLs that go to some other Facebook service redirect back to the canvas
377
+ if path.include?("?")
378
+ path = "#{path}&canvas=true"
379
+ else
380
+ path = "#{path}?canvas=true"
381
+ end
382
+ elsif (!path.starts_with?("http://") and !path.starts_with?("https://"))
383
+ # default to a full URL (will link externally)
384
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: failed to get canvas-friendly URL ("+path+") for ["+options.inspect+"], creating an external URL instead"
385
+ path = "#{request.protocol}#{request.host}:#{request.port}#{path}"
386
+ end
387
+
388
+ # mock-ajax rewriting
389
+ elsif options[:mock_ajax]
390
+ options.delete(:mock_ajax) # clear it so it doesnt show up in the url
391
+ options[:only_path] = true
392
+ path = "#{request.protocol}#{request.host}:#{request.port}#{url_for__ALIASED(options, *parameters)}"
393
+
394
+ # regular Rails rewriting
395
+ else
396
+ path = url_for__ALIASED(options, *parameters)
397
+ end
398
+
399
+ return path
400
+ end
401
+
402
+ def redirect_to__RFACEBOOK(options = {}, *parameters)
403
+ if in_facebook_canvas?
404
+
405
+ canvasRedirUrl = url_for(options, *parameters)
406
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: Canvas redirect to #{canvasRedirUrl}"
407
+ render :text => "<fb:redirect url=\"#{canvasRedirUrl}\" />"
408
+
409
+ else
410
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: Regular redirect_to"
411
+ redirect_to__ALIASED(options, *parameters)
412
+ end
413
+ end
414
+
415
+
416
+ # SECTION: Extension Helpers
296
417
 
297
418
  CLASSES_EXTENDED = []
298
419
 
@@ -301,7 +422,7 @@ module RFacebook
301
422
  # check for a double include
302
423
  doubleInclude = false
303
424
  CLASSES_EXTENDED.each do |klass|
304
- if base.allocate.is_a?(klass) # TODO: is there a more direct way than allocating an instance and checking is_a?
425
+ if base.allocate.is_a?(klass)
305
426
  doubleInclude = true
306
427
  end
307
428
  end
@@ -310,83 +431,21 @@ module RFacebook
310
431
  RAILS_DEFAULT_LOGGER.info "** RFACEBOOK WARNING: detected double-include of RFacebook controller extensions. Please see instructions for RFacebook on Rails plugin usage (http://rfacebook.rubyforge.org). You may be including the deprecated RFacebook::RailsControllerExtensions in addition to the plugin."
311
432
 
312
433
  else
434
+
435
+ # keep track that we have already extended this class
313
436
  CLASSES_EXTENDED << base
314
437
 
315
438
  # we need to use an eval since we will be overriding ActionController::Base methods
316
439
  # and we need to be able to call the originals
317
440
  base.class_eval '
318
-
319
441
  alias_method(:url_for__ALIASED, :url_for)
320
-
321
- def url_for(options={}, *parameters)
322
-
323
- # error check
324
- if !options
325
- RAILS_DEFAULT_LOGGER.info "** RFACEBOOK WARNING: options cannot be nil in call to url_for"
326
- end
327
-
328
- # use special URL rewriting when inside the canvas
329
- # setting the mock_ajax option to true will override this
330
- # and force usage of regular Rails rewriting
331
- if (in_facebook_canvas? and !options[:mock_ajax]) #TODO: or in_facebook_frame?
332
-
333
- if options.is_a? Hash
334
- options[:only_path] = true
335
- end
336
-
337
- # try to get a regular URL
338
- path = url_for__ALIASED(options, *parameters)
339
-
340
- # replace anything that references the callback with the
341
- # Facebook canvas equivalent (apps.facebook.com/*)
342
- if (path.starts_with?(self.facebook_callback_path) or "#{path}/".starts_with?(self.facebook_callback_path))
343
- path.sub!(self.facebook_callback_path, self.facebook_canvas_path)
344
- path = "http://apps.facebook.com#{path}"
345
- else
346
- # default to a full URL (will link externally)
347
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: failed to get canvas-friendly URL ("+path+") for ["+options.inspect+"], creating an external URL instead"
348
- path = "#{request.protocol}#{request.host}:#{request.port}#{path}"
349
- end
350
-
351
- # mock-ajax rewriting
352
- elsif options[:mock_ajax]
353
- options.delete(:mock_ajax) # clear it so it doesnt show up in the url
354
- options[:only_path] = true
355
- path = "#{request.protocol}#{request.host}:#{request.port}#{url_for__ALIASED(options, *parameters)}"
356
-
357
- # regular Rails rewriting
358
- else
359
- path = url_for__ALIASED(options, *parameters)
360
- end
361
-
362
- return path
363
- end
364
-
442
+ alias_method(:url_for, :url_for__RFACEBOOK)
365
443
 
366
444
  alias_method(:redirect_to__ALIASED, :redirect_to)
367
-
368
- def redirect_to(options = {}, *parameters)
369
- if in_facebook_canvas?
370
-
371
- canvasRedirUrl = url_for(options, *parameters)
372
-
373
- # ensure that we come back to the canvas if we redirect
374
- # to somewhere else on Facebook
375
- if canvasRedirUrl.starts_with?("http://www.facebook.com")
376
- canvasRedirUrl = "#{canvasRedirUrl}&canvas"
377
- end
378
-
379
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: Canvas redirect to #{canvasRedirUrl}"
380
- render :text => "<fb:redirect url=\"#{canvasRedirUrl}\" />"
381
-
382
- else
383
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: Regular redirect_to"
384
- redirect_to__ALIASED(options, *parameters)
385
- end
386
- end
445
+ alias_method(:redirect_to, :redirect_to__RFACEBOOK)
387
446
  '
388
447
 
389
- # ensure that we persist the Facebook session in the Rails session (if possible)
448
+ # ensure that we persist the Facebook session into the Rails session (if possible)
390
449
  base.after_filter(:rfacebook_persist_session_to_rails)
391
450
 
392
451
  # fix third party cookies in IE
@@ -32,49 +32,84 @@ require "rfacebook_on_rails/controller_extensions"
32
32
  require "rfacebook_on_rails/model_extensions"
33
33
  require "rfacebook_on_rails/session_extensions"
34
34
 
35
- module RFacebook
36
- module Rails
37
- module Plugin
38
- #####
39
- module ControllerExtensions
40
- def facebook_api_key
41
- FACEBOOK["key"] || super
42
- end
43
- def facebook_api_secret
44
- FACEBOOK["secret"] || super
45
- end
46
- def facebook_canvas_path
47
- FACEBOOK["canvas_path"] || super
48
- end
49
- def facebook_callback_path
50
- FACEBOOK["callback_path"] || super
51
- end
52
- end
53
- #####
54
- module ModelExtensions
55
- def facebook_api_key
56
- FACEBOOK["key"] || super
57
- end
58
- def facebook_api_secret
59
- FACEBOOK["secret"] || super
60
- end
61
- end
62
- #####
63
- module ViewExtensions
64
- end
35
+ module RFacebook::Rails::Plugin
36
+
37
+ module ControllerExtensions
38
+ def facebook_api_key
39
+ FACEBOOK["key"] || super
40
+ end
41
+ def facebook_api_secret
42
+ FACEBOOK["secret"] || super
43
+ end
44
+ def facebook_canvas_path
45
+ FACEBOOK["canvas_path"] || super
46
+ end
47
+ def facebook_callback_path
48
+ FACEBOOK["callback_path"] || super
49
+ end
50
+ end
51
+
52
+ module ModelExtensions
53
+ def facebook_api_key
54
+ FACEBOOK["key"] || super
55
+ end
56
+ def facebook_api_secret
57
+ FACEBOOK["secret"] || super
65
58
  end
66
59
  end
60
+
61
+ module ViewExtensions
62
+ end
63
+
64
+ end
65
+
66
+ # inject methods to Rails MVC classes
67
+ ActionView::Base.send(:include, RFacebook::Rails::ViewExtensions)
68
+ ActionView::Base.send(:include, RFacebook::Rails::Plugin::ViewExtensions)
69
+
70
+ ActionController::Base.send(:include, RFacebook::Rails::ControllerExtensions)
71
+ ActionController::Base.send(:include, RFacebook::Rails::Plugin::ControllerExtensions)
72
+
73
+ ActiveRecord::Base.send(:include, RFacebook::Rails::ModelExtensions)
74
+ ActiveRecord::Base.send(:include, RFacebook::Rails::Plugin::ModelExtensions)
75
+
76
+ # inject methods to Rails session management classes
77
+ CGI::Session.send(:include, RFacebook::Rails::SessionExtensions)
78
+
79
+ # TODO: document SessionStoreExtensions as API so that anyone can patch their own custom session container in addition to these
80
+ CGI::Session::PStore.send(:include, RFacebook::Rails::SessionStoreExtensions)
81
+ CGI::Session::ActiveRecordStore.send(:include, RFacebook::Rails::SessionStoreExtensions)
82
+ CGI::Session::DRbStore.send(:include, RFacebook::Rails::SessionStoreExtensions)
83
+ CGI::Session::FileStore.send(:include, RFacebook::Rails::SessionStoreExtensions)
84
+ CGI::Session::MemoryStore.send(:include, RFacebook::Rails::SessionStoreExtensions)
85
+ begin
86
+ CGI::Session::MemCacheStore.send(:include, RFacebook::Rails::SessionStoreExtensions)
87
+ rescue
88
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: It looks like you don't have memcache-client, so MemCacheStore was not extended"
67
89
  end
68
90
 
69
- # load Facebook configuration file
91
+ # load Facebook configuration file (credit: Evan Weaver)
70
92
  begin
71
93
  FACEBOOK = YAML.load_file("#{RAILS_ROOT}/config/facebook.yml")[RAILS_ENV]
72
94
  rescue
73
95
  FACEBOOK = {}
74
96
  end
75
97
 
98
+ # parse for full URLs in facebook.yml (multiple people have made this mistake)
99
+ def ensureRelativePath(path)
100
+ if matchData = /(\w+)(\:\/\/)([\w0-9\.]+)([\:0-9]*)(.*)/.match(path)
101
+ relativePath = matchData.captures[4]
102
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: It looks like you used a full URL (#{path}) in facebook.yml. RFacebook expected a relative path and has automatically converted this URL to #{relativePath}."
103
+ return relativePath
104
+ else
105
+ return path
106
+ end
107
+ end
108
+
109
+ FACEBOOK["canvas_path"] = ensureRelativePath(FACEBOOK["canvas_path"])
110
+ FACEBOOK["callback_path"] = ensureRelativePath(FACEBOOK["callback_path"])
111
+
76
112
  # make sure the paths have leading and trailing slashes
77
- # TODO: also parse for full URLs beginning with HTTP (see: http://rubyforge.org/tracker/index.php?func=detail&aid=13096&group_id=3607&atid=13796)
78
113
  def ensureLeadingAndTrailingSlashesForPath(path)
79
114
  if (path and path.size>0)
80
115
  if !path.starts_with?("/")
@@ -90,38 +125,4 @@ def ensureLeadingAndTrailingSlashesForPath(path)
90
125
  end
91
126
 
92
127
  FACEBOOK["canvas_path"] = ensureLeadingAndTrailingSlashesForPath(FACEBOOK["canvas_path"])
93
- FACEBOOK["callback_path"] = ensureLeadingAndTrailingSlashesForPath(FACEBOOK["callback_path"])
94
-
95
- # inject methods to Rails MVC classes
96
- ActionView::Base.send(:include, RFacebook::Rails::ViewExtensions)
97
- ActionView::Base.send(:include, RFacebook::Rails::Plugin::ViewExtensions)
98
-
99
- ActionController::Base.send(:include, RFacebook::Rails::ControllerExtensions)
100
- ActionController::Base.send(:include, RFacebook::Rails::Plugin::ControllerExtensions)
101
-
102
- ActiveRecord::Base.send(:include, RFacebook::Rails::ModelExtensions)
103
- ActiveRecord::Base.send(:include, RFacebook::Rails::Plugin::ModelExtensions)
104
-
105
- # inject methods to patch Rails session containers
106
- # TODO: document this as API so that everyone knows how to patch their own custom session container
107
- module RFacebook::Rails::Toolbox
108
- def self.patch_session_store_class(sessionStoreKlass)
109
- sessionStoreKlass.send(:include, RFacebook::Rails::SessionStoreExtensions)
110
- sessionStoreKlass.class_eval'
111
- alias :initialize__ALIASED :initialize
112
- alias :initialize :initialize__RFACEBOOK
113
- '
114
- end
115
- end
116
-
117
- # patch as many session stores as possible
118
- RFacebook::Rails::Toolbox::patch_session_store_class(CGI::Session::PStore)
119
- RFacebook::Rails::Toolbox::patch_session_store_class(CGI::Session::ActiveRecordStore)
120
- RFacebook::Rails::Toolbox::patch_session_store_class(CGI::Session::DRbStore)
121
- RFacebook::Rails::Toolbox::patch_session_store_class(CGI::Session::FileStore)
122
- RFacebook::Rails::Toolbox::patch_session_store_class(CGI::Session::MemoryStore)
123
- begin
124
- RFacebook::Rails::Toolbox::patch_session_store_class(CGI::Session::MemCacheStore)
125
- rescue
126
- # TODO: this needs to be handled better
127
- end
128
+ FACEBOOK["callback_path"] = ensureLeadingAndTrailingSlashesForPath(FACEBOOK["callback_path"])
@@ -101,17 +101,7 @@ production:
101
101
 
102
102
  puts "======================================================"
103
103
  puts "Tunneling #{remoteHost}:#{remotePort} to 0.0.0.0:#{localPort}"
104
-
105
- # TODO: learn more about autossh
106
- # if system("autossh -V")
107
- # cmd = "autossh -M 8888"
108
- # puts "(autossh found, using port 8888 to monitor it)"
109
- # else
110
- # cmd = "ssh"
111
- # puts "(autossh not found, using ssh instead)"
112
- # end
113
- cmd = "ssh"
114
-
104
+
115
105
  puts
116
106
  puts "NOTES:"
117
107
  puts "* ensure that you have Rails running on your local machine at port #{localPort}"
@@ -119,19 +109,17 @@ production:
119
109
  puts "* use ctrl-c to quit the tunnel"
120
110
  puts "* if you have problems creating the tunnel, you may need to add the following to /etc/ssh/sshd_config on your server:"
121
111
  puts "
122
-
123
112
  GatewayPorts clientspecified
124
113
 
125
114
  "
126
115
  puts "* if you have problems with #{remoteHost} timing out your ssh connection, add the following lines to your '~/.ssh/config' file:"
127
116
  puts "
128
-
129
117
  Host #{remoteHost}
130
118
  ServerAliveInterval 120
131
119
 
132
120
  "
133
121
  puts "======================================================"
134
- exec "#{cmd} -nNT -g -R *:#{remotePort}:0.0.0.0:#{localPort} #{remoteUsername}@#{remoteHost}"
122
+ exec "ssh -nNT -g -R *:#{remotePort}:0.0.0.0:#{localPort} #{remoteUsername}@#{remoteHost}"
135
123
 
136
124
 
137
125
  end
@@ -30,21 +30,20 @@
30
30
  require "digest/md5"
31
31
  require "cgi"
32
32
 
33
- # patch up the CGI session module to use Facebook session keys when cookies aren't available
34
- class CGI::Session
35
-
36
- alias :initialize__ALIASED :initialize
37
- alias :new_session__ALIASED :new_session
38
-
39
- def using_facebook_session_id?
40
- return @using_fb_session_id
41
- end
33
+ module RFacebook::Rails::SessionExtensions
42
34
 
35
+ # SECTION: New Methods
43
36
  def force_to_be_new!
44
37
  @force_to_be_new = true
45
38
  end
46
39
 
47
- def new_session
40
+ def using_facebook_session_id?
41
+ return (@fb_sig_session_id != nil)
42
+ end
43
+
44
+ # SECTION: Base Overrides
45
+
46
+ def new_session__RFACEBOOK
48
47
  if @force_to_be_new
49
48
  return true
50
49
  else
@@ -52,50 +51,152 @@ class CGI::Session
52
51
  end
53
52
  end
54
53
 
55
- def initialize(request, options = {})
54
+ def initialize__RFACEBOOK(request, options = {})
56
55
 
57
- # check the environment to find a Facebook sig_session_key (credit: Blake Carlson and David Troy)
58
- fbsessionId = nil
59
- ["RAW_POST_DATA", "QUERY_STRING", "HTTP_REFERER"].each do |tableSource|
60
- if request.env_table[tableSource]
61
- fbsessionId = CGI::parse(request.env_table[tableSource]).fetch('fb_sig_session_key'){[]}.first
62
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: checked #{tableSource} for Facebook session id and got [#{fbsessionId}]"
56
+ # only try to use the sig when we don't have a cookie (i.e., in the canvas)
57
+ if in_facebook_canvas?(request)
58
+
59
+ # try a few different ways
60
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: Attempting to use fb_sig_session_key as a session key, since we are inside the canvas"
61
+ @fb_sig_session_id = lookup_request_parameter(request, "fb_sig_session_key")
62
+
63
+ # we only want to change the session_id if we got one from the fb_sig
64
+ if @fb_sig_session_id
65
+ options["session_id"] = Digest::MD5.hexdigest(@fb_sig_session_id)
66
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: using MD5 of fb_sig_session_key [#{options['session_id']}] for the Rails session id"
63
67
  end
64
- break if fbsessionId
65
- end
66
-
67
- # we only want to change the session_id if we got one from the fb_sig
68
- if fbsessionId
69
- options['session_id'] = Digest::MD5.hexdigest(fbsessionId)
70
- @using_facebook_session_id = true
71
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: using MD5 of Facebook session id [#{options['session_id']}] for the Rails session id}"
72
68
  end
73
69
 
74
70
  # now call the default Rails session initialization
75
71
  initialize__ALIASED(request, options)
76
72
  end
73
+
74
+ # SECTION: Extension Helpers
75
+
76
+ def self.included(base)
77
+ base.class_eval'
78
+ alias :initialize__ALIASED :initialize
79
+ alias :initialize :initialize__RFACEBOOK
80
+
81
+ alias :new_session__ALIASED :new_session
82
+ alias :new_session :new_session__RFACEBOOK
83
+ '
84
+ end
85
+
86
+ # SECTION: Private Helpers
87
+
88
+ private
89
+
90
+ # TODO: it seems that there should be a better way to just get raw parameters
91
+ # (not sure why the nil key bug doesn't seem to be fixed in my installation)
92
+ # ...also, there seems to be some interaction with Mongrel as well that can
93
+ # cause the parameters to fail
94
+ def lookup_request_parameter(request, key)
95
+
96
+ # Depending on the user's version of Rails, this may fail due to a bug in Rails parsing of
97
+ # nil keys: http://dev.rubyonrails.org/ticket/5137, so we have a backup plan
98
+ begin
99
+
100
+ # this should work on most Rails installations
101
+ return request.parameters[key]
102
+
103
+ rescue
104
+
105
+ # this saves most other Rails installations
106
+ begin
107
+
108
+ retval = nil
109
+
110
+ # try accessing raw_post (doesn't work in some mongrel installations)
111
+ if request.respond_to?(:raw_post)
112
+ return CGI::parse(request.send(:raw_post)).fetch(key){[]}.first
113
+ end
114
+
115
+ # try accessing the raw environment table
116
+ if !retval
117
+ envTable = nil
118
+
119
+ envTable = request.send(:env_table) if request.respond_to?(:env_table)
120
+ if !envTable
121
+ envTable = request.send(:env) if request.respond_to?(:env)
122
+ end
123
+
124
+ if envTable
125
+ # credit: Blake Carlson and David Troy
126
+ ["RAW_POST_DATA", "QUERY_STRING"].each do |tableSource|
127
+ if envTable[tableSource]
128
+ retval = CGI::parse(envTable[tableSource]).fetch(key){[]}.first
129
+ end
130
+ break if retval
131
+ end
132
+ end
133
+ end
134
+
135
+ # hopefully we got a parameter
136
+ return retval
137
+
138
+ rescue
139
+
140
+ # for some reason, we just can't get the parameters
141
+ RAILS_DEFAULT_LOGGER.info "** RFACEBOOK WARNING: failed to access request.parameters"
142
+ return nil
143
+
144
+ end
145
+ end
146
+ end
147
+
148
+ def in_facebook_canvas?(request)
149
+ # TODO: we should probably be checking the fb_sig for validity here (template method needed)
150
+ # ...we can only do this if we can grab the equivalent of a params hash
151
+ return lookup_request_parameter(request, "fb_sig_in_canvas")
152
+ end
153
+
77
154
  end
78
155
 
79
156
  # Module: SessionStoreExtensions
80
157
  #
81
- # Special initialize method that forces any session store to use the Facebook session
158
+ # Special initialize method that attempts to force any session store to use the Facebook session
82
159
  module RFacebook::Rails::SessionStoreExtensions
160
+
161
+ # SECTION: Base Overrides
162
+
83
163
  def initialize__RFACEBOOK(session, options, *extraParams)
84
- begin
85
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: inside #{self.class.to_s}, with session_id: #{session.session_id}, new_session = #{session.new_session ? 'yes' : 'no'}"
86
- initialize__ALIASED(session, options, *extraParams)
87
- rescue Exception => e
164
+
165
+ if session.using_facebook_session_id?
166
+
167
+ # we got the fb_sig_session_key, so alter Rails' behavior to use that key to make a session
88
168
  begin
89
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: failed to init #{self.class.to_s} session, trying to make a new session"
90
- # FIXME: technically this might be a security problem, since an external browser can grab any unused session id they want
91
- if session.session_id
92
- session.force_to_be_new!
93
- end
169
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: using fb_sig_session_key for the #{self.class.to_s} session (session_id=#{session.session_id})"
94
170
  initialize__ALIASED(session, options, *extraParams)
95
- rescue Exception => e
96
- RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: failed to create a new #{self.class.to_s} session falling back to default Rails behavior"
97
- raise e
171
+ rescue Exception => e
172
+ begin
173
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: failed to initialize session (session_id=#{session.session_id}), trying to force a new session"
174
+ if session.session_id
175
+ session.force_to_be_new!
176
+ end
177
+ initialize__ALIASED(session, options, *extraParams)
178
+ rescue Exception => e
179
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: failed to force a new session, falling back to default Rails behavior"
180
+ raise e
181
+ end
98
182
  end
183
+
184
+ else
185
+
186
+ # we didn't get the fb_sig_session_key, do not alter Rails' behavior
187
+ RAILS_DEFAULT_LOGGER.debug "** RFACEBOOK INFO: using default Rails sessions (since we didn't find an fb_sig_session_key in the environment)"
188
+ initialize__ALIASED(session, options, *extraParams)
189
+
99
190
  end
100
191
  end
192
+
193
+ # SECTION: Extension Helpers
194
+
195
+ def self.included(base)
196
+ base.class_eval'
197
+ alias :initialize__ALIASED :initialize
198
+ alias :initialize :initialize__RFACEBOOK
199
+ '
200
+ end
201
+
101
202
  end
@@ -1,36 +1,3 @@
1
- # Copyright (c) 2007, Matt Pizzimenti (www.livelearncode.com)
2
- # All rights reserved.
3
- #
4
- # Redistribution and use in source and binary forms, with or without modification,
5
- # are permitted provided that the following conditions are met:
6
- #
7
- # Redistributions of source code must retain the above copyright notice,
8
- # this list of conditions and the following disclaimer.
9
- #
10
- # Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- #
14
- # Neither the name of the original author nor the names of contributors
15
- # may be used to endorse or promote products derived from this software
16
- # without specific prior written permission.
17
- #
18
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
- # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
- #
29
-
30
- module RFacebook
31
- module Rails
32
- DEBUG_PANEL_ERB_TEMPLATE = <<-end_info
33
-
34
1
  <style type="text/css">
35
2
 
36
3
  .RFacebook .environment
@@ -136,6 +103,66 @@ module RFacebook
136
103
  color: black;
137
104
  }
138
105
 
106
+ .RFacebook .backtrace
107
+ {
108
+ border-collapse: collapse;
109
+ background-color: #3B5998;
110
+ color: white;
111
+ }
112
+
113
+ .RFacebook .backtrace
114
+ {
115
+ padding: 30px;
116
+ background: #3B5998;
117
+ }
118
+
119
+ .RFacebook .backtrace h1
120
+ {
121
+ margin: 0px 0px 5px 0px;
122
+ padding: 0px;
123
+
124
+ color: white;
125
+ font-size: 1.6em;
126
+ }
127
+
128
+ /*
129
+ .RFacebook table.backtrace td
130
+ {
131
+ padding: 10px 2px 10px 2px;
132
+ border-width: 1px 0px 1px 0px;
133
+
134
+ border-style: solid;
135
+ border-color: #ccc;
136
+ }
137
+ */
138
+
139
+ .RFacebook .backtrace div.summary
140
+ {
141
+ font-size: 1.2em;
142
+ padding: 2px;
143
+ color: white;
144
+ }
145
+
146
+ .RFacebook .backtrace div.rawsummary
147
+ {
148
+ font-size: 0.7em;
149
+ color: #6D84B4;
150
+ padding-left: 5px;
151
+ }
152
+
153
+ .RFacebook ul
154
+ {
155
+ margin: 0px;
156
+ padding: 0px;
157
+ list-style-type: none;
158
+ }
159
+
160
+ .RFacebook ul li
161
+ {
162
+ list-style-type: none;
163
+ padding: 5px;
164
+ }
165
+
139
166
  </style>
140
167
 
141
168
  <div class="RFacebook">
@@ -170,9 +197,9 @@ module RFacebook
170
197
  <% end %>
171
198
  </td>
172
199
  <td class="value">
173
- <% if statusCheck.message.class == String %>
200
+ <% if statusCheck.message.is_a? String %>
174
201
  <%= statusCheck.message %>
175
- <% elsif statusCheck.message.class == Hash %>
202
+ <% elsif statusCheck.message.is_a? Hash %>
176
203
  <table class="details">
177
204
  <% statusCheck.message.each do |k,v| %>
178
205
  <tr>
@@ -191,20 +218,3 @@ module RFacebook
191
218
 
192
219
  </div>
193
220
  </div>
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
- end_info
208
-
209
- end
210
- end
@@ -53,14 +53,14 @@ module RFacebook
53
53
 
54
54
  def image_path(*params)
55
55
  path = super(*params)
56
- if (in_facebook_canvas? or in_mock_ajax?) # TODO: or in_facebook_frame?)
56
+ if (in_facebook_canvas? or in_mock_ajax?)
57
57
  path = "#{request.protocol}#{request.host_with_port}#{path}"
58
58
  end
59
59
  return path
60
60
  end
61
61
 
62
- def rfacebook_debug_panel(options={})
63
- return @controller.rfacebook_debug_panel(options)
62
+ def facebook_debug_panel(options={})
63
+ return @controller.facebook_debug_panel(options)
64
64
  end
65
65
 
66
66
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.1
3
3
  specification_version: 1
4
4
  name: rfacebook
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.9.0
7
- date: 2007-08-18 00:00:00 -05:00
6
+ version: 0.9.1
7
+ date: 2007-08-20 00:00:00 -04:00
8
8
  summary: A Ruby interface to the Facebook API v1.0+ (F8 and beyond). Works with RFacebook on Rails plugin (see rfacebook.rubyforge.org).
9
9
  require_paths:
10
10
  - lib
@@ -47,7 +47,7 @@ files:
47
47
  - lib/rfacebook_on_rails/plugin/rake.rb
48
48
  - lib/rfacebook_on_rails/plugin/Rakefile.rb
49
49
  - lib/rfacebook_on_rails/plugin/uninstall.rb
50
- - lib/rfacebook_on_rails/templates/debug_panel.rb
50
+ - lib/rfacebook_on_rails/templates/debug_panel.rhtml
51
51
  - README
52
52
  test_files: []
53
53