mattly-couchrest 0.12.1 → 0.12.2
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 +4 -41
- data/examples/word_count/word_count.rb +3 -24
- data/examples/word_count/word_count_query.rb +7 -6
- data/lib/couchrest/core/document.rb +12 -0
- data/lib/couchrest/core/model.rb +8 -7
- data/lib/couchrest/monkeypatches.rb +15 -1
- data/lib/couchrest.rb +1 -1
- data/spec/couchrest/core/database_spec.rb +0 -1
- data/spec/couchrest/core/document_spec.rb +83 -0
- metadata +1 -24
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
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
require 'rake'
|
|
2
2
|
require "rake/rdoctask"
|
|
3
|
+
require 'rake/gempackagetask'
|
|
4
|
+
require File.join(File.expand_path(File.dirname(__FILE__)),'lib','couchrest')
|
|
5
|
+
|
|
3
6
|
|
|
4
7
|
begin
|
|
5
8
|
require 'spec/rake/spectask'
|
|
@@ -11,10 +14,6 @@ EOS
|
|
|
11
14
|
exit(0)
|
|
12
15
|
end
|
|
13
16
|
|
|
14
|
-
# require 'rake/gempackagetask'
|
|
15
|
-
|
|
16
|
-
require File.join(File.expand_path(File.dirname(__FILE__)),'lib','couchrest')
|
|
17
|
-
|
|
18
17
|
spec = Gem::Specification.new do |s|
|
|
19
18
|
s.name = "couchrest"
|
|
20
19
|
s.version = CouchRest::VERSION
|
|
@@ -38,9 +37,7 @@ spec = Gem::Specification.new do |s|
|
|
|
38
37
|
s.add_dependency("extlib", ">= 0.9.6")
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
desc "Update Github Gemspec"
|
|
40
|
+
desc "create .gemspec file (useful for github)"
|
|
44
41
|
task :gemspec do
|
|
45
42
|
filename = "#{spec.name}.gemspec"
|
|
46
43
|
File.open(filename, "w") do |f|
|
|
@@ -48,40 +45,6 @@ task :gemspec do
|
|
|
48
45
|
end
|
|
49
46
|
end
|
|
50
47
|
|
|
51
|
-
# desc "Update Github Gemspec"
|
|
52
|
-
# task :gemspec do
|
|
53
|
-
# skip_fields = %w(new_platform original_platform)
|
|
54
|
-
# integer_fields = %w(specification_version)
|
|
55
|
-
#
|
|
56
|
-
# result = "Gem::Specification.new do |s|\n"
|
|
57
|
-
# spec.instance_variables.each do |ivar|
|
|
58
|
-
# value = spec.instance_variable_get(ivar)
|
|
59
|
-
# name = ivar.split("@").last
|
|
60
|
-
# next if skip_fields.include?(name) || value.nil? || value == "" || (value.respond_to?(:empty?) && value.empty?)
|
|
61
|
-
# if name == "dependencies"
|
|
62
|
-
# value.each do |d|
|
|
63
|
-
# dep, *ver = d.to_s.split(" ")
|
|
64
|
-
# result << " s.add_dependency #{dep.inspect}, [#{ /\(([^\,]*)/ . match(ver.join(" "))[1].inspect}]\n"
|
|
65
|
-
# end
|
|
66
|
-
# else
|
|
67
|
-
# case value
|
|
68
|
-
# when Array
|
|
69
|
-
# value = name != "files" ? value.inspect : value.inspect.split(",").join(",\n")
|
|
70
|
-
# when Fixnum
|
|
71
|
-
# # leave as-is
|
|
72
|
-
# when String
|
|
73
|
-
# value = value.to_i if integer_fields.include?(name)
|
|
74
|
-
# value = value.inspect
|
|
75
|
-
# else
|
|
76
|
-
# value = value.to_s.inspect
|
|
77
|
-
# end
|
|
78
|
-
# result << " s.#{name} = #{value}\n"
|
|
79
|
-
# end
|
|
80
|
-
# end
|
|
81
|
-
# result << "end"
|
|
82
|
-
# File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w"){|f| f << result}
|
|
83
|
-
# end
|
|
84
|
-
|
|
85
48
|
desc "Run all specs"
|
|
86
49
|
Spec::Rake::SpecTask.new('spec') do |t|
|
|
87
50
|
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:"
|
|
@@ -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
|
@@ -4,9 +4,9 @@ require 'digest/md5'
|
|
|
4
4
|
require File.dirname(__FILE__) + '/document'
|
|
5
5
|
require 'mime/types'
|
|
6
6
|
|
|
7
|
-
# = CouchRest::Model -
|
|
7
|
+
# = CouchRest::Model - Document modeling, the CouchDB way
|
|
8
8
|
module CouchRest
|
|
9
|
-
# = CouchRest::Model -
|
|
9
|
+
# = CouchRest::Model - Document modeling, the CouchDB way
|
|
10
10
|
#
|
|
11
11
|
# CouchRest::Model provides an ORM-like interface for CouchDB documents. It
|
|
12
12
|
# avoids all usage of <tt>method_missing</tt>, and tries to strike a balance
|
|
@@ -550,11 +550,12 @@ module CouchRest
|
|
|
550
550
|
return unless new_document?
|
|
551
551
|
if self.class.default
|
|
552
552
|
self.class.default.each do |k,v|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
553
|
+
unless self.key?(k.to_s)
|
|
554
|
+
if v.class == Proc
|
|
555
|
+
self[k.to_s] = v.call
|
|
556
|
+
else
|
|
557
|
+
self[k.to_s] = Marshal.load(Marshal.dump(v))
|
|
558
|
+
end
|
|
558
559
|
end
|
|
559
560
|
end
|
|
560
561
|
end
|
|
@@ -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
|
@@ -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: mattly-couchrest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.12.
|
|
4
|
+
version: 0.12.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- J. Chris Anderson
|
|
@@ -94,16 +94,6 @@ files:
|
|
|
94
94
|
- lib/couchrest/helper
|
|
95
95
|
- lib/couchrest/helper/pager.rb
|
|
96
96
|
- lib/couchrest/helper/streamer.rb
|
|
97
|
-
- lib/couchrest/helper/template-app
|
|
98
|
-
- lib/couchrest/helper/template-app/_attachments
|
|
99
|
-
- lib/couchrest/helper/template-app/foo
|
|
100
|
-
- lib/couchrest/helper/template-app/forms
|
|
101
|
-
- lib/couchrest/helper/template-app/lib
|
|
102
|
-
- lib/couchrest/helper/template-app/lib/helpers
|
|
103
|
-
- lib/couchrest/helper/template-app/lib/templates
|
|
104
|
-
- lib/couchrest/helper/template-app/views
|
|
105
|
-
- lib/couchrest/helper/template-app/views/example
|
|
106
|
-
- lib/couchrest/helper/templates
|
|
107
97
|
- lib/couchrest/monkeypatches.rb
|
|
108
98
|
- lib/couchrest.rb
|
|
109
99
|
- spec/couchrest
|
|
@@ -121,19 +111,6 @@ files:
|
|
|
121
111
|
- spec/fixtures/attachments/couchdb.png
|
|
122
112
|
- spec/fixtures/attachments/README
|
|
123
113
|
- spec/fixtures/attachments/test.html
|
|
124
|
-
- spec/fixtures/couchapp
|
|
125
|
-
- spec/fixtures/couchapp/attachments
|
|
126
|
-
- spec/fixtures/couchapp/attachments/index.html
|
|
127
|
-
- spec/fixtures/couchapp/views
|
|
128
|
-
- spec/fixtures/couchapp/views/example-map.js
|
|
129
|
-
- spec/fixtures/couchapp/views/example-reduce.js
|
|
130
|
-
- spec/fixtures/couchapp-test
|
|
131
|
-
- spec/fixtures/couchapp-test/my-app
|
|
132
|
-
- spec/fixtures/couchapp-test/my-app/attachments
|
|
133
|
-
- spec/fixtures/couchapp-test/my-app/attachments/index.html
|
|
134
|
-
- spec/fixtures/couchapp-test/my-app/views
|
|
135
|
-
- spec/fixtures/couchapp-test/my-app/views/example-map.js
|
|
136
|
-
- spec/fixtures/couchapp-test/my-app/views/example-reduce.js
|
|
137
114
|
- spec/fixtures/views
|
|
138
115
|
- spec/fixtures/views/lib.js
|
|
139
116
|
- spec/fixtures/views/test_view
|