couch-client 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,5 +1,7 @@
1
+ v0.1.1. Fixing Manifest contents and adding Rails information to README.
2
+
1
3
  v0.1.0. Adding rake tasks to sync and manage database functions and design documents. Also added support for list and show functions; as well as fulltext administration.
2
4
 
3
- v0.0.2. Fixing gemspec
5
+ v0.0.2. Fixing gemspec.
4
6
 
5
- v0.0.1. First release
7
+ v0.0.1. First release.
data/Manifest CHANGED
@@ -4,6 +4,7 @@ Manifest
4
4
  README.markdown
5
5
  Rakefile
6
6
  TODO
7
+ couch-client.gemspec
7
8
  lib/couch-client.rb
8
9
  lib/couch-client/attachment.rb
9
10
  lib/couch-client/attachment_list.rb
@@ -15,6 +16,7 @@ lib/couch-client/database.rb
15
16
  lib/couch-client/design.rb
16
17
  lib/couch-client/document.rb
17
18
  lib/couch-client/hookup.rb
19
+ lib/couch-client/rake_task.rb
18
20
  lib/couch-client/row.rb
19
21
  spec/attachment_list_spec.rb
20
22
  spec/attachment_spec.rb
@@ -25,9 +27,19 @@ spec/consistent_hash_spec.rb
25
27
  spec/couch-client_spec.rb
26
28
  spec/database_spec.rb
27
29
  spec/design_spec.rb
30
+ spec/designs/create/people/fulltext/by_name/index.js
31
+ spec/designs/create/people/validate_on_update.js
32
+ spec/designs/create/people/views/all/map.js
33
+ spec/designs/create/people/views/sum/map.js
34
+ spec/designs/create/people/views/sum/reduce.js
35
+ spec/designs/update/people/fulltext/by_name/index.js
36
+ spec/designs/update/people/validate_on_update.js
37
+ spec/designs/update/people/views/sum/map.js
38
+ spec/designs/update/people/views/sum/reduce.js
28
39
  spec/document_spec.rb
29
40
  spec/files/image.png
30
41
  spec/files/plain.txt
31
42
  spec/hookup_spec.rb
43
+ spec/rake_task_spec.rb
32
44
  spec/row_spec.rb
33
45
  spec/spec_helper.rb
@@ -69,7 +69,7 @@ Working with a Document
69
69
  -----------------------
70
70
 
71
71
  # Building new documents
72
- # Couch.build({:name => "alice"})
72
+ # person = Couch.build({:name => "alice"})
73
73
 
74
74
  # Getting and setting fields (with indifferent access and value "stringification")
75
75
  # person[:name] # => "alice"
@@ -116,16 +116,15 @@ Working with Collections
116
116
  ------------------------
117
117
 
118
118
  # Getting all documents
119
- Couch.all_docs # => [{"id"=>"7f22af967b04d1b88212d3d26b017ff6", "key"=>"7f22af967b04d1b88212d3d26b017ff6", "value"=>{"rev"=>"1-f867d6b9aa0a5c31d647d57110fa7d36"}},
120
- # {"id"=>"7f22af967b04d1b88212d3d26b018e89", "key"=>"7f22af967b04d1b88212d3d26b018e89", "value"=>{"rev"=>"3-3a635c1a2b5a8ff94bb5d63eee3cd6ef"}}]
119
+ Couch.all_docs
121
120
 
122
121
  # Getting all documents with document fields
123
122
  Couch.all_docs(:include_docs => true)
124
123
 
125
124
  # Specifying a `key`, `startkey` or `endkey`
126
- couch.all_docs(:key => "7f22af967b04d1b88212d3d26b018e89")
127
- couch.all_docs(:startkey => 200)
128
- couch.all_docs(:endkey => [2010, 01, 01])
125
+ Couch.all_docs(:key => "7f22af967b04d1b88212d3d26b018e89")
126
+ Couch.all_docs(:startkey => 200)
127
+ Couch.all_docs(:endkey => [2010, 01, 01])
129
128
 
