oddlyzen
11/10/2012 - 8:04 PM

Sample Force.com Sinatra app.

Sample Force.com Sinatra app.

<!DOCTYPE HTML>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <script src="https://raw.github.com/ccampbell/rainbow/master/js/rainbow.min.js" type="text/javascript"></script>
  <script src="https://raw.github.com/ccampbell/rainbow/master/js/language/generic.js" type="text/javascript"></script>
  <script src="https://raw.github.com/ccampbell/rainbow/master/js/language/ruby.js" type="text/javascript"></script>
  <style type="text/css" media="all">
    /**
     * GitHub theme
     *
     * @author Craig Campbell
     * @version 1.0.4
     */
    pre {
        border: 1px solid #ccc;
        word-wrap: break-word;
        padding: 6px 10px;
        line-height: 19px;
        margin-bottom: 20px;
    }

    code {
        border: 1px solid #eaeaea;
        margin: 0px 2px;
        padding: 0px 5px;
        font-size: 12px;
    }

    pre code {
        border: 0px;
        padding: 0px;
        margin: 0px;
        -moz-border-radius: 0px;
        -webkit-border-radius: 0px;
        border-radius: 0px;
    }

    pre, code {
        font-family: Consolas, 'Liberation Mono', Courier, monospace;
        color: #333;
        background: #f8f8f8;
        -moz-border-radius: 3px;
        -webkit-border-radius: 3px;
        border-radius: 3px;
    }

    pre, pre code {
        font-size: 13px;
    }

    pre .comment {
        color: #998;
    }

    pre .support {
        color: #0086B3;
    }

    pre .tag, pre .tag-name {
        color: navy;
    }

    pre .keyword, pre .css-property, pre .vendor-prefix, pre .sass, pre .class, pre .id, pre .css-value, pre .entity.function, pre .storage.function {
        font-weight: bold;
    }

    pre .css-property, pre .css-value, pre .vendor-prefix, pre .support.namespace {
        color: #333;
    }

    pre .constant.numeric, pre .keyword.unit, pre .hex-color {
        font-weight: normal;
        color: #099;
    }

    pre .entity.class {
        color: #458;
    }

    pre .entity.id, pre .entity.function {
        color: #900;
    }

    pre .attribute, pre .variable {
        color: teal;
    }

    pre .string, pre .support.value  {
        font-weight: normal;
        color: #d14;
    }

    pre .regexp {
        color: #009926;
    }

    body {
      width: 800px;
      background: #fff;
    }

    pre {
      width: 700px;
    }
  </style>
</head>
<body>
  <div class="container">
    <%= yield %>
  </div>
</body>
</html>
<% if logged_in? %>
  <h1>Hello <%= user['fullName'] %></h1>

  <h2>Here's a list of your Accounts</h2>
  <ul>
    <% @accounts.each do |account| %>
      <li><%= account.Name %></li>
    <% end %>
  </ul>

  <h2>And the Canvas Signed Request</h2>
  <pre><code data-language="ruby"><%=h PP.pp(signed_request, '') %></code></pre>
<% else %>
  Not signed in. Open the app through Force.com Cavnas Preview.
<% end %>
require 'sinatra/base'
require 'json'
require 'restforce'
require 'pp'

class CanvasApp < Sinatra::Base
  configure do
    # Allow the app to be pulled in through an iframe.
    set :protection, except: :frame_options
    enable :sessions
  end

  helpers do
    include Rack::Utils
    alias_method :h, :escape_html

    def secret
      ENV['CLIENT_SECRET']
    end

    def signed_request
      session[:signed_request]
    end

    def context
      signed_request['context']
    end

    def user
      context['user']
    end

    def client
      Restforce.new(
        oauth_token: signed_request['oauthToken'],
        instance_url: signed_request['instanceUrl']
      )
    end

    def logged_in?
      !!signed_request
    end
  end

  get '/' do
    @accounts = client.query('select Name from Account')
    erb :home
  end

  post '/canvas' do
    session[:signed_request] = Restforce.decode_signed_request(params[:signed_request], secret)
    redirect '/'
  end
end

run CanvasApp

This is a simple Sinatra app that shows how to use Restforce with Force.com canvas apps.

Usage

git clone git://gist.github.com/4052312.git sinatra-canvas

Now create a new Connected App on your Salesforce instance. Point the Canvas App URL to https://localhost/canvas and chose "Signed Request (POST)" as the access method.

In one terminal, startup the app:

CLIENT_SECRET="secret from above" bundle exec rackup

In another terminal, startup an https proxy:

sudo bundle exec tunnels 443 9292

Open the app up in the Canvas App Previewer, and you should see your app running.

web: bundle exec rackup -p $PORT
source :rubygems

gem 'sinatra', '~> 1.3.3'
gem 'json', '~> 1.7.5'
gem 'restforce', '~> 1.0.5'
gem 'thin', '~> 1.5.0'

group :development do
  gem 'shotgun', '~> 0.9'
  gem 'tunnels', '~> 1.2.2'
end