May 27th, 2008 cschneid
UPDATE: I made another post about how to do RSpec testing without having to patch sinatra.
I haven’t looked into this myself, but thanks the the enterprising jodo on #sinatra, and the mad coding skillz of avdi on github, there is a patch to enable interop between test-spec (default) and rspec.
So give it a try, and see how it goes. Report back on #sinatra, or leave a comment here.
Posted in Programming, Ruby, Sinatra | No Comments »
May 25th, 2008 cschneid
The Sinatra framework has a fairly unmapped deployment landscape. The standard answer is to use Thin or Mongrel, and have a reverse proxy (lighttpd, or nginx, or even Apache) point to your bundle of servers.
But of course that isn’t always possible. Cheap shared hosting (like Dreamhost) won’t let you run Thin or Mongrel, or setup reverse proxies (at least on the shared plan).
Luckily Rack supports various connectors, including CGI and FastCGI. Unluckily for us, FastCGI doesn’t quite work with the current Sinatra git HEAD.
To get a dumb “hello world” Sinatra application up and running on dreamhost involves pulling down the current Sinatra code, and hacking at it a bit. Don’t worry, it’s mostly just commenting out a few lines, and tweaking another line.
Files needed:
- .htaccess
- dispatch.fcgi
- Tweaked sinatra.rb
.htaccess
RewriteEngine on
AddHandler fastcgi-script .fcgi
Options +FollowSymLinks +ExecCGI
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
dispatch.fcgi
#!/usr/bin/ruby
require 'sinatra/lib/sinatra.rb'
require 'rubygems'
fastcgi_log = File.open("fastcgi.log", "a")
STDOUT.reopen fastcgi_log
STDERR.reopen fastcgi_log
STDOUT.sync = true
set :logging, false
set :server, "FastCGI"
module Rack
class Request
def path_info
@env["SCRIPT_URL"].to_s
end
def path_info=(s)
@env["SCRIPT_URL"] = s.to_s
end
end
end
load 'test.rb'
sinatra.rb - Replace this function with the new version here.
def run
begin
#puts "== Sinatra has taken the stage on port #{port} for #{env} with backup by #{server.name}"
require 'pp'
server.run(application) do |server|
trap(:INT) do
server.stop
#puts "\n== Sinatra has ended his set (crowd applauds)"
end
end
rescue Errno::EADDRINUSE => e
#puts "== Someone is already performing on port #{port}!"
end
end
Hopefully that helps somebody get up and running, check out #sinatra on freenode.org to ask questions, but be patient, we’re friendly, but work day jobs.
Posted in Programming, Ruby, Sinatra | No Comments »
May 24th, 2008 cschneid
Instead of writing a pastebin for semantic data like I had planned (still a good idea I’ll get to eventually), I’ve started working on a blog engine initially written by Ryan Tomayko called Wink. If you visit his blog, you can see the only live instance of Wink. He recently open sourced it with a little cajoling from the rest of the guys in #sinatra.
To get a feel for what it can do, check out Ryan’s post “Administrative Debris”. You can get a very good feel for what Wink is all about: simplicity, consistency, and ease.
Currently it’s not quite in a usable state. If you grab the 0.1 tag off of github, it should run for you, maybe with some tweaking or fighting with it. If you want to give it a shot, please do so, and report back on freenode.org either in #sinatra or #wink on how it went.
Beyond that, we’re going to solidify some of the wibbly-wobbly parts, add a few features, and document how to install and deploy.
I see Wink as being the shining example of what a great sinatra application can be, and I’m glad I got in on the ground floor of it’s open source life.
To grab the source code, or just follow development head over to github at Ryan’s Wink repository, or mine.
Posted in Programming, Rails, Sinatra | 1 Comment »
May 20th, 2008 cschneid
Sinatra has several configurable options you can set at the top of your application.
Default options, straight out of the code:
@default_options = {
:run => true,
:port => 4567,
:env => :development,
:root => root,
:views => root + '/views',
:public => root + '/public',
:sessions => false,
:logging => true,
:raise_errors => false
}
Key options, and what they do:
- run - Should Sinatra auto-call run on itself with an at_exit handler. The idea is that you don’t have to put in a Sinatra.run anywhere in your application, it just happens automatically. I can’t think of a good reason to turn this off.
- env - Most of the time this is overridden by either the command line or the rackup file. A set in an application’s code will override any other previous setting, but this default isn’t used very often.
- root - Setting this has no effect, since it isn’t ever used anywhere in the code (currently…)
- views - Default views dir
- public - Default public dir (public means static files like css and js)
- sessions - Turn on sessions, uses a cookie store by default. I don’t know how to configure the store.
- logging - enables the Rack::CommonLogger middleware.
One at a time:
# Two arguments, key, then value
set :sessions, true
set :logging, false
All at once:
# One argument, a hash mapping key -> value
set :sessions => true,
:logging => false,
:views => 'path/to/views'
### For binary options, you can use enable:
enable :sessions, :logging
Posted in Programming, Sinatra | 1 Comment »
May 20th, 2008 cschneid
Turns out splat routes are much easier than I previously posted. I don’t know when this came into the code, I think you can only get this if you go and check out the newest code.
Straight outta the README:
get '/say/*/to/*' do
# matches /say/hello/to/world
params["splat"] # => ["hello", "world"]
end
get '/download/*.*' do
# matches /download/path/to/file.xml
params["splat"] # => ["path/to/file", "xml"]
end
At this point, you have a nice and easy way of determining what’s in the splat.
Posted in Programming, Sinatra | 1 Comment »
May 17th, 2008 cschneid
Sinatra has a great way of defining routing. You define a route, and then define exactly how it responds right in that same spot. Just the right amount of magic! The routes have only a few basic forms, but it’s more than enough to handle most any situation. In my examples I use get, but there’s no reason you can’t use the same routing with post, put, or delete
No option route
get '/about' do
haml :about
end
Single option
get '/thing/:id' do
@thing = Thing.find(params[:id])
haml :thing_show
end
Multiple options
get '/thing/:id/subthing/:subid' do
@thing = Thing.find(params[:id])
@subthing = SubThing.find(params[:subid])
haml :subthing_show
end
Handling file formats
get '/thing.:format' do
case params[:format]
when 'xml'
render_xml
when 'json'
render_json
end
end
Handling full subfolders
This one is ugly. There’s apparently a feature request + possible patch out there (as mentioned on the mailing list, but it hasn’t been implemented yet.
get '/archive/*' do
star_depth = 1 # /archive comes before the *
splat = request.path_info.split('/')[(star_depth + 1)..-1].join('/')
splat
end
Posted in Programming, Ruby, Sinatra | 3 Comments »
May 11th, 2008 cschneid
I’ve found a very cool new Ruby web framework in the vein of Camping. It’s called Sinatra, and it’s a very minimalist approach to writing RESTful applications.
A quick snippet of code to give you a feel for just how minimal things can get:
require 'rubygems'
require 'sinatra'
get '/' do
"Hello world"
end
Or for something more exciting with sessions:
require 'rubygems'
require 'sinatra'
set_option :sessions, true
get '/' do
session["foo"] ||= 0
session["foo"] += 1
"Hello world, you've asked for foo: #{session["foo"].to_s} number of times"
end
As you can see, it’s dead simple to write a trivial app. Over the next few blog posts, I’m going to get a “semantic pastebin” up and running, complete with database access, backend jobs, form handling, and probably some other cool stuff.
Posted in Programming, Ruby, Sinatra | No Comments »