jchris-couchrest 0.2.2 → 0.7.99
Sign up to get free protection for your applications and to get access to all the features.
- data/README +39 -0
- data/Rakefile +3 -54
- data/lib/couchrest.rb +39 -161
- data/lib/database.rb +83 -0
- data/script/couchdir +58 -0
- data/script/couchview +158 -0
- data/spec/couchrest_spec.rb +86 -0
- data/spec/database_spec.rb +407 -0
- metadata +15 -138
- data/LICENSE +0 -176
- data/README.md +0 -93
- data/THANKS.md +0 -18
- data/examples/model/example.rb +0 -144
- data/examples/word_count/markov +0 -38
- data/examples/word_count/views/books/chunked-map.js +0 -3
- data/examples/word_count/views/books/united-map.js +0 -1
- data/examples/word_count/views/markov/chain-map.js +0 -6
- data/examples/word_count/views/markov/chain-reduce.js +0 -7
- data/examples/word_count/views/word_count/count-map.js +0 -6
- data/examples/word_count/views/word_count/count-reduce.js +0 -3
- data/examples/word_count/word_count.rb +0 -46
- data/examples/word_count/word_count_query.rb +0 -40
- data/examples/word_count/word_count_views.rb +0 -26
- data/lib/couchrest/commands/generate.rb +0 -71
- data/lib/couchrest/commands/push.rb +0 -103
- data/lib/couchrest/core/database.rb +0 -318
- data/lib/couchrest/core/design.rb +0 -89
- data/lib/couchrest/core/document.rb +0 -96
- data/lib/couchrest/core/response.rb +0 -16
- data/lib/couchrest/core/server.rb +0 -88
- data/lib/couchrest/core/view.rb +0 -4
- data/lib/couchrest/helper/pager.rb +0 -103
- data/lib/couchrest/helper/streamer.rb +0 -44
- data/lib/couchrest/helper/upgrade.rb +0 -51
- data/lib/couchrest/mixins.rb +0 -4
- data/lib/couchrest/mixins/attachments.rb +0 -31
- data/lib/couchrest/mixins/callbacks.rb +0 -483
- data/lib/couchrest/mixins/design_doc.rb +0 -64
- data/lib/couchrest/mixins/document_queries.rb +0 -48
- data/lib/couchrest/mixins/extended_attachments.rb +0 -68
- data/lib/couchrest/mixins/extended_document_mixins.rb +0 -6
- data/lib/couchrest/mixins/properties.rb +0 -125
- data/lib/couchrest/mixins/validation.rb +0 -234
- data/lib/couchrest/mixins/views.rb +0 -168
- data/lib/couchrest/monkeypatches.rb +0 -119
- data/lib/couchrest/more/casted_model.rb +0 -28
- data/lib/couchrest/more/extended_document.rb +0 -217
- data/lib/couchrest/more/property.rb +0 -40
- data/lib/couchrest/support/blank.rb +0 -42
- data/lib/couchrest/support/class.rb +0 -191
- data/lib/couchrest/validation/auto_validate.rb +0 -163
- data/lib/couchrest/validation/contextual_validators.rb +0 -78
- data/lib/couchrest/validation/validation_errors.rb +0 -118
- data/lib/couchrest/validation/validators/absent_field_validator.rb +0 -74
- data/lib/couchrest/validation/validators/confirmation_validator.rb +0 -99
- data/lib/couchrest/validation/validators/format_validator.rb +0 -117
- data/lib/couchrest/validation/validators/formats/email.rb +0 -66
- data/lib/couchrest/validation/validators/formats/url.rb +0 -43
- data/lib/couchrest/validation/validators/generic_validator.rb +0 -120
- data/lib/couchrest/validation/validators/length_validator.rb +0 -134
- data/lib/couchrest/validation/validators/method_validator.rb +0 -89
- data/lib/couchrest/validation/validators/numeric_validator.rb +0 -104
- data/lib/couchrest/validation/validators/required_field_validator.rb +0 -109
- data/spec/couchrest/core/couchrest_spec.rb +0 -201
- data/spec/couchrest/core/database_spec.rb +0 -745
- data/spec/couchrest/core/design_spec.rb +0 -131
- data/spec/couchrest/core/document_spec.rb +0 -311
- data/spec/couchrest/core/server_spec.rb +0 -35
- data/spec/couchrest/helpers/pager_spec.rb +0 -122
- data/spec/couchrest/helpers/streamer_spec.rb +0 -23
- data/spec/couchrest/more/casted_extended_doc_spec.rb +0 -40
- data/spec/couchrest/more/casted_model_spec.rb +0 -98
- data/spec/couchrest/more/extended_doc_attachment_spec.rb +0 -130
- data/spec/couchrest/more/extended_doc_spec.rb +0 -509
- data/spec/couchrest/more/extended_doc_view_spec.rb +0 -207
- data/spec/couchrest/more/property_spec.rb +0 -130
- data/spec/couchrest/support/class_spec.rb +0 -59
- data/spec/fixtures/attachments/README +0 -3
- data/spec/fixtures/attachments/couchdb.png +0 -0
- data/spec/fixtures/attachments/test.html +0 -11
- data/spec/fixtures/more/article.rb +0 -34
- data/spec/fixtures/more/card.rb +0 -20
- data/spec/fixtures/more/course.rb +0 -14
- data/spec/fixtures/more/event.rb +0 -6
- data/spec/fixtures/more/invoice.rb +0 -17
- data/spec/fixtures/more/person.rb +0 -8
- data/spec/fixtures/more/question.rb +0 -6
- data/spec/fixtures/more/service.rb +0 -12
- data/spec/fixtures/views/lib.js +0 -3
- data/spec/fixtures/views/test_view/lib.js +0 -3
- data/spec/fixtures/views/test_view/only-map.js +0 -4
- data/spec/fixtures/views/test_view/test-map.js +0 -3
- data/spec/fixtures/views/test_view/test-reduce.js +0 -3
- data/spec/spec.opts +0 -6
- data/spec/spec_helper.rb +0 -26
- data/utils/remap.rb +0 -27
- data/utils/subset.rb +0 -30
@@ -1,318 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
require "base64"
|
3
|
-
|
4
|
-
module CouchRest
|
5
|
-
class Database
|
6
|
-
attr_reader :server, :host, :name, :root, :uri
|
7
|
-
attr_accessor :bulk_save_cache_limit
|
8
|
-
|
9
|
-
# Create a CouchRest::Database adapter for the supplied CouchRest::Server
|
10
|
-
# and database name.
|
11
|
-
#
|
12
|
-
# ==== Parameters
|
13
|
-
# server<CouchRest::Server>:: database host
|
14
|
-
# name<String>:: database name
|
15
|
-
#
|
16
|
-
def initialize(server, name)
|
17
|
-
@name = name
|
18
|
-
@server = server
|
19
|
-
@host = server.uri
|
20
|
-
@uri = @root = "#{host}/#{name}"
|
21
|
-
@streamer = Streamer.new(self)
|
22
|
-
@bulk_save_cache = []
|
23
|
-
@bulk_save_cache_limit = 500 # must be smaller than the uuid count
|
24
|
-
end
|
25
|
-
|
26
|
-
# returns the database's uri
|
27
|
-
def to_s
|
28
|
-
@uri
|
29
|
-
end
|
30
|
-
|
31
|
-
# GET the database info from CouchDB
|
32
|
-
def info
|
33
|
-
CouchRest.get @uri
|
34
|
-
end
|
35
|
-
|
36
|
-
# Query the <tt>_all_docs</tt> view. Accepts all the same arguments as view.
|
37
|
-
def documents(params = {})
|
38
|
-
keys = params.delete(:keys)
|
39
|
-
url = CouchRest.paramify_url "#{@uri}/_all_docs", params
|
40
|
-
if keys
|
41
|
-
CouchRest.post(url, {:keys => keys})
|
42
|
-
else
|
43
|
-
CouchRest.get url
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# POST a temporary view function to CouchDB for querying. This is not
|
48
|
-
# recommended, as you don't get any performance benefit from CouchDB's
|
49
|
-
# materialized views. Can be quite slow on large databases.
|
50
|
-
def slow_view(funcs, params = {})
|
51
|
-
keys = params.delete(:keys)
|
52
|
-
funcs = funcs.merge({:keys => keys}) if keys
|
53
|
-
url = CouchRest.paramify_url "#{@uri}/_temp_view", params
|
54
|
-
JSON.parse(RestClient.post(url, funcs.to_json, {"Content-Type" => 'application/json'}))
|
55
|
-
end
|
56
|
-
|
57
|
-
# backwards compatibility is a plus
|
58
|
-
alias :temp_view :slow_view
|
59
|
-
|
60
|
-
# Query a CouchDB view as defined by a <tt>_design</tt> document. Accepts
|
61
|
-
# paramaters as described in http://wiki.apache.org/couchdb/HttpViewApi
|
62
|
-
def view(name, params = {}, &block)
|
63
|
-
keys = params.delete(:keys)
|
64
|
-
name = name.split('/') # I think this will always be length == 2, but maybe not...
|
65
|
-
dname = name.shift
|
66
|
-
vname = name.join('/')
|
67
|
-
url = CouchRest.paramify_url "#{@uri}/_design/#{dname}/_view/#{vname}", params
|
68
|
-
if keys
|
69
|
-
CouchRest.post(url, {:keys => keys})
|
70
|
-
else
|
71
|
-
if block_given?
|
72
|
-
@streamer.view("_design/#{dname}/_view/#{vname}", params, &block)
|
73
|
-
else
|
74
|
-
CouchRest.get url
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
# GET a document from CouchDB, by id. Returns a Ruby Hash.
|
80
|
-
def get(id, params = {})
|
81
|
-
slug = escape_docid(id)
|
82
|
-
url = CouchRest.paramify_url("#{@uri}/#{slug}", params)
|
83
|
-
result = CouchRest.get(url)
|
84
|
-
return result unless result.is_a?(Hash)
|
85
|
-
doc = if /^_design/ =~ result["_id"]
|
86
|
-
Design.new(result)
|
87
|
-
else
|
88
|
-
Document.new(result)
|
89
|
-
end
|
90
|
-
doc.database = self
|
91
|
-
doc
|
92
|
-
end
|
93
|
-
|
94
|
-
# GET an attachment directly from CouchDB
|
95
|
-
def fetch_attachment(doc, name)
|
96
|
-
# slug = escape_docid(docid)
|
97
|
-
# name = CGI.escape(name)
|
98
|
-
uri = uri_for_attachment(doc, name)
|
99
|
-
RestClient.get uri
|
100
|
-
# "#{@uri}/#{slug}/#{name}"
|
101
|
-
end
|
102
|
-
|
103
|
-
# PUT an attachment directly to CouchDB
|
104
|
-
def put_attachment(doc, name, file, options = {})
|
105
|
-
docid = escape_docid(doc['_id'])
|
106
|
-
name = CGI.escape(name)
|
107
|
-
uri = uri_for_attachment(doc, name)
|
108
|
-
JSON.parse(RestClient.put(uri, file, options))
|
109
|
-
end
|
110
|
-
|
111
|
-
# DELETE an attachment directly from CouchDB
|
112
|
-
def delete_attachment doc, name
|
113
|
-
uri = uri_for_attachment(doc, name)
|
114
|
-
# this needs a rev
|
115
|
-
JSON.parse(RestClient.delete(uri))
|
116
|
-
end
|
117
|
-
|
118
|
-
# Save a document to CouchDB. This will use the <tt>_id</tt> field from
|
119
|
-
# the document as the id for PUT, or request a new UUID from CouchDB, if
|
120
|
-
# no <tt>_id</tt> is present on the document. IDs are attached to
|
121
|
-
# documents on the client side because POST has the curious property of
|
122
|
-
# being automatically retried by proxies in the event of network
|
123
|
-
# segmentation and lost responses.
|
124
|
-
#
|
125
|
-
# If <tt>bulk</tt> is true (false by default) the document is cached for bulk-saving later.
|
126
|
-
# Bulk saving happens automatically when #bulk_save_cache limit is exceded, or on the next non bulk save.
|
127
|
-
def save_doc(doc, bulk = false)
|
128
|
-
if doc['_attachments']
|
129
|
-
doc['_attachments'] = encode_attachments(doc['_attachments'])
|
130
|
-
end
|
131
|
-
if bulk
|
132
|
-
@bulk_save_cache << doc
|
133
|
-
return bulk_save if @bulk_save_cache.length >= @bulk_save_cache_limit
|
134
|
-
return {"ok" => true} # Compatibility with Document#save
|
135
|
-
elsif !bulk && @bulk_save_cache.length > 0
|
136
|
-
bulk_save
|
137
|
-
end
|
138
|
-
result = if doc['_id']
|
139
|
-
slug = escape_docid(doc['_id'])
|
140
|
-
CouchRest.put "#{@uri}/#{slug}", doc
|
141
|
-
else
|
142
|
-
begin
|
143
|
-
slug = doc['_id'] = @server.next_uuid
|
144
|
-
CouchRest.put "#{@uri}/#{slug}", doc
|
145
|
-
rescue #old version of couchdb
|
146
|
-
CouchRest.post @uri, doc
|
147
|
-
end
|
148
|
-
end
|
149
|
-
if result['ok']
|
150
|
-
doc['_id'] = result['id']
|
151
|
-
doc['_rev'] = result['rev']
|
152
|
-
doc.database = self if doc.respond_to?(:database=)
|
153
|
-
end
|
154
|
-
result
|
155
|
-
end
|
156
|
-
|
157
|
-
### DEPRECATION NOTICE
|
158
|
-
def save(doc, bulk=false)
|
159
|
-
puts "CouchRest::Database's save method is being deprecated, please use save_doc instead"
|
160
|
-
save_doc(doc, bulk)
|
161
|
-
end
|
162
|
-
|
163
|
-
|
164
|
-
# POST an array of documents to CouchDB. If any of the documents are
|
165
|
-
# missing ids, supply one from the uuid cache.
|
166
|
-
#
|
167
|
-
# If called with no arguments, bulk saves the cache of documents to be bulk saved.
|
168
|
-
def bulk_save(docs = nil, use_uuids = true)
|
169
|
-
if docs.nil?
|
170
|
-
docs = @bulk_save_cache
|
171
|
-
@bulk_save_cache = []
|
172
|
-
end
|
173
|
-
if (use_uuids)
|
174
|
-
ids, noids = docs.partition{|d|d['_id']}
|
175
|
-
uuid_count = [noids.length, @server.uuid_batch_count].max
|
176
|
-
noids.each do |doc|
|
177
|
-
nextid = @server.next_uuid(uuid_count) rescue nil
|
178
|
-
doc['_id'] = nextid if nextid
|
179
|
-
end
|
180
|
-
end
|
181
|
-
CouchRest.post "#{@uri}/_bulk_docs", {:docs => docs}
|
182
|
-
end
|
183
|
-
alias :bulk_delete :bulk_save
|
184
|
-
|
185
|
-
# DELETE the document from CouchDB that has the given <tt>_id</tt> and
|
186
|
-
# <tt>_rev</tt>.
|
187
|
-
#
|
188
|
-
# If <tt>bulk</tt> is true (false by default) the deletion is recorded for bulk-saving (bulk-deletion :) later.
|
189
|
-
# Bulk saving happens automatically when #bulk_save_cache limit is exceded, or on the next non bulk save.
|
190
|
-
def delete_doc(doc, bulk = false)
|
191
|
-
raise ArgumentError, "_id and _rev required for deleting" unless doc['_id'] && doc['_rev']
|
192
|
-
if bulk
|
193
|
-
@bulk_save_cache << { '_id' => doc['_id'], '_rev' => doc['_rev'], '_deleted' => true }
|
194
|
-
return bulk_save if @bulk_save_cache.length >= @bulk_save_cache_limit
|
195
|
-
return { "ok" => true } # Mimic the non-deferred version
|
196
|
-
end
|
197
|
-
slug = escape_docid(doc['_id'])
|
198
|
-
CouchRest.delete "#{@uri}/#{slug}?rev=#{doc['_rev']}"
|
199
|
-
end
|
200
|
-
|
201
|
-
### DEPRECATION NOTICE
|
202
|
-
def delete(doc, bulk=false)
|
203
|
-
puts "CouchRest::Database's delete method is being deprecated, please use delete_doc instead"
|
204
|
-
delete_doc(doc, bulk)
|
205
|
-
end
|
206
|
-
|
207
|
-
# COPY an existing document to a new id. If the destination id currently exists, a rev must be provided.
|
208
|
-
# <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
|
209
|
-
# hash with a '_rev' key
|
210
|
-
def copy_doc(doc, dest)
|
211
|
-
raise ArgumentError, "_id is required for copying" unless doc['_id']
|
212
|
-
slug = escape_docid(doc['_id'])
|
213
|
-
destination = if dest.respond_to?(:has_key?) && dest['_id'] && dest['_rev']
|
214
|
-
"#{dest['_id']}?rev=#{dest['_rev']}"
|
215
|
-
else
|
216
|
-
dest
|
217
|
-
end
|
218
|
-
CouchRest.copy "#{@uri}/#{slug}", destination
|
219
|
-
end
|
220
|
-
|
221
|
-
### DEPRECATION NOTICE
|
222
|
-
def copy(doc, dest)
|
223
|
-
puts "CouchRest::Database's copy method is being deprecated, please use copy_doc instead"
|
224
|
-
copy_doc(doc, dest)
|
225
|
-
end
|
226
|
-
|
227
|
-
# MOVE an existing document to a new id. If the destination id currently exists, a rev must be provided.
|
228
|
-
# <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
|
229
|
-
# hash with a '_rev' key
|
230
|
-
def move_doc(doc, dest)
|
231
|
-
raise ArgumentError, "_id and _rev are required for moving" unless doc['_id'] && doc['_rev']
|
232
|
-
slug = escape_docid(doc['_id'])
|
233
|
-
destination = if dest.respond_to?(:has_key?) && dest['_id'] && dest['_rev']
|
234
|
-
"#{dest['_id']}?rev=#{dest['_rev']}"
|
235
|
-
else
|
236
|
-
dest
|
237
|
-
end
|
238
|
-
CouchRest.move "#{@uri}/#{slug}?rev=#{doc['_rev']}", destination
|
239
|
-
end
|
240
|
-
|
241
|
-
### DEPRECATION NOTICE
|
242
|
-
def move(doc, dest)
|
243
|
-
puts "CouchRest::Database's move method is being deprecated, please use move_doc instead"
|
244
|
-
move_doc(doc, dest)
|
245
|
-
end
|
246
|
-
|
247
|
-
# Compact the database, removing old document revisions and optimizing space use.
|
248
|
-
def compact!
|
249
|
-
CouchRest.post "#{@uri}/_compact"
|
250
|
-
end
|
251
|
-
|
252
|
-
# Create the database
|
253
|
-
def create!
|
254
|
-
bool = server.create_db(@name) rescue false
|
255
|
-
bool && true
|
256
|
-
end
|
257
|
-
|
258
|
-
# Delete and re create the database
|
259
|
-
def recreate!
|
260
|
-
delete!
|
261
|
-
create!
|
262
|
-
rescue RestClient::ResourceNotFound
|
263
|
-
ensure
|
264
|
-
create!
|
265
|
-
end
|
266
|
-
|
267
|
-
# Replicates via "pulling" from another database to this database. Makes no attempt to deal with conflicts.
|
268
|
-
def replicate_from other_db
|
269
|
-
raise ArgumentError, "must provide a CouchReset::Database" unless other_db.kind_of?(CouchRest::Database)
|
270
|
-
CouchRest.post "#{@host}/_replicate", :source => other_db.root, :target => name
|
271
|
-
end
|
272
|
-
|
273
|
-
# Replicates via "pushing" to another database. Makes no attempt to deal with conflicts.
|
274
|
-
def replicate_to other_db
|
275
|
-
raise ArgumentError, "must provide a CouchReset::Database" unless other_db.kind_of?(CouchRest::Database)
|
276
|
-
CouchRest.post "#{@host}/_replicate", :target => other_db.root, :source => name
|
277
|
-
end
|
278
|
-
|
279
|
-
# DELETE the database itself. This is not undoable and could be rather
|
280
|
-
# catastrophic. Use with care!
|
281
|
-
def delete!
|
282
|
-
CouchRest.delete @uri
|
283
|
-
end
|
284
|
-
|
285
|
-
private
|
286
|
-
|
287
|
-
def uri_for_attachment(doc, name)
|
288
|
-
if doc.is_a?(String)
|
289
|
-
puts "CouchRest::Database#fetch_attachment will eventually require a doc as the first argument, not a doc.id"
|
290
|
-
docid = doc
|
291
|
-
rev = nil
|
292
|
-
else
|
293
|
-
docid = doc['_id']
|
294
|
-
rev = doc['_rev']
|
295
|
-
end
|
296
|
-
docid = escape_docid(docid)
|
297
|
-
name = CGI.escape(name)
|
298
|
-
rev = "?rev=#{doc['_rev']}" if rev
|
299
|
-
"#{@root}/#{docid}/#{name}#{rev}"
|
300
|
-
end
|
301
|
-
|
302
|
-
def escape_docid id
|
303
|
-
/^_design\/(.*)/ =~ id ? "_design/#{CGI.escape($1)}" : CGI.escape(id)
|
304
|
-
end
|
305
|
-
|
306
|
-
def encode_attachments(attachments)
|
307
|
-
attachments.each do |k,v|
|
308
|
-
next if v['stub']
|
309
|
-
v['data'] = base64(v['data'])
|
310
|
-
end
|
311
|
-
attachments
|
312
|
-
end
|
313
|
-
|
314
|
-
def base64(data)
|
315
|
-
Base64.encode64(data).gsub(/\s/,'')
|
316
|
-
end
|
317
|
-
end
|
318
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
module CouchRest
|
2
|
-
class Design < Document
|
3
|
-
def view_by *keys
|
4
|
-
opts = keys.pop if keys.last.is_a?(Hash)
|
5
|
-
opts ||= {}
|
6
|
-
self['views'] ||= {}
|
7
|
-
method_name = "by_#{keys.join('_and_')}"
|
8
|
-
|
9
|
-
if opts[:map]
|
10
|
-
view = {}
|
11
|
-
view['map'] = opts.delete(:map)
|
12
|
-
if opts[:reduce]
|
13
|
-
view['reduce'] = opts.delete(:reduce)
|
14
|
-
opts[:reduce] = false
|
15
|
-
end
|
16
|
-
self['views'][method_name] = view
|
17
|
-
else
|
18
|
-
doc_keys = keys.collect{|k|"doc['#{k}']"} # this is where :require => 'doc.x == true' would show up
|
19
|
-
key_emit = doc_keys.length == 1 ? "#{doc_keys.first}" : "[#{doc_keys.join(', ')}]"
|
20
|
-
guards = opts.delete(:guards) || []
|
21
|
-
guards.concat doc_keys
|
22
|
-
map_function = <<-JAVASCRIPT
|
23
|
-
function(doc) {
|
24
|
-
if (#{guards.join(' && ')}) {
|
25
|
-
emit(#{key_emit}, null);
|
26
|
-
}
|
27
|
-
}
|
28
|
-
JAVASCRIPT
|
29
|
-
self['views'][method_name] = {
|
30
|
-
'map' => map_function
|
31
|
-
}
|
32
|
-
end
|
33
|
-
self['views'][method_name]['couchrest-defaults'] = opts unless opts.empty?
|
34
|
-
method_name
|
35
|
-
end
|
36
|
-
|
37
|
-
# Dispatches to any named view.
|
38
|
-
def view view_name, query={}, &block
|
39
|
-
view_name = view_name.to_s
|
40
|
-
view_slug = "#{name}/#{view_name}"
|
41
|
-
defaults = (self['views'][view_name] && self['views'][view_name]["couchrest-defaults"]) || {}
|
42
|
-
fetch_view(view_slug, defaults.merge(query), &block)
|
43
|
-
end
|
44
|
-
|
45
|
-
def name
|
46
|
-
id.sub('_design/','') if id
|
47
|
-
end
|
48
|
-
|
49
|
-
def name= newname
|
50
|
-
self['_id'] = "_design/#{newname}"
|
51
|
-
end
|
52
|
-
|
53
|
-
def save
|
54
|
-
raise ArgumentError, "_design docs require a name" unless name && name.length > 0
|
55
|
-
super
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
# returns stored defaults if the there is a view named this in the design doc
|
61
|
-
def has_view?(view)
|
62
|
-
view = view.to_s
|
63
|
-
self['views'][view] &&
|
64
|
-
(self['views'][view]["couchrest-defaults"]||{})
|
65
|
-
end
|
66
|
-
|
67
|
-
# def fetch_view_with_docs name, opts, raw=false, &block
|
68
|
-
# if raw
|
69
|
-
# fetch_view name, opts, &block
|
70
|
-
# else
|
71
|
-
# begin
|
72
|
-
# view = fetch_view name, opts.merge({:include_docs => true}), &block
|
73
|
-
# view['rows'].collect{|r|new(r['doc'])} if view['rows']
|
74
|
-
# rescue
|
75
|
-
# # fallback for old versions of couchdb that don't
|
76
|
-
# # have include_docs support
|
77
|
-
# view = fetch_view name, opts, &block
|
78
|
-
# view['rows'].collect{|r|new(database.get(r['id']))} if view['rows']
|
79
|
-
# end
|
80
|
-
# end
|
81
|
-
# end
|
82
|
-
|
83
|
-
def fetch_view view_name, opts, &block
|
84
|
-
database.view(view_name, opts, &block)
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
require 'delegate'
|
2
|
-
|
3
|
-
module CouchRest
|
4
|
-
class Document < Response
|
5
|
-
include CouchRest::Mixins::Attachments
|
6
|
-
|
7
|
-
# def self.inherited(subklass)
|
8
|
-
# subklass.send(:class_inheritable_accessor, :database)
|
9
|
-
# end
|
10
|
-
|
11
|
-
class_inheritable_accessor :database
|
12
|
-
attr_accessor :database
|
13
|
-
|
14
|
-
# override the CouchRest::Model-wide default_database
|
15
|
-
# This is not a thread safe operation, do not change the model
|
16
|
-
# database at runtime.
|
17
|
-
def self.use_database(db)
|
18
|
-
self.database = db
|
19
|
-
end
|
20
|
-
|
21
|
-
def id
|
22
|
-
self['_id']
|
23
|
-
end
|
24
|
-
|
25
|
-
def rev
|
26
|
-
self['_rev']
|
27
|
-
end
|
28
|
-
|
29
|
-
# returns true if the document has never been saved
|
30
|
-
def new_document?
|
31
|
-
!rev
|
32
|
-
end
|
33
|
-
|
34
|
-
# Saves the document to the db using create or update. Also runs the :save
|
35
|
-
# callbacks. Sets the <tt>_id</tt> and <tt>_rev</tt> fields based on
|
36
|
-
# CouchDB's response.
|
37
|
-
# If <tt>bulk</tt> is <tt>true</tt> (defaults to false) the document is cached for bulk save.
|
38
|
-
def save(bulk = false)
|
39
|
-
raise ArgumentError, "doc.database required for saving" unless database
|
40
|
-
result = database.save_doc self, bulk
|
41
|
-
result['ok']
|
42
|
-
end
|
43
|
-
|
44
|
-
# Deletes the document from the database. Runs the :delete callbacks.
|
45
|
-
# Removes the <tt>_id</tt> and <tt>_rev</tt> fields, preparing the
|
46
|
-
# document to be saved to a new <tt>_id</tt>.
|
47
|
-
# If <tt>bulk</tt> is <tt>true</tt> (defaults to false) the document won't
|
48
|
-
# actually be deleted from the db until bulk save.
|
49
|
-
def destroy(bulk = false)
|
50
|
-
raise ArgumentError, "doc.database required to destroy" unless database
|
51
|
-
result = database.delete_doc(self, bulk)
|
52
|
-
if result['ok']
|
53
|
-
self['_rev'] = nil
|
54
|
-
self['_id'] = nil
|
55
|
-
end
|
56
|
-
result['ok']
|
57
|
-
end
|
58
|
-
|
59
|
-
# copies the document to a new id. If the destination id currently exists, a rev must be provided.
|
60
|
-
# <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
|
61
|
-
# hash with a '_rev' key
|
62
|
-
def copy(dest)
|
63
|
-
raise ArgumentError, "doc.database required to copy" unless database
|
64
|
-
result = database.copy_doc(self, dest)
|
65
|
-
result['ok']
|
66
|
-
end
|
67
|
-
|
68
|
-
# moves the document to a new id. If the destination id currently exists, a rev must be provided.
|
69
|
-
# <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
|
70
|
-
# hash with a '_rev' key
|
71
|
-
def move(dest)
|
72
|
-
raise ArgumentError, "doc.database required to copy" unless database
|
73
|
-
result = database.move_doc(self, dest)
|
74
|
-
result['ok']
|
75
|
-
end
|
76
|
-
|
77
|
-
# Returns the CouchDB uri for the document
|
78
|
-
def uri(append_rev = false)
|
79
|
-
return nil if new_document?
|
80
|
-
couch_uri = "http://#{database.uri}/#{CGI.escape(id)}"
|
81
|
-
if append_rev == true
|
82
|
-
couch_uri << "?rev=#{rev}"
|
83
|
-
elsif append_rev.kind_of?(Integer)
|
84
|
-
couch_uri << "?rev=#{append_rev}"
|
85
|
-
end
|
86
|
-
couch_uri
|
87
|
-
end
|
88
|
-
|
89
|
-
# Returns the document's database
|
90
|
-
def database
|
91
|
-
@database || self.class.database
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|