130
129
  # Getting additional collection information
131
130
  Couch.all_docs.info # => {"total_rows" => 2, "offset" => 0}
@@ -133,36 +132,36 @@ Working with Collections
133
132
  Using Design Documents
134
133
  ----------------------
135
134
 
136
- # Map Views
137
- Couch.design(:people).view(:all) # => [{"id"=>"7f22af967b04d1b88212d3d26b017ff6", "key"=>"7f22af967b04d1b88212d3d26b017ff6", "value"=>{"name" => "alice"}},
138
- # {"id"=>"7f22af967b04d1b88212d3d26b018e89", "key"=>"7f22af967b04d1b88212d3d26b018e89", "value"=>{"name" => "bob"}}]
135
+ # Map views
136
+ Couch.design(:people).view(:all)
137
+
138
+ # Map views with a key
139
+ Couch.design(:people).view(:by_sex, :key => "male")
139
140
 
140
- # MapReduce Views
141
- Couch.design(:people).view(:sum) # => [{"key" => "male", "value" => 1}, {"key" => "female", "value" => 1}]
141
+ # MapReduce views
142
+ Couch.design(:people).view(:sum)
142
143
 
143
144
  Using Show and List Functions
144
145
  -----------------------------
145
146
 
146
- # Show Functions
147
- Couch.design(:people).show(:html) # => "<h1>alice</h1>"
148
- Couch.design(:people).show(:json) # => {"name" => "alice"}
147
+ # Show functions
148
+ Couch.design(:people).show(:html, "7f22af967b04d1b88212d3d26b018e89") # => "<h1>alice</h1>"
149
+ Couch.design(:people).show(:json, "7f22af967b04d1b88212d3d26b018e89") # => {"name" => "alice"}
149
150
 
150
- # List Functions
151
+ # List functions
151
152
  Couch.design(:people).list(:json, :people, :all) # => ["alice", "bob", "charlie"]
152
153
 
153
154
  Using FullText Search (Must Have CouchDB-Lucene Installed)
154
155
  ----------------------------------------------------------
155
156
 
156
157
  # Getting search results
157
- Couch.design(:people).fulltext(:by_name, :q => "ali*") # => [{"id"=>"a6c92090bbee241e892be1ac4464b9d9", "score"=>4.505526065826416, "fields"=>{"default"=>"alice"}}]
158
+ Couch.design(:people).fulltext(:by_name, :q => "ali*")
158
159
 
159
160
  # Getting additional search results information
160
- Couch.design(:people).fulltext(:by_name, :q => "ali*").info # => {"q"=>"default:alice", "etag"=>"11e1541e20d9b860", "skip"=>0, "limit"=>25,
161
- # "total_rows"=>7, "search_duration"=>0, "fetch_duration"=>1}
161
+ Couch.design(:people).fulltext(:by_name, :q => "ali*").info
162
162
 
163
163
  # Getting search index information
164
- Couch.design(:people).fulltext(:by_name) # => {"current"=>true, "disk_size"=>3759, "doc_count"=>25, "doc_del_count"=>3, "fields"=>["default"],
165
- # "last_modified"=>"1288403429000", "optimized"=>false, "ref_count"=>2}
164
+ Couch.design(:people).fulltext(:by_name)
166
165
 
167
166
  # Optimizing an index
168
167
  Couch.design(:people).fulltext(:by_name, :optimize) # => true
@@ -180,6 +179,17 @@ CouchClient rake tasks can be enabled by adding the following to your `Rakefile`
180
179
  c.design_path = "./designs"
181
180
  end
182
181
 
