• Stars
    star
    142
  • Rank 258,495 (Top 6 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 16 years ago
  • Updated over 15 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

lol

Sinatra's Hat

Easy REST-ful apps with Sinatra.

Using Sinatra's Hat is centered around the mount method, which is added to Sinatra::Base. It takes at bare minimum a model class. This class will be mounted as a REST-ful resource, giving you all the CRUD actions, as well as new and edit actions. Let's look at some code:

mount Article

Now you've basically got the same functionality as you'll get in Rails by running script/generate scaffold Article. The views for your Article will live in views/articles, and be named index.erb, show.erb, etc.

You can look at my Hatter project, or the examples/ directory in this one to see this in action.

Go ahead, try it.

ORM agnostic? Or ORM atheist?

By default, Sinatra's Hat works with ActiveRecord. That means that going to /articles will simply call Article.all to populate the @articles instance variable. Going to /articles/2 will call Article.find_by_id(2) to populate the @article instance variable.

We call find_by_id instead of find because the record option should simply return nil when the record can't be found.

Not every class is an ActiveRecord though (especially if you're not using ActiveRecord). That's why you can use the finder and record options.

This example will show you how to use DataMapper with Sinatra's Hat:

mount Article do
  finder { |model, params| model.all }
  record { |model, params| model.first(:id => params[:id]) }
end

As you can see, both finder and record take a block, which will get passed the "model" and params for each request. The reason you should use the "model" argument instead of referencing the class directly is that when you start nesting mounted models, then Sinatra's Hat will attempt to pass the association proxy as the model argument instead of the class itself.

"Nested mounted models?" you ask?

Nested mounted models.

You don't want to have to expose your entire application at the top level of URL paths. That wouldn't be very RESTful, and more importantly, it'd be damn ugly. So Sinatra's Hat allows you to nest resources:

mount Article do
  mount Comment
end

With this example, you'd get /articles/1/comments, /articles/1/comments/1 and all the rest of the actions you get for articles, just nested. As long as your Article model supports a comments association proxy, then the finder and record options for Comment will automatically scope their results by the parent Article.

Limiting routes

By default, Sinatra's Hat creates seven routes for each mounted model (the four ones for CRUD actions plus the routes for index, new and edit action), but you can reduce the number of available routes with only:

mount Article do
  only :index, :show
end

Only the listed actions will return valid responses; requests for the "missing" routes will produce 404 "Not Found" HTTP responses.

Basic Auth

To protect actions using basic authentication, you can use the protect method.

mount Article do
  protect :create, :update, :destroy, :username => "foo", :password => "bar", :realm => "BLOGZ"
end

The above snippet will protect your CUD actions with basic auth, using the username "foo" and password "bar". The realm for the basic auth prompt will say "BLOGZ".

If you want to protect all of your actions, you cay say protect :all.

.xml, .json, .yaml, and whatever else you want

If a request has a format extensions, then Sinatra's Hat will first check to see if it has a custom way of serializing that format. To specify a custom formatter, you can use the formats hash:

mount Article do
  formats[:ruby] = { |data| data.inspect }
end

With that custom formatter, a request to /articles.ruby will return the equivalent of Article.all.inspect.

Automatic formatters

If you don't specify a custom formatter, then Sinatra's Hat will try to call to_#{format} on the record object. That means that with most ORMs, things like to_xml, to_json, and to_yaml will be supported right out of the box.

Requests for unknow formats will produce 406 "Not Acceptable" HTTP responses.

Default Flows

Sinatra's Hat has some default flows:

After the create action

On Success: If a record is successfully created, Sinatra's Hat will redirect to that record's show page.

On Failure: If a record cannot be saved, Sinatra's Hat will render the new action.

After the Update action

On Success: If a record is successfully updated, Sinatra's Hat will redirect to that record's show page.

On Failure: If a record cannot be updated, Sinatra's Hat will render the edit action.

Custom Flows

To specify custom flows for your actions, you can use the after method.

Let's say that after a user creates an Article, you want to render the article's edit action, and if it can't be created, you want to redirect back to the articles index.

mount Article do
  after :create do |on|
    on.success { |record| render(:edit) }
    on.failure { |record| redirect(:index) }
  end
end

Only :create and :update actions allow to handle success and failure differently; for the other actions you can customize only the success result and if something goes wrong (i.e., when a record cannot be found) they will simply return a 404 "Not Found" HTTP response.

redirect options

When specifying a custom redirect, you can pass one of a few things:

A String

When you pass redirect a string, the redirect will go to that string.

after :create do |on|
  on.success { |record| redirect("/articles/#{record.to_param}") }
end

A Record

When you pass redirect a record, the redirect will go to the show action for that record.

after :create do |on|
  on.success { |record| redirect(record) }
end

A symbol

If you pass redirect the name of an action as a symbol (like :index), then the redirect will go to the correct path for that option:

after :create do |on|
  on.success { redirect(:index) }
end

When the action requires a record (like :show), then just pass the record as a second argument:

after :create do |on|
  on.success { |record| redirect(:show, record) }
end

Responding with a render

When you want your response to just render a template, just call render with the name of the template:

after :create do |on|
  on.failure { |record| render(:new) }
end

Todo

  • Make last_modified calls more efficient
  • Investigate other forms of caching

Other Info

(c) Copyright 2008-2009 Pat Nakajima. All Rights Reserved.

More Repositories

1

slidedown

Generate syntax-highlighted slides from Markdown
JavaScript
439
star
2

rack-flash

If you're using Sinatra, you should use sinatra-flash instead.
Ruby
181
star
3

jquery-glow

Make your elements glow. Ooooh.
JavaScript
162
star
4

aintablog

Open source tumblog/aggregator. Do not use.
Ruby
122
star
5

better-edit-in-place

Easy editing in place for RESTful web apps.
JavaScript
92
star
6

roleful

Generic roles for you and your objects
Ruby
85
star
7

jquery-livesearch

Adds some live search to your page
JavaScript
74
star
8

capinatra

You should probably use Heroku instead..
Ruby
62
star
9

acts_as_fu

When you need a dash of ActiveRecord and nothing more
Ruby
57
star
10

elementor

View testing that doesn't suck.
Ruby
32
star
11

proxen

Easy method_missing proxying
Ruby
32
star
12

sms-rb

Send text messages with Twilio. Easily.
Ruby
32
star
13

calendar-maker

Rails plugin to build a simple calendar scaffold, with events signified by class names added to the day.
Ruby
32
star
14

many-mailers

Support for multiple SMTP servers in ActionMailer
Ruby
28
star
15

method-missing-js

Like Ruby's method_missing but for JabaScript
JavaScript
25
star
16

aspectory

Callbacks for your classes
Ruby
25
star
17

capistrano-bells

Recipes to get your app up and running quickly and easily.
Ruby
25
star
18

whitespace

It strips whitespace. That's it.
Ruby
23
star
19

makers-mark

Syntax highlight your markdown.
Ruby
23
star
20

jquery-jk

Easy keyboard shortcuts for traversing lists (like Gmail)
JavaScript
20
star
21

fixjour

Ruby
18
star
22

jquery-ajax-queue

Provides a way to limit certain AJAX requests to be submitted one at a time.
JavaScript
18
star
23

screw-driver

A way to automate the running of your Screw.Unit specs.
JavaScript
15
star
24

minijs

A small, jQuery-esque JavaScript library
JavaScript
14
star
25

optimus-prime

Something easy without function introspection
Ruby
13
star
26

the-little-schemer-in-ruby

Examples from The Little Schemer ported to Ruby (and scheme).
Ruby
13
star
27

gemifest

Like Heroku's gem manifests, but for your own computer
Ruby
11
star
28

augment-github

Bookmarklet to augment your GitHub dashboard repository information
JavaScript
10
star
29

WhereWhen

Where have you been? And when?
Swift
10
star
30

hatter

An example app using Sinatra's Hat, acts-as-fu, and SemiFormal
Ruby
10
star
31

action-query

jQuery and ActiveRecord, sitting in a tree...
Ruby
9
star
32

nakatype

Prototype extensions that I find myself using frequently, or just ideas that I think would be fun.
JavaScript
9
star
33

modal-overlays

The easiest way to create modal overlays I could muster
JavaScript
8
star
34

pretty-buttons

Inspired by the Stop Design post and Gmail's buttons
8
star
35

jquery-easter-eggs

Hidden behaviors based on your visitors’ typing into the document.
JavaScript
7
star
36

rack-unbasic

Wrap HTTP authentication in more tender UIs via Rack middleware
7
star
37

semi-formal

form_for outside of ActionView
Ruby
7
star
38

bookmarklet-factory

It creates bookmarklets! Code's kind of ugly, but whatever!
Ruby
7
star
39

poundie

A Campfire Bot
Ruby
6
star
40

test-js

Write JavaScript tests that don't need no stinkin' browser.
Ruby
6
star
41

mytweets-rb

Get all your tweets from Twitter
Ruby
6
star
42

rip-server

Like `gem server` but for Rip.
Ruby
6
star
43

nest-unit

Nested contexts for test/unit tests
Ruby
6
star
44

key-val

Easily get or set key/value pairs from ~/.key-val
Ruby
6
star
45

twitter-db

don't do this
Ruby
6
star
46

syntaxily

Syntax highlighting for strings and stuff
Ruby
5
star
47

middleware-talk

Talk about Rack/Middleware for nyc.rb
Ruby
5
star
48

nakajima-tracker

For tracking nakajimas
Ruby
5
star
49

fixjour-2

A rewrite of fixjour.
Ruby
5
star
50

github-client

Another GitHub API client. For fun, not for real.
Ruby
5
star
51

another

Swiss army knife of project templates.
JavaScript
5
star
52

thunder-app

Before lightning (talks) comes thunder
Ruby
5
star
53

HueEntertainmentSwift

A way to talk to the Hue Entertainment API.
Swift
5
star
54

jj

A JavaScript mock framework
JavaScript
4
star
55

rebound

Bind any instance of UnboundMethod to any object, regardless of class.
Ruby
4
star
56

screw-cucumber-talk

A Cucumber discussion.
4
star
57

screw-fixtures

Fixtures for Screw.Unit tests
3
star
58

lee-me

Comes correct.
Ruby
3
star
59

LilClock

A lil clock for visionOS
Swift
2
star
60

pat.swift

swift stuff i tend to use, you probably don't want to
Swift
2
star
61

hans-zimmer

Sound effects for web pages
CoffeeScript
2
star
62

dash-ci

Metrics and build failure notification for your continuous integration build
Ruby
2
star
63

twitter-client

Another one.
Ruby
2
star
64

set-js

A Ruby-esque Set implementation in JavaScript. (WIP)
2
star
65

screenwriting-textmate-bundle

A copy of the code from Google Code
2
star
66

feature-hider

A way to hide features based on Rails environment.
Ruby
2
star
67

4sq.pat.fm

Show all of your foursquare checkins on a google map
Ruby
1
star
68

test-repo

Test repo
1
star
69

my-twitter

Ruby
1
star
70

nakajima-dot-js

MY .js DIRECTORY FOR ALL TO SEE
CoffeeScript
1
star
71

ezcoffee

Generates quick coffeescript projects and compiles them. Scratching my own itch.
Ruby
1
star
72

poundie-pic

Poundie plugin to post first google images result to Campfire
Ruby
1
star
73

poundie-weather

Poundie plugin to post weather information to campfire
Ruby
1
star
74

langerdotjs

~/.js/
Ruby
1
star
75

talkerton

Say things with say
Ruby
1
star
76

offlinezor

Playing with HTML5's offline cache
Ruby
1
star
77

poundie-urban-dictionary

A Poundie plugin for posting urban dictionary definitions to campfire
Ruby
1
star
78

poundie-last-tweet

Posts the last tweet of a given twitter user to campfire
Ruby
1
star
79

shoe-boxer

A Shoes app for finding and running Shoes apps in Shoes.
Ruby
1
star
80

jquery-laser-page

Add lasers to your page with this one weird trick.
JavaScript
1
star
81

poundie-wikipedia

Poundie plugin to post wikipedia link for a given search term
Ruby
1
star
82

HandShapeClassifier

Swift
1
star
83

poundie-shake-shack

Poundie plugin to post latest image from Shake Shack cam to Campfire
Ruby
1
star
84

LiveModelDemo

Swift
1
star
85

ScrollObserverDemo

Swift
1
star
86

atom-branch-status

Atom plugin to show current branch status
CoffeeScript
1
star
87

home-manager

Nix
1
star