Saturday, September 26, 2009

CouchDB is not a CMS

‹prev | My Chain | next›

On the legacy site, we have several content pages that have yet to make it into the new Sinatra / CouchDB site. The pages include things like an "About this Site" page, an "About Us" page, and pages describing our favorite restaurants.

I could store such pages in the /public directory, but then I would be duplicating headers and footers on each of those pages. As with any duplication, I would have to remember to update the header and footer on each of these static files any time the header/footer Haml partials are updated.

I would like to store these pages in CouchDB, preferably as Textile in a JSON attribute. If the document exists, then the textile would be converted and presented. If the document does not exist, then a 404 would be returned.

To drive this feature, I will describe the fictional resource /foo-bar in an RSpec example:
describe "GET /foo-bar" do
context "without an associated CouchDB document" do
it "should not be found" do
get "/foo-bar"
last_response.status.should == 404
end
end
end
That example passes because Sinatra does not know that resource.

To describe the case when there is a backing CouchDB document, I use this example:
  context "with an associated CouchDB document" do
it "should be found" do
RestClient.stub!(:get).and_return("{}")
get "/foo-bar"
last_response.should be_ok
end
end
end
That example fails because I have no resource to handle it. To get it passing, I need a Sinatra action that responds to something resembling CouchDB resource IDs. Something like this ought to be a good start:
get %r{^/([\-\w]+)$} do |doc_id|
"foo"
end
The textile-couchdb-doc-should-be-found example now passes, but the previous, with-no-corresponding-couchdb-doc example now fails:
1)
'GET /foo-bar without an associated CouchDB document should not be found' FAILED
expected: 404,
got: 200 (using ==)
./spec/eee_spec.rb:605:
The simplest thing that can possibly appease both of these cases is to make a RestClient.get request to the CouchDB resource and, if that fails, to pass handling back to another resource (possibly to be not found anywhere). In other words:
get %r{^/([\-\w]+)$} do |doc_id|
begin
RestClient.get "#{@@db}/#{doc_id}"
rescue RestClient::ResourceNotFound
pass
end
"foo"
end
The pass method comes from Sinatra. It indicates that the currently executing resource does not handle the current request. It passes handling back to Sinatra (in case another resource in the Sinatra application matches) or back to Rack (in case another Rack application is capable of handling this request).

With those two examples passing, I call it a day. I will pick back up tomorrow getting the textile in the document converted to HTML and inserted into the normal Haml layout.

No comments:

Post a Comment