Sunday, July 5, 2009

A CouchDB Mess

‹prev | My Chain | next›

With my important scenarios complete, I would like to start applying CSS to the homepage. Before I can do that...

I need to load many more meals and recipes into my development database than I currently have. I could manually load them, but that's a hassle. I would much prefer to drop the development database and then seed all of the data from scratch. I can do that, but I have no way to load my CouchDB views.

For testing purposes, I have been loading my CouchDB views in Cucumber's features/support/env.rb:
Before do
$rspec_mocks ||= Spec::Mocks::Space.new

RestClient.put @@db, { }

# TODO need to accomplish this via CouchDB migrations
lucene_index_function = <<_JS
function(doc) {
var ret = new Document();

function zero_pad(i, number_of_zeroes) {
...
}
_JS

doc = { 'transform' => lucene_index_function }

RestClient.put "#{@@db}/_design/lucene",
doc.to_json,
:content_type => 'application/json'

meals_view = <<_JS
{
"views": {
"by_year": {
"map": "function (doc) {
...
},
"language": "javascript"
}
_JS

RestClient.put "#{@@db}/_design/meals",
meals_view,
:content_type => 'application/json'

recipes_view = <<_JS
{
"views": {
"by_date": {
...
},
"language": "javascript"
}
_JS

RestClient.put "#{@@db}/_design/recipes",
recipes_view,
:content_type => 'application/json'
end
Each one of those "..." represents a lot of CouchDB code that clogs up the features/support/env.rb. Clogs it up in way that is not at all re-usable.

I create a couch/_design directory to hold these views:
mkdir -p couch/_design
In there, I create three JSON files: couch/_design/lucene.json, couch/_design/recipes.json and couch/_design/meals.json.

I can then reduce Before block to:
Before do
# For mocking & stubbing in Cucumber
$rspec_mocks ||= Spec::Mocks::Space.new

RestClient.put @@db, { }

# Lucene
file = File.new("couch/_design/lucene.json")
lucene_view = file.read

RestClient.put "#{@@db}/_design/lucene",
lucene_view,
:content_type => 'application/json'

# Meals
file = File.new("couch/_design/meals.json")
meals_view = file.read

RestClient.put "#{@@db}/_design/meals",
meals_view,
:content_type => 'application/json'

# Recipes
file = File.new("couch/_design/recipes.json")
recipes_view = file.read

RestClient.put "#{@@db}/_design/recipes",
recipes_view,
:content_type => 'application/json'
end
Hmm... lotsa duplication in there. All I need to do is, for each JSON file, create a similarly named design document in the CouchDB view. Thinking of it that way, the Before block gets even smaller:
Before do
# For mocking & stubbing in Cucumber
$rspec_mocks ||= Spec::Mocks::Space.new

RestClient.put @@db, { }

Dir.glob("couch/_design/*.json").each do |filename|
document_name = File.basename(filename, ".json")
file = File.new(filename)
json = file.read

RestClient.put "#{@@db}/_design/#{document_name}",
json,
:content_type => 'application/json'
end
end
I really wish that I had done something like this sooner. That feels much better.

I am in pretty good shape now for being able to reload those design documents after wiping my development database. I see an opportunity to go a little bit farther and possibly make some of those design documents test-able. I do not know if I want to go that far at this point, so I will stop here for the day and give it some more thought.

No comments:

Post a Comment