Permalink
Browse files

Use optparse for couchview. Implemented view generation option.

  • Loading branch information...
1 parent 021121f commit c5397a9b6b8dc2753b1abacac507966b276a3253 @topfunky topfunky committed Sep 11, 2008
Showing with 218 additions and 101 deletions.
  1. +1 −0 .gitignore
  2. +42 −100 bin/couchview
  3. +0 −1 couchrest.gemspec
  4. +5 −0 lib/couch_rest/commands.rb
  5. +71 −0 lib/couch_rest/commands/generate.rb
  6. +99 −0 lib/couch_rest/commands/push.rb
View
@@ -0,0 +1 @@
+.DS_Store
View
@@ -1,111 +1,53 @@
#!/usr/bin/env ruby
-commands = %w{push generate}
+require 'optparse'
+require File.dirname(__FILE__) + "/../lib/couch_rest/commands"
+
+# Set defaults
+options = {
+ :loud => true,
+}
+
+opts = OptionParser.new do |opts|
+ opts.banner = "Usage: #$0 [options] (push|generate) directory database"
+ opts.on('-q', '--quiet', "Omit extra debug info") do
+ options[:loud] = false
+ end
+ opts.on_tail('-h', '--help [push|generate]', "Display detailed help and exit") do |help_command|
+ puts opts
+ case help_command
+ when "push"
+ puts CouchRest::Commands::Push.help
+ when "generate"
+ puts CouchRest::Commands::Generate.help
+ end
+ exit
+ end
+end
+opts.parse!(ARGV)
-command = ARGV[0]
+options[:command] = ARGV.shift
+options[:directory] = ARGV.shift
+options[:trailing_args] = ARGV
-if !commands.include?(command)
- puts <<-USAGE
-Couchview has two modes: push and generate. Run couchview push or couchview generate for usage documentation.
-USAGE
+# There must be a better way to check for extra required args
+unless (["push", "generate"].include?(options[:command]) && options[:directory] && options[:trailing_args])
+ puts(opts)
exit
end
-if ARGV.length == 1
- case command
- when "generate"
- puts <<-GEN
-Usage: couchview generate directory design1 design2 design3 ...
-
-Couchview will create directories and example views for the design documents you specify.
-
-GEN
- when "push"
- puts <<-PUSH
-== Pushing views with Couchview ==
-
-Usage: couchview push directory dbname
-
-Couchview expects a specific filesystem layout for your CouchDB views (see
-example below). It also supports advanced features like inlining of library
-code (so you can keep DRY) as well as avoiding unnecessary document
-modification.
-
-Couchview also solves a problem with CouchDB's view API, which only provides
-access to the final reduce side of any views which have both a map and a
-reduce function defined. The intermediate map results are often useful for
-development and production. CouchDB is smart enough to reuse map indexes for
-functions duplicated across views within the same design document.
-
-For views with a reduce function defined, Couchview creates both a reduce view
-and a map-only view, so that you can browse and query the map side as well as
-the reduction, with no performance penalty.
-
-== Example ==
-
-couchview push foo-project/bar-views baz-database
-
-This will push the views defined in foo-project/bar-views into a database
-called baz-database. Couchview expects the views to be defined in files with
-names like:
-
-foo-project/bar-views/my-design/viewname-map.js
-foo-project/bar-views/my-design/viewname-reduce.js
-foo-project/bar-views/my-design/noreduce-map.js
+# DEBUG
+puts options.inspect
-Pushed to => http://localhost:5984/baz-database/_design/my-design
-
-And the design document:
- {
- "views" : {
- "viewname-map" : {
- "map" : "### contents of view-name-map.js ###"
- },
- "viewname-reduce" : {
- "map" : "### contents of view-name-map.js ###",
- "reduce" : "### contents of view-name-reduce.js ###"
- },
- "noreduce-map" : {
- "map" : "### contents of noreduce-map.js ###"
- }
- }
- }
-
-Couchview will create a design document for each subdirectory of the views
-directory specified on the command line.
-
-== Library Inlining ==
-
-Couchview can optionally inline library code into your views so you only have
-to maintain it in one place. It looks for any files named lib.* in your
-design-doc directory (for doc specific libs) and in the parent views directory
-(for project global libs). These libraries are only inserted into views which
-include the text
-
-//include-lib
-
-or
-
-#include-lib
-
-Couchview is a result of scratching my own itch. I'd be happy to make it more
-general, so please contact me at jchris@grabb.it if you'd like to see anything
-added or changed.
-PUSH
- end
- exit
-end
+# The options hash now contains the resolved defaults
+# and the overrides from the command line.
-require 'rubygems'
-require 'couchrest'
+# Call your class and send it the options here
+# cr = CouchRest::FileManager.new(options[:database_name])
-if command == 'push'
- dirname = ARGV[1]
- dbname = ARGV[2]
- fm = CouchRest::FileManager.new(dbname)
- fm.loud = true
- puts "Pushing views from directory #{dirname} to database #{fm.db}"
- fm.push_views(dirname)
-elsif command == 'generate'
- puts "Under construction ;)"
+case options[:command]
+when "push"
+ CouchRest::Commands::Push.run(options)
+when "generate"
+ CouchRest::Commands::Generate.run(options)
end
View
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
s.bindir = 'bin'
s.executables << 'couchview'
s.executables << 'couchdir'
- s.executables << 'couchcontrol'
s.add_dependency("json", [">= 1.1.2"])
s.add_dependency("rest-client", [">= 0.5"])
end
@@ -0,0 +1,5 @@
+require File.join(File.dirname(__FILE__), "..", "couchrest")
+
+%w(push generate).each do |filename|
+ require File.join(File.dirname(__FILE__), "commands", filename)
+end
@@ -0,0 +1,71 @@
+require 'fileutils'
+
+class CouchRest
+ module Commands
+ module Generate
+
+ def self.run(options)
+ directory = options[:directory]
+ design_names = options[:trailing_args]
+
+ FileUtils.mkdir_p(directory)
+ filename = File.join(directory, "lib.js")
+ self.write(filename, <<-FUNC)
+ // Put global functions here.
+ // Include in your views with
+ //
+ // //include-lib
+ FUNC
+
+ design_names.each do |design_name|
+ subdirectory = File.join(directory, design_name)
+ FileUtils.mkdir_p(subdirectory)
+ filename = File.join(subdirectory, "sample-map.js")
+ self.write(filename, <<-FUNC)
+ function(doc) {
+ // Keys is first letter of _id
+ emit(doc._id[0], doc);
+ }
+ FUNC
+
+ filename = File.join(subdirectory, "sample-reduce.js")
+ self.write(filename, <<-FUNC)
+ function(keys, values) {
+ // Count the number of keys starting with this letter
+ return values.length;
+ }
+ FUNC
+
+ filename = File.join(subdirectory, "lib.js")
+ self.write(filename, <<-FUNC)
+ // Put functions specific to '#{design_name}' here.
+ // Include in your views with
+ //
+ // //include-lib
+ FUNC
+ end
+ end
+
+ def self.help
+ helpstring = <<-GEN
+
+ Usage: couchview generate directory design1 design2 design3 ...
+
+ Couchview will create directories and example views for the design documents you specify.
+
+ GEN
+ helpstring.gsub(/^ /, '')
+ end
+
+ def self.write(filename, contents)
+ puts "Writing #{filename}"
+ File.open(filename, "w") do |f|
+ # Remove leading spaces
+ contents.gsub!(/^ ( )?/, '')
+ f.write contents
+ end
+ end
+
+ end
+ end
+end
@@ -0,0 +1,99 @@
+class CouchRest
+
+ module Commands
+
+ module Push
+
+ def self.run(options)
+ directory = options[:directory]
+ database = options[:trailing_args].first
+
+ fm = CouchRest::FileManager.new(database)
+ fm.loud = options[:loud]
+ puts "Pushing views from directory #{directory} to database #{fm.db}"
+ fm.push_views(directory)
+ end
+
+ def self.help
+ helpstring = <<-GEN
+
+ == Pushing views with Couchview ==
+
+ Usage: couchview push directory dbname
+
+ Couchview expects a specific filesystem layout for your CouchDB views (see
+ example below). It also supports advanced features like inlining of library
+ code (so you can keep DRY) as well as avoiding unnecessary document
+ modification.
+
+ Couchview also solves a problem with CouchDB's view API, which only provides
+ access to the final reduce side of any views which have both a map and a
+ reduce function defined. The intermediate map results are often useful for
+ development and production. CouchDB is smart enough to reuse map indexes for
+ functions duplicated across views within the same design document.
+
+ For views with a reduce function defined, Couchview creates both a reduce view
+ and a map-only view, so that you can browse and query the map side as well as
+ the reduction, with no performance penalty.
+
+ == Example ==
+
+ couchview push foo-project/bar-views baz-database
+
+ This will push the views defined in foo-project/bar-views into a database
+ called baz-database. Couchview expects the views to be defined in files with
+ names like:
+
+ foo-project/bar-views/my-design/viewname-map.js
+ foo-project/bar-views/my-design/viewname-reduce.js
+ foo-project/bar-views/my-design/noreduce-map.js
+
+ Pushed to => http://localhost:5984/baz-database/_design/my-design
+
+ And the design document:
+ {
+ "views" : {
+ "viewname-map" : {
+ "map" : "### contents of view-name-map.js ###"
+ },
+ "viewname-reduce" : {
+ "map" : "### contents of view-name-map.js ###",
+ "reduce" : "### contents of view-name-reduce.js ###"
+ },
+ "noreduce-map" : {
+ "map" : "### contents of noreduce-map.js ###"
+ }
+ }
+ }
+
+ Couchview will create a design document for each subdirectory of the views
+ directory specified on the command line.
+
+ == Library Inlining ==
+
+ Couchview can optionally inline library code into your views so you only have
+ to maintain it in one place. It looks for any files named lib.* in your
+ design-doc directory (for doc specific libs) and in the parent views directory
+ (for project global libs). These libraries are only inserted into views which
+ include the text
+
+ //include-lib
+
+ or
+
+ #include-lib
+
+ Couchview is a result of scratching my own itch. I'd be happy to make it more
+ general, so please contact me at jchris@grabb.it if you'd like to see anything
+ added or changed.
+
+ GEN
+ helpstring.gsub(/^ /, '')
+ end
+
+ end
+
+
+ end
+
+end

0 comments on commit c5397a9

Please sign in to comment.