Skip to content

Instantly share code, notes, and snippets.

@harrikauhanen
Created February 19, 2009 14:26
Show Gist options
  • Save harrikauhanen/66941 to your computer and use it in GitHub Desktop.
Save harrikauhanen/66941 to your computer and use it in GitHub Desktop.
#
# Gisted by harri.kauhanen ('AT') gmail.com
#
# Coucher - Super simple RESTful HTTP service with Rack and CouchFoo
# Should work easily with ActiveRecord or other persistence frameworks.
# This demo only supports HTTP GET requests on existing resources.
# With tiny modifications it could support JSON output or Etag caching.
#
# Feel free to use and modify, but let me know your ideas as well, thanks!
#
#
# To run it, you could e.g. 'rackup coucher.ru -p 3000' or attach to any Rack-capable server.
# Or you could easily make it a Rails Metal and run along with the Rails stuff.
#
#
# File: coucher.ru
#
# require 'rubygems'
# require 'rack'
#
# require 'coucher.rb'
# run Coucher.new
#
#
# To consume the service, you could use HTTP GET to e.g. these resources:
#
# http://localhost:3000/people/
# http://localhost:3000/people/52a4e65a6735a65e899a120ef2e6a572
# http://localhost:3000/people/52a4e65a6735a65e899a120ef2e6a572/dogs
# http://localhost:3000/people?name=Harri
# http://localhost:3000/dogs/1793f7d6647b72d4f00c029c1b1649b5/person
#
require 'rubygems'
require 'couch_foo'
class Person < CouchFoo::Base
property :name, String
has_many :dogs
end
class Dog < CouchFoo::Base
property :name, String
property :person_id, String
belongs_to :person
end
#
# Define more models here. Note! No need to define "routes" or anything, HTTP interface just works.
#
class Coucher
def initialize
CouchFoo::Base.set_database(:database => 'people_and_dogs', :host => "localhost:5984")
end
def call(env)
if env['REQUEST_METHOD'] != 'GET'
return fail(400, 'This demo supports only GET requests')
end
slash, classname, id, nesting, other = env['PATH_INFO'].split('/')
if other || classname.nil?
return fail(400, 'Invalid path')
end
begin
clazz = Kernel.const_get(classname.classify)
if id
if nesting
res = clazz.find(id).send(nesting)
if res.nil?
return [200, {"Content-Type" => "text/xml"}, ["<?xml version='1.0' encoding='UTF-8'?><nil />"]]
end
else
res = clazz.find(id)
end
else
conditions = CGI.parse(env['QUERY_STRING'])
res = clazz.all(:conditions => conditions)
end
return [200, {"Content-Type" => "text/xml"}, [res.to_xml]]
rescue CouchFoo::DocumentNotFound => e # or an ActiveRecord exception
return fail(404, 'Resource not found')
rescue NameError
return fail(400, "Class not found")
end
end
def fail(code, message)
return [code,
{"Content-Type" => "text/xml"},
["<?xml version='1.0' encoding='UTF-8'?><error>#{message}</error>"]]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment