couchrest 0.12.2 → 0.12.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +1 -2
- data/Rakefile +1 -38
- data/examples/word_count/word_count.rb +3 -24
- data/examples/word_count/word_count_query.rb +7 -6
- data/examples/word_count/word_count_views.rb +26 -0
- data/lib/couchrest/core/document.rb +12 -0
- data/lib/couchrest/core/model.rb +7 -1
- data/lib/couchrest/monkeypatches.rb +15 -1
- data/lib/couchrest.rb +1 -2
- data/spec/couchrest/core/database_spec.rb +0 -1
- data/spec/couchrest/core/document_spec.rb +83 -0
- metadata +5 -15
- data/bin/couchdir +0 -20
data/README.md
CHANGED
@@ -6,8 +6,7 @@ which I find to be concise, clear, and well designed. CouchRest lightly wraps
|
|
6
6
|
CouchDB's HTTP API, managing JSON serialization, and remembering the URI-paths
|
7
7
|
to CouchDB's API endpoints so you don't have to.
|
8
8
|
|
9
|
-
CouchRest
|
10
|
-
framework-specific object oriented APIs.
|
9
|
+
CouchRest is designed to make a simple base for application and framework-specific object oriented APIs. CouchRest is Object-Mapper agnostic, the parsed JSON it returns from CouchDB shows up as subclasses of Ruby's Hash. Naked JSON, just as it was mean to be.
|
11
10
|
|
12
11
|
## Easy Install
|
13
12
|
|
data/Rakefile
CHANGED
@@ -25,16 +25,13 @@ spec = Gem::Specification.new do |s|
|
|
25
25
|
s.has_rdoc = true
|
26
26
|
s.authors = ["J. Chris Anderson"]
|
27
27
|
s.files = %w( LICENSE README.md Rakefile THANKS.md ) +
|
28
|
-
Dir["{
|
28
|
+
Dir["{examples,lib,spec,utils}/**/*"] -
|
29
29
|
Dir["spec/tmp"]
|
30
30
|
s.extra_rdoc_files = %w( README.md LICENSE THANKS.md )
|
31
31
|
s.require_path = "lib"
|
32
|
-
s.bindir = 'bin'
|
33
|
-
s.executables << 'couchdir'
|
34
32
|
s.add_dependency("json", ">= 1.1.2")
|
35
33
|
s.add_dependency("rest-client", ">= 0.5")
|
36
34
|
s.add_dependency("mime-types", ">= 1.15")
|
37
|
-
s.add_dependency("extlib", ">= 0.9.6")
|
38
35
|
end
|
39
36
|
|
40
37
|
|
@@ -46,40 +43,6 @@ task :gemspec do
|
|
46
43
|
end
|
47
44
|
end
|
48
45
|
|
49
|
-
# desc "Update Github Gemspec"
|
50
|
-
# task :gemspec do
|
51
|
-
# skip_fields = %w(new_platform original_platform)
|
52
|
-
# integer_fields = %w(specification_version)
|
53
|
-
#
|
54
|
-
# result = "Gem::Specification.new do |s|\n"
|
55
|
-
# spec.instance_variables.each do |ivar|
|
56
|
-
# value = spec.instance_variable_get(ivar)
|
57
|
-
# name = ivar.split("@").last
|
58
|
-
# next if skip_fields.include?(name) || value.nil? || value == "" || (value.respond_to?(:empty?) && value.empty?)
|
59
|
-
# if name == "dependencies"
|
60
|
-
# value.each do |d|
|
61
|
-
# dep, *ver = d.to_s.split(" ")
|
62
|
-
# result << " s.add_dependency #{dep.inspect}, [#{ /\(([^\,]*)/ . match(ver.join(" "))[1].inspect}]\n"
|
63
|
-
# end
|
64
|
-
# else
|
65
|
-
# case value
|
66
|
-
# when Array
|
67
|
-
# value = name != "files" ? value.inspect : value.inspect.split(",").join(",\n")
|
68
|
-
# when Fixnum
|
69
|
-
# # leave as-is
|
70
|
-
# when String
|
71
|
-
# value = value.to_i if integer_fields.include?(name)
|
72
|
-
# value = value.inspect
|
73
|
-
# else
|
74
|
-
# value = value.to_s.inspect
|
75
|
-
# end
|
76
|
-
# result << " s.#{name} = #{value}\n"
|
77
|
-
# end
|
78
|
-
# end
|
79
|
-
# result << "end"
|
80
|
-
# File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w"){|f| f << result}
|
81
|
-
# end
|
82
|
-
|
83
46
|
desc "Run all specs"
|
84
47
|
Spec::Rake::SpecTask.new('spec') do |t|
|
85
48
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require 'rubygems'
|
2
|
+
require 'couchrest'
|
2
3
|
|
3
4
|
couch = CouchRest.new("http://127.0.0.1:5984")
|
4
5
|
db = couch.database('word-count-example')
|
@@ -39,29 +40,7 @@ books.keys.each do |book|
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
end
|
42
|
-
|
43
|
-
# word_count = {
|
44
|
-
# :map => 'function(doc){
|
45
|
-
# var words = doc.text.split(/\W/);
|
46
|
-
# words.forEach(function(word){
|
47
|
-
# if (word.length > 0) emit([word,doc.title],1);
|
48
|
-
# });
|
49
|
-
# }',
|
50
|
-
# :reduce => 'function(key,combine){
|
51
|
-
# return sum(combine);
|
52
|
-
# }'
|
53
|
-
# }
|
54
|
-
#
|
55
|
-
# db.delete db.get("_design/word_count") rescue nil
|
56
|
-
#
|
57
|
-
# db.save({
|
58
|
-
# "_id" => "_design/word_count",
|
59
|
-
# :views => {
|
60
|
-
# :count => word_count,
|
61
|
-
# :words => {:map => word_count[:map]}
|
62
|
-
# }
|
63
|
-
# })
|
64
43
|
|
65
44
|
# puts "The books have been stored in your CouchDB. To initiate the MapReduce process, visit http://127.0.0.1:5984/_utils/ in your browser and click 'word-count-example', then select view 'words' or 'count'. The process could take about 15 minutes on an average MacBook."
|
66
|
-
|
45
|
+
|
67
46
|
|
@@ -1,22 +1,23 @@
|
|
1
|
-
require
|
1
|
+
require 'rubygems'
|
2
|
+
require 'couchrest'
|
2
3
|
|
3
4
|
couch = CouchRest.new("http://127.0.0.1:5984")
|
4
5
|
db = couch.database('word-count-example')
|
5
6
|
|
6
7
|
puts "Now that we've parsed all those books into CouchDB, the queries we can run are incredibly flexible."
|
7
8
|
puts "\nThe simplest query we can run is the total word count for all words in all documents:"
|
8
|
-
|
9
|
-
puts db.view('word_count/
|
9
|
+
puts "this will take a few minutes the first time. if it times out, just rerun this script in a few few minutes."
|
10
|
+
puts db.view('word_count/words').inspect
|
10
11
|
|
11
12
|
puts "\nWe can also narrow the query down to just one word, across all documents. Here is the count for 'flight' in all three books:"
|
12
13
|
|
13
14
|
word = 'flight'
|
14
15
|
params = {
|
15
16
|
:startkey => [word],
|
16
|
-
:endkey => [word,
|
17
|
+
:endkey => [word,{}]
|
17
18
|
}
|
18
19
|
|
19
|
-
puts db.view('word_count/
|
20
|
+
puts db.view('word_count/words',params).inspect
|
20
21
|
|
21
22
|
puts "\nWe scope the query using startkey and endkey params to take advantage of CouchDB's collation ordering. Here are the params for the last query:"
|
22
23
|
puts params.inspect
|
@@ -28,7 +29,7 @@ params = {
|
|
28
29
|
:key => [word, title]
|
29
30
|
}
|
30
31
|
|
31
|
-
puts db.view('word_count/
|
32
|
+
puts db.view('word_count/words',params).inspect
|
32
33
|
|
33
34
|
|
34
35
|
puts "\nHere are the params for 'flight' in the da-vinci book:"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'couchrest'
|
3
|
+
|
4
|
+
couch = CouchRest.new("http://127.0.0.1:5984")
|
5
|
+
db = couch.database('word-count-example')
|
6
|
+
|
7
|
+
word_count = {
|
8
|
+
:map => 'function(doc){
|
9
|
+
var words = doc.text.split(/\W/);
|
10
|
+
words.forEach(function(word){
|
11
|
+
if (word.length > 0) emit([word,doc.title],1);
|
12
|
+
});
|
13
|
+
}',
|
14
|
+
:reduce => 'function(key,combine){
|
15
|
+
return sum(combine);
|
16
|
+
}'
|
17
|
+
}
|
18
|
+
|
19
|
+
db.delete db.get("_design/word_count") rescue nil
|
20
|
+
|
21
|
+
db.save({
|
22
|
+
"_id" => "_design/word_count",
|
23
|
+
:views => {
|
24
|
+
:words => word_count
|
25
|
+
}
|
26
|
+
})
|
@@ -56,6 +56,18 @@ module CouchRest
|
|
56
56
|
end
|
57
57
|
result['ok']
|
58
58
|
end
|
59
|
+
|
60
|
+
def copy(dest)
|
61
|
+
raise ArgumentError, "doc.database required to copy" unless database
|
62
|
+
result = database.copy(self, dest)
|
63
|
+
result['ok']
|
64
|
+
end
|
65
|
+
|
66
|
+
def move(dest)
|
67
|
+
raise ArgumentError, "doc.database required to copy" unless database
|
68
|
+
result = database.move(self, dest)
|
69
|
+
result['ok']
|
70
|
+
end
|
59
71
|
|
60
72
|
end
|
61
73
|
|
data/lib/couchrest/core/model.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
|
2
|
+
begin
|
3
|
+
require 'extlib'
|
4
|
+
rescue
|
5
|
+
puts "CouchRest::Model requires extlib. This is left out of the gemspec on purpose."
|
6
|
+
raise
|
7
|
+
end
|
3
8
|
require 'digest/md5'
|
4
9
|
require File.dirname(__FILE__) + '/document'
|
5
10
|
require 'mime/types'
|
@@ -439,6 +444,7 @@ module CouchRest
|
|
439
444
|
saved['views'][name] = view
|
440
445
|
end
|
441
446
|
database.save(saved)
|
447
|
+
self.design_doc = saved
|
442
448
|
else
|
443
449
|
design_doc['_id'] = did
|
444
450
|
design_doc.delete('_rev')
|
@@ -8,7 +8,7 @@ class Time
|
|
8
8
|
|
9
9
|
def to_json(options = nil)
|
10
10
|
u = self.utc
|
11
|
-
%("#{u.strftime("%Y/%m/%d %H:%M:%S
|
11
|
+
%("#{u.strftime("%Y/%m/%d %H:%M:%S +0000")}")
|
12
12
|
end
|
13
13
|
|
14
14
|
# Decodes the JSON time format to a UTC time.
|
@@ -21,4 +21,18 @@ class Time
|
|
21
21
|
# rescue
|
22
22
|
# fallback
|
23
23
|
# end
|
24
|
+
end
|
25
|
+
|
26
|
+
module RestClient
|
27
|
+
def self.copy(url, headers={})
|
28
|
+
Request.execute(:method => :copy,
|
29
|
+
:url => url,
|
30
|
+
:headers => headers)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.move(url, headers={})
|
34
|
+
Request.execute(:method => :move,
|
35
|
+
:url => url,
|
36
|
+
:headers => headers)
|
37
|
+
end
|
24
38
|
end
|
data/lib/couchrest.rb
CHANGED
@@ -15,7 +15,6 @@
|
|
15
15
|
require "rubygems"
|
16
16
|
require 'json'
|
17
17
|
require 'rest_client'
|
18
|
-
# require 'extlib'
|
19
18
|
|
20
19
|
$:.unshift File.dirname(__FILE__) unless
|
21
20
|
$:.include?(File.dirname(__FILE__)) ||
|
@@ -26,7 +25,7 @@ require 'couchrest/monkeypatches'
|
|
26
25
|
|
27
26
|
# = CouchDB, close to the metal
|
28
27
|
module CouchRest
|
29
|
-
VERSION = '0.12.
|
28
|
+
VERSION = '0.12.4'
|
30
29
|
|
31
30
|
autoload :Server, 'couchrest/core/server'
|
32
31
|
autoload :Database, 'couchrest/core/database'
|
@@ -128,3 +128,86 @@ describe "destroying a document from a db using bulk save" do
|
|
128
128
|
lambda{@db.get @resp['id']}.should raise_error
|
129
129
|
end
|
130
130
|
end
|
131
|
+
|
132
|
+
describe "copying a document" do
|
133
|
+
before :each do
|
134
|
+
@db = reset_test_db!
|
135
|
+
@resp = @db.save({'key' => 'value'})
|
136
|
+
@docid = 'new-location'
|
137
|
+
@doc = @db.get(@resp['id'])
|
138
|
+
end
|
139
|
+
describe "to a new location" do
|
140
|
+
it "should work" do
|
141
|
+
@doc.copy @docid
|
142
|
+
newdoc = @db.get(@docid)
|
143
|
+
newdoc['key'].should == 'value'
|
144
|
+
end
|
145
|
+
it "should fail without a database" do
|
146
|
+
lambda{CouchRest::Document.new({"not"=>"a real doc"}).copy}.should raise_error(ArgumentError)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
describe "to an existing location" do
|
150
|
+
before :each do
|
151
|
+
@db.save({'_id' => @docid, 'will-exist' => 'here'})
|
152
|
+
end
|
153
|
+
it "should fail without a rev" do
|
154
|
+
lambda{@doc.copy @docid}.should raise_error(RestClient::RequestFailed)
|
155
|
+
end
|
156
|
+
it "should succeed with a rev" do
|
157
|
+
@to_be_overwritten = @db.get(@docid)
|
158
|
+
@doc.copy "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
|
159
|
+
newdoc = @db.get(@docid)
|
160
|
+
newdoc['key'].should == 'value'
|
161
|
+
end
|
162
|
+
it "should succeed given the doc to overwrite" do
|
163
|
+
@to_be_overwritten = @db.get(@docid)
|
164
|
+
@doc.copy @to_be_overwritten
|
165
|
+
newdoc = @db.get(@docid)
|
166
|
+
newdoc['key'].should == 'value'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "MOVE existing document" do
|
172
|
+
before :each do
|
173
|
+
@db = reset_test_db!
|
174
|
+
@resp = @db.save({'key' => 'value'})
|
175
|
+
@docid = 'new-location'
|
176
|
+
@doc = @db.get(@resp['id'])
|
177
|
+
end
|
178
|
+
describe "to a new location" do
|
179
|
+
it "should work" do
|
180
|
+
@doc.move @docid
|
181
|
+
newdoc = @db.get(@docid)
|
182
|
+
newdoc['key'].should == 'value'
|
183
|
+
lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
|
184
|
+
end
|
185
|
+
it "should fail without a database" do
|
186
|
+
lambda{CouchRest::Document.new({"not"=>"a real doc"}).move}.should raise_error(ArgumentError)
|
187
|
+
lambda{CouchRest::Document.new({"_id"=>"not a real doc"}).move}.should raise_error(ArgumentError)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
describe "to an existing location" do
|
191
|
+
before :each do
|
192
|
+
@db.save({'_id' => @docid, 'will-exist' => 'here'})
|
193
|
+
end
|
194
|
+
it "should fail without a rev" do
|
195
|
+
lambda{@doc.move @docid}.should raise_error(RestClient::RequestFailed)
|
196
|
+
lambda{@db.get(@resp['id'])}.should_not raise_error
|
197
|
+
end
|
198
|
+
it "should succeed with a rev" do
|
199
|
+
@to_be_overwritten = @db.get(@docid)
|
200
|
+
@doc.move "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
|
201
|
+
newdoc = @db.get(@docid)
|
202
|
+
newdoc['key'].should == 'value'
|
203
|
+
lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
|
204
|
+
end
|
205
|
+
it "should succeed given the doc to overwrite" do
|
206
|
+
@to_be_overwritten = @db.get(@docid)
|
207
|
+
@doc.move @to_be_overwritten
|
208
|
+
newdoc = @db.get(@docid)
|
209
|
+
newdoc['key'].should == 'value'
|
210
|
+
lambda {@db.get(@resp['id'])}.should raise_error(RestClient::ResourceNotFound)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: couchrest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.12.
|
4
|
+
version: 0.12.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- J. Chris Anderson
|
@@ -10,7 +10,7 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
|
12
12
|
date: 2008-11-22 00:00:00 -08:00
|
13
|
-
default_executable:
|
13
|
+
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -42,20 +42,10 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: "1.15"
|
44
44
|
version:
|
45
|
-
- !ruby/object:Gem::Dependency
|
46
|
-
name: extlib
|
47
|
-
type: :runtime
|
48
|
-
version_requirement:
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 0.9.6
|
54
|
-
version:
|
55
45
|
description: CouchRest provides a simple interface on top of CouchDB's RESTful HTTP API, as well as including some utility scripts for managing views and attachments.
|
56
46
|
email: jchris@apache.org
|
57
|
-
executables:
|
58
|
-
|
47
|
+
executables: []
|
48
|
+
|
59
49
|
extensions: []
|
60
50
|
|
61
51
|
extra_rdoc_files:
|
@@ -67,7 +57,6 @@ files:
|
|
67
57
|
- README.md
|
68
58
|
- Rakefile
|
69
59
|
- THANKS.md
|
70
|
-
- bin/couchdir
|
71
60
|
- examples/model
|
72
61
|
- examples/model/example.rb
|
73
62
|
- examples/word_count
|
@@ -84,6 +73,7 @@ files:
|
|
84
73
|
- examples/word_count/views/word_count/count-reduce.js
|
85
74
|
- examples/word_count/word_count.rb
|
86
75
|
- examples/word_count/word_count_query.rb
|
76
|
+
- examples/word_count/word_count_views.rb
|
87
77
|
- lib/couchrest
|
88
78
|
- lib/couchrest/commands
|
89
79
|
- lib/couchrest/commands/generate.rb
|
data/bin/couchdir
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
unless ARGV.length >= 2
|
4
|
-
puts "usage: couchdir path/to/directory db-name [docid]"
|
5
|
-
exit
|
6
|
-
end
|
7
|
-
|
8
|
-
require 'rubygems'
|
9
|
-
require 'couchrest'
|
10
|
-
|
11
|
-
dirname = ARGV[0]
|
12
|
-
dbname = ARGV[1]
|
13
|
-
docid = ARGV[2]
|
14
|
-
|
15
|
-
puts "Create attachments for the files in #{dirname} in database #{dbname}."
|
16
|
-
|
17
|
-
fm = CouchRest::FileManager.new(dbname)
|
18
|
-
fm.loud = true
|
19
|
-
puts "Pushing views from directory #{dirname} to database #{fm.db}"
|
20
|
-
fm.push_directory(dirname, docid)
|