Before the couch_design_docs gem is ready for prime-time (i.e. ready to be used in my Sinatra / CouchDB app), I want a simpler API than is currently exposed. Currently I need to instantiate both a
Store
object (to describe the target CouchDB store) and a Directory
object (to describe the design documents stored on the file system). The Store
object then needs to upload a hash representation of the Directory
object. I would much prefer a single method to upload a design documents directory to a CouchDB store. Something like:CouchDesignDocs.upload_dir(URI, DIR)This convenience method should instantiate
Store
and Directory
objects just I have to by-hand now. The instantiated Store
object should receive the :load
message with an argument of the hash from Directory
. As an RSpec example:describe CouchDesignDocs doThe example fails with
it "should be able to load directory/JS files into CouchDB as design docs" do
store = mock("Store")
Store.stub!(:new).and_return(store)
dir = mock("Directory")
dir.stub!(:to_hash).and_return({ "foo" => "bar" })
Directory.stub!(:new).and_return(dir)
store.
should_receive(:load).
with({ "foo" => "bar" })
CouchDesignDocs.upload_dir("uri", "fixtures")
end
end
cstrom@jaynestown:~/repos/couch_design_docs$ spec spec/couch_design_docs_spec.rbI change the message by defining the method. I change the next message ("wrong number of arguments (2 for 0)") by defining the method with two arguments:
F...........
1)
NoMethodError in 'CouchDesignDocs should be able to load directory/JS files into CouchDB as design docs'
undefined method `upload_dir' for CouchDesignDocs:Module
./spec/couch_design_docs_spec.rb:16:
Finished in 0.011794 seconds
12 examples, 1 failure
def self.upload_dir(db_uri, dir)With that I get this failure:
end
cstrom@jaynestown:~/repos/couch_design_docs$ spec spec/couch_design_docs_spec.rbI make that example pass by defining the methods as I planned from the beginning:
F...........
1)
Spec::Mocks::MockExpectationError in 'CouchDesignDocs should be able to load directory/JS files into CouchDB as design docs'
Mock 'Store' expected :load with ({"foo"=>"bar"}) once, but received it 0 times
./spec/couch_design_docs_spec.rb:12:
Finished in 0.012137 seconds
12 examples, 1 failure
def self.upload_dir(db_uri, dir)After updating the README and the History.txt file, I create an updated gemspec with the built-in Bones rake command:
store = Store.new(db_uri)
dir = Directory.new(dir)
store.load(dir.to_hash)
end
rake gem:specThen I upload to github.
(commit)
Finally, I replace the code from which the
couch_design_docs
gem was extracted with a call to the gem:Before doNice! At one point, that
# For mocking & stubbing in Cucumber
$rspec_mocks ||= Spec::Mocks::Space.new
# Create the DB
RestClient.put @@db, { }
# Upload the design documents with a super-easy gem :)
CouchDesignDocs.upload_dir(@@db, 'couch/_design')
end
Before
block was well over a hundred lines long, mostly because the design documents were embedded directly in that block. Now it is a single line.To make sure that everything is still working, I break the design docs out into the component
.js
files:cstrom@jaynestown:~/repos/eee-code$ find couch/Running the various Cucumber scenarios that exercise the full-stack, including the CouchDB views/design documents as well as the couchdb-lucene design document, I find no failures:
couch/
couch/_design
couch/_design/lucene
couch/_design/lucene/transform.js
couch/_design/recipes
couch/_design/recipes/views
couch/_design/recipes/views/by_date
couch/_design/recipes/views/by_date/map.js
couch/_design/meals
couch/_design/meals/views
couch/_design/meals/views/by_month
couch/_design/meals/views/by_month/map.js
couch/_design/meals/views/by_month/reduce.js
couch/_design/meals/views/by_date
couch/_design/meals/views/by_date/map.js
couch/_design/meals/views/count_by_month
couch/_design/meals/views/count_by_month/map.js
couch/_design/meals/views/count_by_month/reduce.js
couch/_design/meals/views/count_by_year
couch/_design/meals/views/count_by_year/map.js
couch/_design/meals/views/count_by_year/reduce.js
couch/_design/meals/views/by_year
couch/_design/meals/views/by_year/map.js
couch/_design/meals/views/by_year/reduce.js
27 scenariosSay, that's a really convenient gem, it'd be nice to have easy access to it from the command line! I add it to my
9 skipped steps
1 undefined step
226 passed steps
Rakefile
thusly:task :load_design_docs doThat winds up work on the
CouchDesignDocs.upload_dir("http://localhost:5984/eee", "couch/_design")
end
couch_design_docs
gem—an excursion made quite enjoyable thanks to Bones. I still have some features that I would like to add (ability to unit test the .js
files, Javascript function re-use via Erb includes), but it serves my purposes really well as-is.Up tomorrow: figuring out where I was before I decided extracting a gem might be a good idea.
No comments:
Post a Comment