couch 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Johannes J. Schmidt
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ = couch
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Johannes J. Schmidt. See LICENSE for details.
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require File.join(File.dirname(__FILE__), 'lib', 'couch', 'version')
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "couch"
9
+ gem.version = Couch::VERSION
10
+ gem.summary = %Q{Standalone CouchDB Application Development Suite}
11
+ gem.description = %Q{With Couch you can easy build a standalone CouchDB application.}
12
+ gem.email = "schmidt@netzmerk.com"
13
+ gem.homepage = "http://github.com/jo/couch"
14
+ gem.authors = ["Johannes J. Schmidt"]
15
+ gem.rubyforge_project = "couch"
16
+ gem.add_dependency "thor", ">= 0.13.4"
17
+ gem.add_dependency "rest-client", ">= 1.4.1"
18
+ gem.add_dependency "json_pure", ">= 1.2.2"
19
+ gem.add_development_dependency "rspec", ">= 1.2.9"
20
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ Jeweler::RubyforgeTasks.new do |rubyforge|
24
+ rubyforge.doc_task = "rdoc"
25
+ end
26
+ rescue LoadError
27
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
28
+ end
29
+
30
+ require 'spec/rake/spectask'
31
+ Spec::Rake::SpecTask.new(:spec) do |spec|
32
+ spec.libs << 'lib' << 'spec'
33
+ spec.spec_files = FileList['spec/**/*_spec.rb']
34
+ end
35
+
36
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
37
+ spec.libs << 'lib' << 'spec'
38
+ spec.pattern = 'spec/**/*_spec.rb'
39
+ spec.rcov = true
40
+ end
41
+
42
+ task :spec => :check_dependencies
43
+
44
+ task :default => :spec
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "couch #{Couch::VERSION}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby1.8
2
+
3
+ couch_path = File.expand_path('../../lib', __FILE__)
4
+ $:.unshift(couch_path) if File.directory?(couch_path) && !$:.include?(couch_path)
5
+
6
+ require 'couch/commands'
@@ -0,0 +1,89 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{couch}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Johannes J. Schmidt"]
12
+ s.date = %q{2010-03-07}
13
+ s.default_executable = %q{couch}
14
+ s.description = %q{With Couch you can easy build a standalone CouchDB application.}
15
+ s.email = %q{schmidt@netzmerk.com}
16
+ s.executables = ["couch"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "bin/couch",
28
+ "couch.gemspec",
29
+ "lib/couch.rb",
30
+ "lib/couch/actions/base.rb",
31
+ "lib/couch/actions/pull.rb",
32
+ "lib/couch/actions/push.rb",
33
+ "lib/couch/commands.rb",
34
+ "lib/couch/commands/destroy.rb",
35
+ "lib/couch/commands/generate.rb",
36
+ "lib/couch/commands/pull.rb",
37
+ "lib/couch/commands/push.rb",
38
+ "lib/couch/core_ext/string/inflections.rb",
39
+ "lib/couch/generators.rb",
40
+ "lib/couch/generators/application/USAGE",
41
+ "lib/couch/generators/application/application_generator.rb",
42
+ "lib/couch/generators/application/templates/README",
43
+ "lib/couch/generators/application/templates/_attachments/index.html",
44
+ "lib/couch/generators/application/templates/_attachments/stylesheets/application.css",
45
+ "lib/couch/generators/application/templates/_id",
46
+ "lib/couch/generators/application/templates/couchrc",
47
+ "lib/couch/generators/application/templates/gitignore",
48
+ "lib/couch/generators/application/templates/validate_doc_update.js",
49
+ "lib/couch/generators/base.rb",
50
+ "lib/couch/mapper.rb",
51
+ "lib/couch/version.rb",
52
+ "spec/couch_spec.rb",
53
+ "spec/spec.opts",
54
+ "spec/spec_helper.rb"
55
+ ]
56
+ s.homepage = %q{http://github.com/jo/couch}
57
+ s.rdoc_options = ["--charset=UTF-8"]
58
+ s.require_paths = ["lib"]
59
+ s.rubyforge_project = %q{couch}
60
+ s.rubygems_version = %q{1.3.6}
61
+ s.summary = %q{Standalone CouchDB Application Development Suite}
62
+ s.test_files = [
63
+ "spec/spec_helper.rb",
64
+ "spec/couch_spec.rb"
65
+ ]
66
+
67
+ if s.respond_to? :specification_version then
68
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
69
+ s.specification_version = 3
70
+
71
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
72
+ s.add_runtime_dependency(%q<thor>, [">= 0.13.4"])
73
+ s.add_runtime_dependency(%q<rest-client>, [">= 1.4.1"])
74
+ s.add_runtime_dependency(%q<json_pure>, [">= 1.2.2"])
75
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
76
+ else
77
+ s.add_dependency(%q<thor>, [">= 0.13.4"])
78
+ s.add_dependency(%q<rest-client>, [">= 1.4.1"])
79
+ s.add_dependency(%q<json_pure>, [">= 1.2.2"])
80
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
81
+ end
82
+ else
83
+ s.add_dependency(%q<thor>, [">= 0.13.4"])
84
+ s.add_dependency(%q<rest-client>, [">= 1.4.1"])
85
+ s.add_dependency(%q<json_pure>, [">= 1.2.2"])
86
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
87
+ end
88
+ end
89
+
@@ -0,0 +1,33 @@
1
+ require 'yaml'
2
+
3
+ module Couch
4
+ CONFIG_FILENAME = ".couchrc"
5
+
6
+ def self.root
7
+ @root ||= find_root
8
+ end
9
+
10
+ def self.database
11
+ config["database"]
12
+ end
13
+
14
+ def self.config
15
+ @config ||= YAML.load(File.open config_file)
16
+ end
17
+
18
+ def self.config_file
19
+ File.join root, CONFIG_FILENAME
20
+ end
21
+
22
+ private
23
+
24
+ def self.find_root
25
+ cwd = Dir.pwd
26
+ return cwd if File.exists?(File.join(cwd, CONFIG_FILENAME))
27
+ Dir.chdir("..") do
28
+ find_root unless cwd == Dir.pwd
29
+ end
30
+ rescue SystemCallError
31
+ # could not chdir, no problem just return
32
+ end
33
+ end
@@ -0,0 +1,40 @@
1
+ require 'couch'
2
+ require 'couch/mapper'
3
+ require 'couch/core_ext/string/inflections'
4
+
5
+ require 'rubygems'
6
+ require "rest_client"
7
+ require 'json'
8
+ require 'thor/group'
9
+
10
+ module Couch
11
+ module Actions
12
+ class Base < Thor::Group
13
+ attr_reader :mapper
14
+
15
+ include Thor::Actions
16
+
17
+ class_option :database, :type => :string
18
+
19
+ def initialize(*args)
20
+ super
21
+ @mapper = Mapper.new(destination_root)
22
+ end
23
+
24
+ def self.banner
25
+ "couch #{to_s.split('::').last.underscore}"
26
+ end
27
+
28
+ private
29
+
30
+ def database
31
+ options[:database] || Couch.database
32
+ end
33
+
34
+ def url_for(id)
35
+ File.join database, id
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,48 @@
1
+ require 'couch/actions/base'
2
+
3
+ module Couch
4
+ module Actions
5
+ class Pull < Base
6
+ add_runtime_options!
7
+
8
+ def pull_me
9
+ id = mapper.doc["_id"]
10
+ url = url_for(id)
11
+
12
+ say "Pulling from %s..." % url
13
+
14
+ resp = RestClient.get url + "?attachments=true"
15
+ response = JSON.parse(resp.body)
16
+ map_doc(response)
17
+ rev = response["_rev"]
18
+
19
+ say "Checked out %s" % rev
20
+ rescue RestClient::ResourceNotFound
21
+ say "Error: Document %s does not exist!" % id
22
+ end
23
+
24
+ private
25
+
26
+ def map_doc(doc, dirname = destination_root)
27
+ doc.each do |key, value|
28
+ next if key == "_attachments"
29
+ filename = File.join(dirname, key)
30
+ if value.is_a?(String)
31
+ create_file filename, value
32
+ else
33
+ Dir.mkdir(filename) unless File.directory?(filename)
34
+ map_doc value, File.join(dirname, key)
35
+ end
36
+ end
37
+ map_doc_attachments(doc["_attachments"], dirname) if doc["_attachments"]
38
+ end
39
+
40
+ def map_doc_attachments(doc, dirname)
41
+ doc.each do |key, value|
42
+ filename = File.join(dirname, "_attachments", key)
43
+ create_file filename, value["data"].unpack("m")
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,37 @@
1
+ require 'couch/actions/base'
2
+
3
+ module Couch
4
+ module Actions
5
+ class Push < Base
6
+ def create_database_unless_exists
7
+ RestClient.put database, nil
8
+ say "Created database %s" % database
9
+ rescue RestClient::PreconditionFailed
10
+ end
11
+
12
+ def push
13
+ doc = mapper.doc
14
+ url = url_for(doc["_id"])
15
+
16
+ say "Pushing to %s..." % url
17
+
18
+ resp = RestClient.put url, doc.to_json
19
+ response = JSON.parse(resp.body)
20
+
21
+ if response["ok"]
22
+ rev = response["rev"]
23
+ File.open File.join(destination_root, "_rev"), "w" do |file|
24
+ file << rev
25
+ end
26
+
27
+ say "Pushed %s" % rev
28
+ else
29
+ say "Error occured: %s" % response.inspect
30
+ end
31
+
32
+ rescue RestClient::Conflict
33
+ say "Conflict! Try to pull first or delete ./_rev."
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,38 @@
1
+ if ARGV.empty?
2
+ ARGV << '--help'
3
+ end
4
+
5
+ HELP_TEXT = <<-EOT
6
+ Usage: couch COMMAND [ARGS]
7
+
8
+ The most common couch commands are:
9
+ generate Generate new code (short-cut alias: "g")
10
+ push Push application code to CouchDB
11
+ pull Pull latest application code from CouchDB
12
+
13
+ In addition to those, there are:
14
+ destroy Undo code generated with "generate"
15
+
16
+ All commands can be run with -h for more information.
17
+ EOT
18
+
19
+
20
+ case ARGV.shift
21
+ when 'g', 'generate'
22
+ require 'couch/commands/generate'
23
+ when 'destroy'
24
+ require 'couch/commands/destroy'
25
+ when 'push'
26
+ require 'couch/commands/push'
27
+ when 'pull'
28
+ require 'couch/commands/pull'
29
+
30
+ when '--help', '-h'
31
+ puts HELP_TEXT
32
+ when '--version', '-v'
33
+ require 'couch/version'
34
+ puts "Couch #{Couch::VERSION}"
35
+ else
36
+ puts "Error: Command not recognized"
37
+ puts HELP_TEXT
38
+ end
@@ -0,0 +1,9 @@
1
+ require 'couch/generators'
2
+
3
+ if [nil, "-h", "--help"].include?(ARGV.first)
4
+ Couch::Generators.help 'destroy'
5
+ exit
6
+ end
7
+
8
+ name = ARGV.shift
9
+ Couch::Generators.invoke name, ARGV, :behavior => :revoke, :destination_root => Couch.root
@@ -0,0 +1,9 @@
1
+ require 'couch/generators'
2
+
3
+ if [nil, "-h", "--help"].include?(ARGV.first)
4
+ Couch::Generators.help 'generate'
5
+ exit
6
+ end
7
+
8
+ name = ARGV.shift
9
+ Couch::Generators.invoke name, ARGV, :behavior => :invoke, :destination_root => Couch.root
@@ -0,0 +1,4 @@
1
+ require 'couch'
2
+ require 'couch/actions/pull'
3
+
4
+ Couch::Actions::Pull.start ARGV, :destination_root => Couch.root
@@ -0,0 +1,4 @@
1
+ require 'couch'
2
+ require 'couch/actions/push'
3
+
4
+ Couch::Actions::Push.start ARGV, :destination_root => Couch.root
@@ -0,0 +1,50 @@
1
+ # String inflections define new methods on the String class to transform names for different purposes.
2
+ # For instance, you can figure out the name of a database from the name of a class.
3
+ #
4
+ # "ScaleScore".underscore # => "scale_score"
5
+
6
+ class String
7
+ # +camelize+ converts strings to UpperCamelCase.
8
+ #
9
+ # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
10
+ #
11
+ # Examples:
12
+ # "scale_score".camelize # => "ScaleScore"
13
+ # "scale_score/errors".camelize # => "ScaleScore::Errors"
14
+ def camelize
15
+ self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
16
+ end
17
+
18
+ # Makes an underscored, lowercase form from the expression in the string.
19
+ #
20
+ # +underscore+ will also change '::' to '/' to convert namespaces to paths.
21
+ #
22
+ # "ScaleScore".underscore # => "scale_score"
23
+ # "Couch::Generators".underscore # => couch/generators
24
+ def underscore
25
+ self.gsub(/::/, '/').
26
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
27
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
28
+ tr("-", "_").
29
+ downcase
30
+ end
31
+
32
+ # Capitalizes the first word and turns underscores into spaces.
33
+ # This is meant for creating pretty output.
34
+ #
35
+ # Examples:
36
+ # "employee_salary" # => "Employee salary"
37
+ def humanize
38
+ self.gsub(/_/, " ").capitalize
39
+ end
40
+
41
+ # Create a class name
42
+ # Note that this returns a string and not a Class. (To convert to an actual class
43
+ # follow +classify+ with +constantize+.)
44
+ #
45
+ # Examples:
46
+ # "post".classify # => "Post"
47
+ def classify
48
+ self.camelize
49
+ end
50
+ end
@@ -0,0 +1,62 @@
1
+ require 'couch'
2
+ require 'couch/generators/base'
3
+
4
+ module Couch
5
+ module Generators
6
+ # Receives a name, arguments and the behavior to invoke the generator.
7
+ # It's used as the default entry point for generate and destroy commands.
8
+ def self.invoke(name, args = ARGV, config = {})
9
+ if klass = lookup(name)
10
+ args << "--help" if args.empty? && klass.arguments.any? { |a| a.required? }
11
+ klass.start(args, config)
12
+ else
13
+ puts "Could not find generator #{name}."
14
+ end
15
+ end
16
+
17
+ # Show help message with available generators.
18
+ def self.help(command = 'generate')
19
+ path = File.expand_path("../generators/*/*_generator.rb", __FILE__)
20
+ generators = Dir.glob(path)
21
+ generators.map! { |f| File.basename(f) }
22
+ generators.map! { |n| n.sub!(/_generator\.rb$/, '') }
23
+ longest_name = generators.map { |g| g.size }.sort.first
24
+ generators.map! { |g| "%s # %s" % [g.ljust(longest_name), lookup(g).info] }
25
+
26
+ puts "Usage: couch #{command} GENERATOR [args] [options]"
27
+ puts
28
+ puts "General options:"
29
+ puts " -h, [--help] # Print generators options and usage"
30
+ puts " -p, [--pretend] # Run but do not make any changes"
31
+ puts " -f, [--force] # Overwrite files that already exist"
32
+ puts " -s, [--skip] # Skip files that already exist"
33
+ puts " -q, [--quiet] # Supress status output"
34
+ puts
35
+ puts "Please choose a generator below."
36
+ puts
37
+ puts generators
38
+ end
39
+
40
+ protected
41
+
42
+ def self.lookup(name)
43
+ # real path
44
+ path = File.expand_path("../generators/#{name}/#{name}_generator.rb", __FILE__)
45
+ # no matches?
46
+ unless File.exists?(path)
47
+ # try to find by prefix
48
+ found = Dir.glob(File.expand_path("../generators/#{name}*/#{name}*_generator.rb", __FILE__))
49
+ if found.size == 1
50
+ path = found.first
51
+ name = File.basename(path).sub(/_generator\.rb$/, '')
52
+ end
53
+ end
54
+ require path
55
+ const_get "#{name.classify}Generator"
56
+ rescue LoadError => e
57
+ raise unless e.message =~ /#{Regexp.escape(path)}$/
58
+ rescue Exception => e
59
+ warn "[WARNING] Could not load generator #{path.inspect}. Error: #{e.message}.\n#{e.backtrace.join("\n")}"
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,10 @@
1
+ Description:
2
+ The 'application' generator creates a new Couch application
3
+ with a default directory structure and configuration
4
+ at the path you specify.
5
+
6
+ Example:
7
+ couch generate application ~/couch/weblog
8
+
9
+ This generates a skeletal Couch installation in ~/couch/weblog.
10
+ See the README in the newly created application to get going.
@@ -0,0 +1,53 @@
1
+ module Couch::Generators
2
+ class ApplicationGenerator < Base
3
+ argument :app_path, :type => :string
4
+
5
+ class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false,
6
+ :desc => "Skip Git ignores and keeps"
7
+
8
+
9
+ def create_root
10
+ self.destination_root = File.expand_path(app_path, destination_root)
11
+
12
+ empty_directory '.'
13
+ FileUtils.cd(destination_root) if File.directory?(destination_root)
14
+ end
15
+
16
+ def create_root_files
17
+ template "couchrc", ".couchrc"
18
+ copy_file "README"
19
+ copy_file "gitignore", ".gitignore" unless options[:skip_git]
20
+ template "_id"
21
+ copy_file "validate_doc_update.js"
22
+ empty_directory_with_gitkeep "lists"
23
+ empty_directory_with_gitkeep "shows"
24
+ empty_directory_with_gitkeep "updates"
25
+ empty_directory_with_gitkeep "views"
26
+ end
27
+
28
+ def create_attachments_files
29
+ empty_directory "_attachments"
30
+ inside "_attachments" do
31
+ empty_directory_with_gitkeep "images"
32
+ empty_directory_with_gitkeep "javascripts"
33
+ directory "stylesheets"
34
+ template "index.html"
35
+ end
36
+ end
37
+
38
+ protected
39
+
40
+ def app_name
41
+ @app_name ||= File.basename(destination_root)
42
+ end
43
+
44
+ def app_title
45
+ @app_title ||= app_name.humanize
46
+ end
47
+
48
+ def empty_directory_with_gitkeep(destination, config = {})
49
+ empty_directory(destination, config)
50
+ create_file("#{destination}/.gitkeep") unless options[:skip_git]
51
+ end
52
+ end
53
+ end
@@ -0,0 +1 @@
1
+ # Welcome to Couch!
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE HTML>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
5
+ <title><%= app_title %></title>
6
+ <link rel="stylesheet" href="stylesheets/application.css" type="text/css" media="screen" charset="utf-8">
7
+ </head>
8
+ <body>
9
+ <h1>Welcome to <%= app_title %>!</h1>
10
+ </body>
11
+ <script src="/_utils/script/json2.js"></script>
12
+ <script src="/_utils/script/jquery.js?1.3.2"></script>
13
+ <script src="/_utils/script/jquery.couch.js?0.10.0"></script>
14
+ </html>
@@ -0,0 +1,25 @@
1
+ body {
2
+ background-color: #fff;
3
+ color: #333;
4
+ margin: 1cm 1.618cm;
5
+ }
6
+
7
+ body, p, ol, ul, td {
8
+ font-family: verdana, arial, helvetica, sans-serif;
9
+ font-size: 13px;
10
+ line-height: 18px;
11
+ }
12
+
13
+ pre {
14
+ background-color: #eee;
15
+ padding: 10px;
16
+ font-size: 11px;
17
+ }
18
+
19
+ a { color: #000; }
20
+ a:visited { color: #666; }
21
+ a:hover { color: #fff; background-color:#000; }
22
+
23
+ .notice {
24
+ color: green;
25
+ }
@@ -0,0 +1 @@
1
+ _design/<%= app_name %>
@@ -0,0 +1 @@
1
+ database: "http://127.0.0.1:5984/<%= app_name %>"
@@ -0,0 +1,3 @@
1
+ function (newDoc, oldDoc, userCtx) {
2
+ // validation code goes here
3
+ }
@@ -0,0 +1,65 @@
1
+ require 'couch/core_ext/string/inflections'
2
+
3
+ require 'rubygems'
4
+ require 'thor/group'
5
+
6
+ module Couch
7
+ module Generators
8
+ class Error < Thor::Error
9
+ end
10
+
11
+ class Base < Thor::Group
12
+ include Thor::Actions
13
+
14
+ add_runtime_options!
15
+
16
+ # Automatically sets the source root based on the class name.
17
+ #
18
+ def self.source_root
19
+ @_couch_source_root ||= begin
20
+ if generator_name
21
+ File.expand_path(File.join("../generators", generator_name, 'templates'), File.dirname(__FILE__))
22
+ end
23
+ end
24
+ end
25
+
26
+ # Tries to get the description from a USAGE file one folder above the source
27
+ # root otherwise uses a default description.
28
+ #
29
+ def self.desc(description=nil)
30
+ return super if description
31
+ usage = File.expand_path(File.join(source_root, "..", "USAGE"))
32
+
33
+ @desc ||= if File.exist?(usage)
34
+ File.read(usage)
35
+ else
36
+ "Description:\n Create files for #{generator_name} generator."
37
+ end
38
+ end
39
+
40
+ def self.info
41
+ desc.split(/\n+/)[1].strip
42
+ end
43
+
44
+ protected
45
+
46
+ # Use Couch default banner.
47
+ #
48
+ def self.banner
49
+ "couch generate|destroy #{generator_name} #{self.arguments.map{ |a| a.usage }.join(' ')} [options]"
50
+ end
51
+
52
+ # Removes the namespaces and get the generator name. For example,
53
+ # Couch::Generators::MetalGenerator will return "metal" as generator name.
54
+ #
55
+ def self.generator_name
56
+ @generator_name ||= begin
57
+ if generator = name.to_s.split('::').last
58
+ generator.sub!(/Generator$/, '')
59
+ generator.underscore
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,52 @@
1
+ module Couch
2
+ class Mapper
3
+ def initialize(root)
4
+ raise "Root invalid" unless root && File.directory?(root)
5
+ @root = root
6
+ end
7
+
8
+ def doc
9
+ map @root
10
+ end
11
+
12
+ private
13
+
14
+ def map(dirname, hash = {})
15
+ Dir.entries(dirname).each do |file|
16
+ next if file =~ /^\./
17
+ filename = File.join(dirname, file)
18
+ key = file.sub(/\.js$/, '')
19
+ hash[key] = if file == "_attachments"
20
+ map_attachments(filename)
21
+ elsif File.directory?(filename)
22
+ map filename
23
+ else
24
+ File.read(filename).strip
25
+ end
26
+ end
27
+ hash
28
+ end
29
+
30
+ def map_attachments(dirname, hash = {}, keys = [])
31
+ Dir.entries(dirname).each do |file|
32
+ next if file =~ /^\./
33
+ filename = File.join(dirname, file)
34
+ base = keys + [file]
35
+ if File.directory?(filename)
36
+ map_attachments filename, hash, base
37
+ else
38
+ hash[base.join('/')] = {
39
+ "content_type" => "text/plain",
40
+ "data" => base64(File.read(filename)),
41
+ }
42
+ end
43
+ end
44
+ hash
45
+ end
46
+
47
+ # CouchDB needs base64 encodings without spaces
48
+ def base64(data)
49
+ [data].pack("m").gsub(/\s/,'')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Couch
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Couch" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'couch'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: couch
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Johannes J. Schmidt
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-07 00:00:00 +01:00
18
+ default_executable: couch
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: thor
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 13
30
+ - 4
31
+ version: 0.13.4
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rest-client
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 4
44
+ - 1
45
+ version: 1.4.1
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: json_pure
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 1
57
+ - 2
58
+ - 2
59
+ version: 1.2.2
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 1
71
+ - 2
72
+ - 9
73
+ version: 1.2.9
74
+ type: :development
75
+ version_requirements: *id004
76
+ description: With Couch you can easy build a standalone CouchDB application.
77
+ email: schmidt@netzmerk.com
78
+ executables:
79
+ - couch
80
+ extensions: []
81
+
82
+ extra_rdoc_files:
83
+ - LICENSE
84
+ - README.rdoc
85
+ files:
86
+ - .document
87
+ - .gitignore
88
+ - LICENSE
89
+ - README.rdoc
90
+ - Rakefile
91
+ - bin/couch
92
+ - couch.gemspec
93
+ - lib/couch.rb
94
+ - lib/couch/actions/base.rb
95
+ - lib/couch/actions/pull.rb
96
+ - lib/couch/actions/push.rb
97
+ - lib/couch/commands.rb
98
+ - lib/couch/commands/destroy.rb
99
+ - lib/couch/commands/generate.rb
100
+ - lib/couch/commands/pull.rb
101
+ - lib/couch/commands/push.rb
102
+ - lib/couch/core_ext/string/inflections.rb
103
+ - lib/couch/generators.rb
104
+ - lib/couch/generators/application/USAGE
105
+ - lib/couch/generators/application/application_generator.rb
106
+ - lib/couch/generators/application/templates/README
107
+ - lib/couch/generators/application/templates/_attachments/index.html
108
+ - lib/couch/generators/application/templates/_attachments/stylesheets/application.css
109
+ - lib/couch/generators/application/templates/_id
110
+ - lib/couch/generators/application/templates/couchrc
111
+ - lib/couch/generators/application/templates/gitignore
112
+ - lib/couch/generators/application/templates/validate_doc_update.js
113
+ - lib/couch/generators/base.rb
114
+ - lib/couch/mapper.rb
115
+ - lib/couch/version.rb
116
+ - spec/couch_spec.rb
117
+ - spec/spec.opts
118
+ - spec/spec_helper.rb
119
+ has_rdoc: true
120
+ homepage: http://github.com/jo/couch
121
+ licenses: []
122
+
123
+ post_install_message:
124
+ rdoc_options:
125
+ - --charset=UTF-8
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ requirements: []
143
+
144
+ rubyforge_project: couch
145
+ rubygems_version: 1.3.6
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: Standalone CouchDB Application Development Suite
149
+ test_files:
150
+ - spec/spec_helper.rb
151
+ - spec/couch_spec.rb