I finally got a chance to do some work with Sinatra. Something more than the typical Hello, World! app. I needed a UI on top of a restful web API. The docs are written using curl calls into their service, with JSON response payloads. Easy enough to deal with, but I wanted something a bit more robust. Thus I created Cardspring_browse.

The app is little more than HTML over a JSON API. Which isn’t to bad since most apps are just HTML over SQL. I needed to handle to many URLs to have it all in a single file so I split it up into several apps. I then used an outer app to include all the inner apps.

class Inner < Sinatra::Base
  get "/inner" do
    # ...
  end
end

class Outer < Sinatra::Base
  use Inner

  get "/" do
    # ...
  end
end

Easy enough until it came time to share some configuration settings. Each split up file seemed to get it’s own copy of the settings. This meant that the outer app’s settings didn’t apply. I tried all kinds of things, but nothing worked. I resorted to asking a question on Stack Overflow.

The answer there was acceptable, but not the ideal. I thought if I read the source code I might be able to figure something better out. It turns out the source for Sinatra and Rack are very readable. Both are very tiny too. After reading the answer was clear. The pattern used throughout many Rack apps is to set values in the env parameter hash that is passed to the call method. Typically you use a string with the name of your app and the name of the value separated by a . (period).

The Cardspring_browse app uses it here. This code uses the Rack middleware Rack::Config to achieve the result.

use Rack::Config do |env|
  env["my_app.my_property"] = "custom value"
end

The full code for the outer application is the following. From the looks of the code I don’t yet know the best practice for creating larger Sinatra apps. I still need to figure out the best way to split up the URLs into different files and still create a maintainable codebase. I think this style might be abusing the builder style.

Help wanted! It is open source.

class Application < Sinatra::Base

  enable :method_override
  enable :config_file

  PROPERTY_NAME = 'cardspring_browse.config_file'
  use Rack::Config do |env|
    env[PROPERTY_NAME] = settings.config_file
  end

  use CardspringBrowse::App::Publisher
  use CardspringBrowse::App::Users
  use CardspringBrowse::App::Events
  use CardspringBrowse::App::Businesses
  use CardspringBrowse::App::Apps
  use CardspringBrowse::App::Transactions

  def initialize(app, config_file = __FILE__)
    super(app)
    settings.config_file = config_file
  end

  get "/" do
    redirect to("/v1")
  end

end