182
+ Or you can add CouchClient rake tasks to your rails app by making the following file in `lib/tasks/couch.rake`.
183
+
184
+ require "#{Rails.root}/config/environment"
185
+
186
+ CouchClient::RakeTask.new do |c|
187
+ c.connection = Couch
188
+ c.design_path = "./app/designs"
189
+ end
190
+
191
+ You can then specify your CouchClient settings for each each environment in their respective configuration files (e.g. development.rb, test.rb and production.rb).
192
+
183
193
  Two parameters are available, `connection` should be the actual variable used for your CouchDB interface and `design_path` should be the application's location where design documents will be stored.
184
194
 
185
195
  Within the design path, you should format each design document with folders and files corresponding to the fields in your design document.
@@ -246,5 +256,3 @@ Performing Database Administration
246
256
  # Delete the database
247
257
  Couch.databse.delete!
248
258
 
249
-
250
-
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{couch-client}
5
- s.version = "0.1.0"
5
+ s.version = "0.1.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Robert Sosinski"]
9
- s.date = %q{2010-11-05}
9
+ s.date = %q{2010-11-11}
10
10
  s.description = %q{A Ruby interface for CouchDB}
11
11
  s.email = %q{email@robertsosinski.com}
12
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.markdown", "TODO", "lib/couch-client.rb", "lib/couch-client/attachment.rb", "lib/couch-client/attachment_list.rb", "lib/couch-client/collection.rb", "lib/couch-client/connection.rb", "lib/couch-client/connection_handler.rb", "lib/couch-client/consistent_hash.rb", "lib/couch-client/database.rb", "lib/couch-client/design.rb", "lib/couch-client/document.rb", "lib/couch-client/hookup.rb", "lib/couch-client/row.rb"]
13
- s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.markdown", "Rakefile", "TODO", "lib/couch-client.rb", "lib/couch-client/attachment.rb", "lib/couch-client/attachment_list.rb", "lib/couch-client/collection.rb", "lib/couch-client/connection.rb", "lib/couch-client/connection_handler.rb", "lib/couch-client/consistent_hash.rb", "lib/couch-client/database.rb", "lib/couch-client/design.rb", "lib/couch-client/document.rb", "lib/couch-client/hookup.rb", "lib/couch-client/row.rb", "spec/attachment_list_spec.rb", "spec/attachment_spec.rb", "spec/collection_spec.rb", "spec/conection_handler_spec.rb", "spec/connection_spec.rb", "spec/consistent_hash_spec.rb", "spec/couch-client_spec.rb", "spec/database_spec.rb", "spec/design_spec.rb", "spec/document_spec.rb", "spec/files/image.png", "spec/files/plain.txt", "spec/hookup_spec.rb", "spec/row_spec.rb", "spec/spec_helper.rb", "couch-client.gemspec"]
12
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.markdown", "TODO", "lib/couch-client.rb", "lib/couch-client/attachment.rb", "lib/couch-client/attachment_list.rb", "lib/couch-client/collection.rb", "lib/couch-client/connection.rb", "lib/couch-client/connection_handler.rb", "lib/couch-client/consistent_hash.rb", "lib/couch-client/database.rb", "lib/couch-client/design.rb", "lib/couch-client/document.rb", "lib/couch-client/hookup.rb", "lib/couch-client/rake_task.rb", "lib/couch-client/row.rb"]
13
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.markdown", "Rakefile", "TODO", "couch-client.gemspec", "lib/couch-client.rb", "lib/couch-client/attachment.rb", "lib/couch-client/attachment_list.rb", "lib/couch-client/collection.rb", "lib/couch-client/connection.rb", "lib/couch-client/connection_handler.rb", "lib/couch-client/consistent_hash.rb", "lib/couch-client/database.rb", "lib/couch-client/design.rb", "lib/couch-client/document.rb", "lib/couch-client/hookup.rb", "lib/couch-client/rake_task.rb", "lib/couch-client/row.rb", "spec/attachment_list_spec.rb", "spec/attachment_spec.rb", "spec/collection_spec.rb", "spec/conection_handler_spec.rb", "spec/connection_spec.rb", "spec/consistent_hash_spec.rb", "spec/couch-client_spec.rb", "spec/database_spec.rb", "spec/design_spec.rb", "spec/designs/create/people/fulltext/by_name/index.js", "spec/designs/create/people/validate_on_update.js", "spec/designs/create/people/views/all/map.js", "spec/designs/create/people/views/sum/map.js", "spec/designs/create/people/views/sum/reduce.js", "spec/designs/update/people/fulltext/by_name/index.js", "spec/designs/update/people/validate_on_update.js", "spec/designs/update/people/views/sum/map.js", "spec/designs/update/people/views/sum/reduce.js", "spec/document_spec.rb", "spec/files/image.png", "spec/files/plain.txt", "spec/hookup_spec.rb", "spec/rake_task_spec.rb", "spec/row_spec.rb", "spec/spec_helper.rb"]
14
14
  s.homepage = %q{http://github.com/robertsosinski/couch-client}
15
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Couch-client", "--main", "README.markdown"]
16
16
  s.require_paths = ["lib"]
@@ -11,7 +11,7 @@ require 'couch-client/attachment'
11
11
  require 'couch-client/design'
12
12
  require 'couch-client/collection'
13
13
  require 'couch-client/row'
14
- require "couch-client/rake_task" if defined?(Rake)
14
+ require 'couch-client/rake_task' if defined?(Rake)
15
15
 
16
16
  # The CouchClient module is the overall container of all CouchClient logic.
17
17
  module CouchClient
@@ -1,4 +1,6 @@
1
1
  module CouchClient
2
+ class AttachmentNotFound < Exception; end
3
+
2
4
  # Attachment is an extended Hash that provides additional methods
3
5
  # to interact with attached files saved within a document.
4
6
  class Attachment < ConsistentHash
@@ -26,7 +28,20 @@ module CouchClient
26
28
 
27
29
  # Returns a string that contains attachment data
28
30
  def data
29
- @data ||= @connection.hookup.get([@id, @name], nil, self["content_type"]).last
31
+ return @data if @data # Return data if it has been memoized
32
+
33
+ code, @data = @connection.hookup.get([@id, @name], nil, self["content_type"])
34
+
35
+ case code
36
+ when 200
37
+ @data # Return data if the attachment is found
38
+ when 404
39
+ # Raise an error if the attachment is not found
40
+ raise AttachmentNotFound.new("attachment '#{@name}' could not be found for document '#{@id}'")
41
+ else
42
+ # Also raise an error if something else happens
43
+ raise Error.new("code: #{code}, error: #{@data["error"]}, reason: #{@data["reason"]}")
44
+ end
30
45
  end
31
46
  end
32
47
  end
@@ -4,7 +4,6 @@ require 'json'
4
4
  module CouchClient
5
5
  class InvalidHTTPVerb < Exception; end
6
6
  class InvalidJSONData < Exception; end
7
- class SymbolUsedInField < Exception; end
8
7
 
9
8
  # Hookup is the basic HTTP interface that connects CouchClient to CouchDB.
10
9
  # Hookup can use any HTTP library if the conventions listed below are followed.
@@ -87,14 +86,18 @@ module CouchClient
87
86
  # code is the http code (e.g. 200 or 404)
88
87
  code = easy.response_code
89
88
 
90
- # body is either a nil, a hash or a string containing attachment data
91
- body = if easy.body_str == "" || easy.body_str.nil?
89
+ # body is either a nil, a hash or a string containing attachment data.
90
+ body = if verb == :head
91
+ # Head requests should return `nil`.
92
92
  nil
93
- elsif [content_type, easy.content_type].include?("application/json") || [:post, :put, :delete].include?(verb)
93
+ # If the response is not a 200, then it must be JSON (as CouchDB returns all feedback as JSON), so parse it.
94
+ # If the response is a 200, it may not be JSON (if it is an attachment), therefore check the content type before parsing.
95
+ elsif code != 200 || [content_type, easy.content_type].include?("application/json")
94
96
  begin
95
97
  JSON.parse(easy.body_str)
96
98
  rescue
97
- raise InvalidJSONData.new("document received is not valid JSON")
99
+ # Raise an error of the JSON returned is malformed.
100
+ raise InvalidJSONData.new("data received is not valid JSON")
98
101
  end
99
102
  else
100
103
  easy.body_str
@@ -0,0 +1,181 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 'set'
4
+ require 'pathname'
5
+
6
+ module CouchClient
7
+ # RakeTask is a namespace for all Rake tasks that are bundled with
8
+ # CouchClient, such as database creation, sync, compaction and deletion.
9
+ class RakeTask < ::Rake::TaskLib
10
+ class MissingCouchClientConnection < Exception; end
11
+
12
+ attr_accessor :connection, :design_path
13
+
14
+ # Start using CouchClient::RakeTask by constructing a new instance with a block.
15
+ #
16
+ # CouchClient::RakeTask.new do |c|
17
+ # c.connection = Couch
18
+ # c.design_path = "./app/designs"
19
+ # end
20
+ #
21
+ # CouchClient::RakeTask.new takes the following options.
22
+ #
23
+ # connection: A CouchClient Connection, default being `Couch`.
24
+ # design_path: The path where design documents are stored, default being "./designs".
25
+ def initialize(&block)
26
+ instance_eval(&block) if block_given?
27
+
28
+ begin
29
+ @connection ||= Object.const_get("Couch")
30
+ rescue NameError
31
+ raise MissingCouchClientConnection.new("specify a CouchClient connection within your RakeTask setup.")
32
+ end
33
+
34
+ @design_path = Pathname.new(@design_path || './designs')
35
+
36
+ # Create Rake tasks.
37
+ namespace :couch do
38
+ desc "Syncs design documents with the database."
39
+ task :sync do
40
+ sync
41
+ end
42
+
43
+ desc "Creates the database."
44
+ task :create do
45
+ create
46
+ end
47
+
48
+ desc "Deletes the database and all its data."
49
+ task :delete do
50
+ delete
51
+ end
52
+
53
+ desc "Compacts the database."
54
+ task :compact do
55
+ compact
56
+ end
57
+ end
58
+ end
59
+
60
+ def sync
61
+ # Fetch all design documents that are cuurently saved in the database.
62
+ saved_design_docs = @connection.all_design_docs("include_docs" => true)
63
+ local_design_docs = {}
64
+
65
+ design_path_depth = design_path.to_s.count("/") + 1
66
+
67
+ # Recurse though the design directory and construct a hash of design functions.
68
+ recurser = lambda do |path|
69
+ path_breadcrumbs = path.to_s.match("[^\.]+")[0].split("/")[design_path_depth..-1] # e.g. ["people", "views", "all", "map"]
70
+ path_hash_follow = path_breadcrumbs.reduce(""){|memo, key| memo + "['#{key}']"} # e.g. ['people']['views']['all']['map']
71
+
72
+ if path.directory?
73
+ # Set an empty hash for the directory.
74
+ eval("local_design_docs#{path_hash_follow} = {}")
75
+
76
+ # Reject hidden filenames (filesnames that begin with a ".").
77
+ path.children.reject{|p| p.basename.to_s.match(/^\./)}.each do |child|
78
+ # Continue recursion.
79
+ recurser.call(child)
80
+ end
81
+ else
82
+ # Set a field with design function data.
83
+ eval("local_design_docs#{path_hash_follow} = #{path.read.inspect}")
84
+ end
85
+ end
86
+
87
+ recurser.call(@design_path)
88
+
89
+ # Get a set of id's that are currently saved and a set that are avaiable locally.
90
+ saved_ids = saved_design_docs.map{|doc| doc["id"].gsub(/^_design\//, "")}.to_set
91
+ local_ids = local_design_docs.keys.to_set
92
+
93
+ doc_ids_to_create = local_ids.difference(saved_ids).to_a
94
+ doc_ids_to_update = saved_ids.intersection(local_ids).to_a
95
+ doc_ids_to_delete = saved_ids.difference(local_ids).to_a
96
+
97
+ # Create any new design documents.
98
+ doc_ids_to_create.each do |id|
99
+ new_doc = @connection.build
100
+ new_doc.id = "_design/#{id}"
101
+ new_doc.merge!(local_design_docs[id])
102
+ new_doc.merge!({"language" => "javascript"})
103
+
104
+ if new_doc.save
105
+ puts "Creating: #{new_doc.id} -- #{new_doc.rev}"
106
+ else
107
+ puts "Failure: #{new_doc.id} -- #{new_doc.error.inspect}"
108
+ end
109
+ end
110
+
111
+ # Construct design documents that already exist.
112
+ doc_ids_to_update.each do |id|
113
+ old_doc = saved_design_docs.detect{|d| d["id"] == "_design/#{id}"}["doc"]
114
+
115
+ new_doc = @connection.build
116
+ new_doc.id = old_doc.id
117
+ new_doc.rev = old_doc.rev
118
+ new_doc.merge!(local_design_docs[id])
119
+ new_doc.merge!({"language" => "javascript"})
120
+
121
+ # If the new document is the same as what is on the server
122
+ if old_doc == new_doc
123
+ # Keep the old design document.
124
+ puts "Keeping: #{new_doc.id} -- #{new_doc.rev}"
125
+ else
126
+ # Else save the new design docuemnt.
127
+ if new_doc.save
128
+ puts "Updating: #{new_doc.id} -- #{new_doc.rev}"
129
+ else
130
+ puts "Failure: #{new_doc.id} -- #{new_doc.error.inspect}"
131
+ end
132
+ end
133
+ end
134
+
135
+ # Delete any documents that are not available locally.
136
+ doc_ids_to_delete.each do |id|
137
+ old_doc = saved_design_docs.detect{|d| d["id"] == "_design/#{id}"}["doc"]
138
+
139
+ if old_doc.delete!
140
+ puts "Deleting: #{old_doc.id} -- #{old_doc.rev}"
141
+ else
142
+ puts "Failure: #{old_doc.id} -- #{new_doc.error.inspect}"
143
+ end
144
+ end
145
+ end
146
+
147
+ def create
148
+ resp = @connection.database.create
149
+ if resp["ok"]
150
+ puts "Created."
151
+ else
152
+ puts "The database could not be created, the file already exists."
153
+ end
154
+ end
155
+
156
+ def delete
157
+ resp = @connection.database.delete!
158
+
159
+ if resp["ok"]
160
+ puts "Deleted."
161
+ else
162
+ puts "The database could not be deleted, the file does not exist."
163
+ end
164
+ end
165
+
166
+ def compact
167
+ resp = @connection.database.compact!
168
+
169
+ if resp["ok"]
170
+ puts "Compaction Complete."
171
+ else
172
+ utils_uri = lambda{
173
+ handler = handler = @connection.hookup.handler
174
+ handler.uri.gsub(/#{handler.database}$/, "_utils")
175
+ }.call
176
+
177
+ puts "The database could not be compacted, see #{utils_uri} for more information."
178
+ end
179
+ end
180
+ end
181
+ end
@@ -25,9 +25,17 @@ describe CouchClient::Attachment do
25
25
 
26
26
  @alice.attach("plain.txt", @plain, "text/plain")
27
27
  @alice.attach("image.png", @image, "image/png")
28
+ @alice.attach("missing", @plain, "text/plain") # will be deleted
28
29
 
29
- @attachment_plain = @alice.saved_doc.attachments["plain.txt"]
30
- @attachment_image = @alice.saved_doc.attachments["image.png"]
30
+ @alice = @alice.saved_doc
31
+
32
+ @attachment_plain = @alice.attachments["plain.txt"]
33
+ @attachment_image = @alice.attachments["image.png"]
34
+
35
+ @attachment_missing = @alice.attachments["missing"]
36
+
37
+ @alice.attachments.delete("missing")
38
+ @alice.save
31
39
  end
32
40
 
33
41
  after(:all) do
@@ -48,10 +56,14 @@ describe CouchClient::Attachment do
48
56
  end
49
57
  end
50
58
 
51
- describe '#file' do
59
+ describe '#data' do
52
60
  it 'should yield the file for the attachment as a string' do
53
61
  @digest.call(@attachment_plain.data).should eql(@plain_digest)
54
62
  @digest.call(@attachment_image.data).should eql(@image_digest)
55
63
  end
64
+
65
+ it 'should raise an error if the attachment is not found' do
66
+ lambda{@attachment_missing.data}.should raise_error(CouchClient::AttachmentNotFound)
67
+ end
56
68
  end
57
69
  end
@@ -0,0 +1,5 @@
1
+ function(doc) {
2
+ var ret = new Document();
3
+ ret.add(doc.name, {'store':'yes'});
4
+ return ret;
5
+ }
@@ -0,0 +1,6 @@
1
+ function(newDoc, savedDoc, userCtx) {
2
+ if(newDoc._deleted) return;
3
+ if(!newDoc.name) {
4
+ throw({"forbidden": "Document must have a name field."});
5
+ }
6
+ }
@@ -0,0 +1,3 @@
1
+ function(doc) {
2
+ emit(doc._id, doc);
3
+ }
@@ -0,0 +1,3 @@
1
+ function(doc) {
2
+ emit(null, 1);
3
+ }
@@ -0,0 +1,3 @@
1
+ function(id, values, rereduce) {
2
+ return sum(values);
3
+ }
@@ -0,0 +1,6 @@
1
+ function(doc) {
2
+ var ret = new Document();
3
+ ret.add(doc.name, {'store':'yes'});
4
+ ret.add(doc.city, {'store':'yes'});
5
+ return ret;
6
+ }
@@ -0,0 +1,9 @@
1
+ function(newDoc, savedDoc, userCtx) {
2
+ if(newDoc._deleted) return;
3
+ if(!newDoc.name) {
4
+ throw({"forbidden": "Document must have a name field."});
5
+ }
6
+ if(!newDoc.city) {
7
+ throw({"forbidden": "Document must have a city field."});
8
+ }
9
+ }
@@ -0,0 +1,3 @@
1
+ function(doc) {
2
+ emit(null, 1);
3
+ }
@@ -0,0 +1,3 @@
1
+ function(id, values, rereduce) {
2
+ return sum(values);
3
+ }
@@ -0,0 +1,78 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe CouchClient::RakeTask do
4
+ before(:all) do
5
+ Couch = CouchClient.connect(COUCHDB_TEST_SETTINGS)
6
+
7
+ @task = CouchClient::RakeTask.new do |t|
8
+ t.connection = Couch
9
+ # t.design_path = "./spec/designs"
10
+ end
11
+ end
12
+
13
+ describe '#sync' do
14
+ before(:all) do
15
+ Couch.database.create
16
+ end
17
+
18
+ after(:all) do
19
+ Couch.database.delete!
20
+ end
21
+
22
+ it 'should create a new design document' do
23
+ @task.design_path = Pathname("./spec/designs/create")
24
+
25
+ lambda{Couch["_design/people"]}.should raise_error(CouchClient::DocumentNotFound)
26
+
27
+ suppress{@task.sync}
28
+
29
+ @doc = Couch["_design/people"]
30
+ @doc.code.should eql(200)
31
+ @rev = @doc.rev
32
+ @rev[0].should eql("1")
33
+ end
34
+
35
+ it 'should update an existing design document' do
36
+ @task.design_path = Pathname("./spec/designs/update")
37
+
38
+ suppress{@task.sync}
39
+
40
+ @doc = Couch["_design/people"]
41
+ @doc.code.should eql(200)
42
+ @doc.rev.should_not eql(@rev)
43
+ @doc.rev[0].should eql("2")
44
+ end
45
+
46
+ it 'should delete a missing design document' do
47
+ @task.design_path = Pathname("./spec/designs/delete")
48
+
49
+ suppress{@task.sync}
50
+
51
+ lambda{Couch["_design/people"]}.should raise_error(CouchClient::DocumentNotFound)
52
+ end
53
+ end
54
+
55
+ describe '#create, #compact, #delete' do
56
+ describe '#create' do
57
+ it 'should create a new database' do
58
+ Couch.database.exists?.should be_false
59
+ suppress{@task.create}
60
+ Couch.database.exists?.should be_true
61
+ end
62
+ end
63
+
64
+ describe '#compact' do
65
+ it 'should compact a database' do
66
+ suppress{@task.compact}
67
+ end
68
+ end
69
+
70
+ describe '#delete' do
71
+ it 'should delete a database' do
72
+ Couch.database.exists?.should be_true
73
+ suppress{@task.delete}
74
+ Couch.database.exists?.should be_false
75
+ end
76
+ end
77
+ end
78
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Robert Sosinski
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-05 00:00:00 -04:00
17
+ date: 2010-11-11 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -99,6 +99,7 @@ extra_rdoc_files:
99
99
  - lib/couch-client/design.rb
100
100
  - lib/couch-client/document.rb
101
101
  - lib/couch-client/hookup.rb
102
+ - lib/couch-client/rake_task.rb
102
103
  - lib/couch-client/row.rb
103
104
  files:
104
105
  - CHANGELOG
@@ -107,6 +108,7 @@ files:
107
108
  - README.markdown
108
109
  - Rakefile
109
110
  - TODO
111
+ - couch-client.gemspec
110
112
  - lib/couch-client.rb
111
113
  - lib/couch-client/attachment.rb
112
114
  - lib/couch-client/attachment_list.rb
@@ -118,6 +120,7 @@ files:
118
120
  - lib/couch-client/design.rb
119
121
  - lib/couch-client/document.rb
120
122
  - lib/couch-client/hookup.rb
123
+ - lib/couch-client/rake_task.rb
121
124
  - lib/couch-client/row.rb
122
125
  - spec/attachment_list_spec.rb
123
126
  - spec/attachment_spec.rb
@@ -128,13 +131,22 @@ files:
128
131
  - spec/couch-client_spec.rb
129
132
  - spec/database_spec.rb
130
133
  - spec/design_spec.rb
134
+ - spec/designs/create/people/fulltext/by_name/index.js
135
+ - spec/designs/create/people/validate_on_update.js
136
+ - spec/designs/create/people/views/all/map.js
137
+ - spec/designs/create/people/views/sum/map.js
138
+ - spec/designs/create/people/views/sum/reduce.js
139
+ - spec/designs/update/people/fulltext/by_name/index.js
140
+ - spec/designs/update/people/validate_on_update.js
141
+ - spec/designs/update/people/views/sum/map.js
142
+ - spec/designs/update/people/views/sum/reduce.js
131
143
  - spec/document_spec.rb
132
144
  - spec/files/image.png
133
145
  - spec/files/plain.txt
134
146
  - spec/hookup_spec.rb
147
+ - spec/rake_task_spec.rb
135
148
  - spec/row_spec.rb
136
149
  - spec/spec_helper.rb
137
- - couch-client.gemspec
138
150
  has_rdoc: true
139
151
  homepage: http://github.com/robertsosinski/couch-client
140
152
  licenses: []