Time to implement my directory watcher feature in couch_docs for real. First things first—my work from last night:
cstrom@whitefall:~/repos/couch_docs$ git stGone:
# On branch master
# Changed but not updated:
# (use "git add..." to update what will be committed)
# (use "git checkout --..." to discard changes in working directory)
#
# modified: Rakefile
# modified: couch_docs.gemspec
# modified: lib/couch_docs.rb
# modified: lib/couch_docs/command_line.rb
#
no changes added to commit (use "git add" and/or "git commit -a")
cstrom@whitefall:~/repos/couch_docs$ git checkout -- Rakefile couch_docs.gemspec lib/couch_docs.rb lib/couch_docs/command_line.rbI am fairly obsessive about deleting prototype code. The code that I produced might be fine, it might not. It is more than likely that it is not great because I was learning something new and making mistakes along the way. I do not want to be in a position to be building on crap code. I alway build on the simplest thing that can possibly work. The only way to be sure of that (that I know of) is BDD.
cstrom@whitefall:~/repos/couch_docs$ git st
# On branch master
nothing to commit (working directory clean)
Soooo...
it "should know watch" doThis fails because there is no
@it = CommandLine.new(%w(load dir uri -w))
@it.options[:watch].should be_true
end
OptParse
code supporting the -w
switch:cstrom@whitefall:~/repos/couch_docs$ spec ./spec/couch_docs_spec.rb(that pending spec is a note for version 1.2)
..........................*................F
Pending:
CouchDocs::DesignDirectory a valid directory should work with absolute !code paths (Not Yet Implemented)
./spec/couch_docs_spec.rb:314
1)
OptionParser::InvalidOption in 'CouchDocs::CommandLine an instance that uploads to a CouchDB database should know watch'
invalid option: -w
./spec/couch_docs_spec.rb:483:in `new'
./spec/couch_docs_spec.rb:483:
Finished in 0.225247 seconds
44 examples, 1 failure, 1 pending
To make the example pass, I add:
opts.on("-w", "--watch", "Watch the directory for changes, uploading when detected") doDo I want to add a time to that? I think not. I will stick with 2 seconds and await pull requests if anyone wants something different. Keep it small...
@options[:watch] = true
end
Now that I have the command line options being set in response to the
-w
switch, I need to actually do something with it. Currently, the push code looks like:#...If the
when "push"
if @options[:destructive]
CouchDocs.destructive_database_create(options[:couchdb_url])
end
CouchDocs.put_dir(@options[:couchdb_url],
@options[:target_dir])
#...
-w
switch is present, the put_dir
should be run as long as the directory watcher run. If the switch is not present, then put_dir
should be run once. Happily, the directory watcher gem can run one or indefinitely, so I can exploit that. First, I add directory_watcher as a dependency in my Bones 2.5 Rakefile:depend_on 'rest-client'And regenerate my gemspec with
depend_on 'json'
depend_on 'directory_watcher'
rake gem:spec
.To describe normal usage, I use this example:
before(:each) doIn other words, I want the
CouchDocs.stub!(:put_dir)
@dw = mock("Directory Watcher").as_null_object
DirectoryWatcher.stub!(:new).and_return(@dw)
end
it "should run once normally" do
@dw.should_receive(:run_once)
@it = CommandLine.new(%w(push uri dir))
@it.run
end
DirectoryWatcher
object to be told to run once. That fails because I am not using a directory watcher yet, so I wrap the current put_dir
call inside one:dw = DirectoryWatcher.new @options[:target_dir]I do not have a full stack test of this at the moment, so before moving on, I verify that the command line still pushes directories to CouchDB (it does).
dw.add_observer do |*args|
CouchDocs.put_dir(@options[:couchdb_url],
@options[:target_dir])
end
dw.run_once
Now I need to start the watcher if the
:watch
option is set:it "should start a watcher with -w" doTo make that pass, I add a simple conditional:
@dw.should_receive(:start)
@it = CommandLine.new(%w(push uri dir -w))
@it.run
end
dw = DirectoryWatcher.new @options[:target_dir]That should just about do it. I need to add some settings to directory watched (glob all changes in sub-directories, set the watch interval for 2 seconds:
dw.add_observer do |*args|
CouchDocs.put_dir(@options[:couchdb_url],
@options[:target_dir])
end
if @options[:watch]
dw.start
else
dw.run_once
end
dw = DirectoryWatcher.new @options[:target_dir]I also add an endless loop that can be
dw.glob = '**/*'
dw.interval = 2.0
dw.add_observer do |*args|
CouchDocs.put_dir(@options[:couchdb_url],
@options[:target_dir])
end
if @options[:watch]
dw.start
begin
sleep 30 while true
rescue Interrupt
dw.stop
puts
end
else
dw.run_once
end
Ctrl-C
'd top stop the watcher. That behavior seems like more trouble than it is worth to BDD so I simply add it. The other two options are not new behaviors, just settings, so no new specs there either.That about does it. I do not know if the resulting code is any simpler that last night's prototype. I do know that it is as simple as I can make it. That is what matters most to me.
Tomorrow: document and release couch_docs 1.1.
Day #39
No comments:
Post a Comment