Leverage Rails Resource Routes on Facebook

Since all canvas page views are proxied through POSTs, resource routes were hopelessly broken. The Facebook platform team was kind enough to add a new feature just for us rails folks: a new signed parameter that indicates the original request type (i.e. POST v. GET) against canvas pages.



Here’s a small patch you can stick at the end of environment.rb to restore REST-ful routes.


class ActionController::Routing::RouteSet
  def extract_request_environment(request)
    contents = request.body.read
    facebook_method_override = nil
    if contents =~ /fb_sig_request_method=([A-Z]+)/
      facebook_method_override = $1
    end
    request.body.string = contents
    { :method => facebook_method_override ? facebook_method_override.downcase.intern : request.method}
  end
end



UPDATE: Here’s a slightly better implementation that allows the .get? and .post? helpers as well as a few other things to work (thanks Chris Nolan for reminding us to update this blog entry):


ActionController::AbstractRequest.class_eval do
  def request_method_with_facebook_overrides
    @request_method ||= begin
      case
        when parameters[:_method]
          parameters[:_method].downcase.to_sym
        when parameters[:fb_sig_request_method]
          parameters[:fb_sig_request_method].downcase.to_sym
        else
          request_method_without_facebook_overrides
      end
    end
  end
  alias_method_chain :request_method, :facebook_overrides
end

2 Comments

  1. Better yet, drop way down into ActionController::AbstractRequest and much with the setting of request.method directly.

    See http://facebooker.professionalnerd.com/rdoc/latest/classes/AbstractRequest.html for an example.

  2. Hi Hungry Machine,

    We used your solution and encountered issues with uploading images to our app larger than ~132k. Did you see this at all?

    The updated solution from Chris doesn’t seem to have the issue.

    Here is the error we were getting with the original

    Status: 500 Internal Server Error
    undefined method `string=’ for #<File:/tmp/mongrel8273-0>
    /usr/local/lib/ruby/1.8/delegate.rb:268:in `method_missing’
    /ourapppath/config/initializers/facebook_routing.rb:8:in `extract_request_environment’