sporkd-couchrest 0.31 → 0.33
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 -1
- data/history.txt +23 -10
- data/lib/couchrest/core/database.rb +13 -2
- data/lib/couchrest/core/rest_api.rb +49 -0
- data/lib/couchrest/middlewares/logger.rb +263 -0
- data/lib/couchrest/mixins/attachments.rb +2 -2
- data/lib/couchrest/mixins/class_proxy.rb +5 -1
- data/lib/couchrest/mixins/collection.rb +14 -2
- data/lib/couchrest/mixins/design_doc.rb +6 -1
- data/lib/couchrest/mixins/document_queries.rb +32 -1
- data/lib/couchrest/mixins/properties.rb +25 -6
- data/lib/couchrest/mixins/views.rb +3 -3
- data/lib/couchrest/more/casted_model.rb +4 -3
- data/lib/couchrest/validation/validation_errors.rb +7 -0
- data/lib/couchrest.rb +6 -47
- data/spec/couchrest/core/couchrest_spec.rb +1 -1
- data/spec/couchrest/core/database_spec.rb +18 -4
- data/spec/couchrest/core/design_spec.rb +1 -1
- data/spec/couchrest/core/document_spec.rb +1 -1
- data/spec/couchrest/core/server_spec.rb +1 -1
- data/spec/couchrest/helpers/pager_spec.rb +1 -1
- data/spec/couchrest/helpers/streamer_spec.rb +1 -1
- data/spec/couchrest/more/casted_extended_doc_spec.rb +1 -1
- data/spec/couchrest/more/casted_model_spec.rb +1 -1
- data/spec/couchrest/more/extended_doc_attachment_spec.rb +1 -1
- data/spec/couchrest/more/extended_doc_spec.rb +11 -2
- data/spec/couchrest/more/extended_doc_subclass_spec.rb +1 -1
- data/spec/couchrest/more/extended_doc_view_spec.rb +13 -7
- data/spec/couchrest/more/property_spec.rb +28 -1
- metadata +6 -2
data/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Note: CouchRest only support CouchDB 0.9.0 or newer.
|
|
|
17
17
|
Alternatively, you can install from Github:
|
|
18
18
|
|
|
19
19
|
$ gem sources -a http://gems.github.com (you only have to do this once)
|
|
20
|
-
$ sudo gem install
|
|
20
|
+
$ sudo gem install couchrest-couchrest
|
|
21
21
|
|
|
22
22
|
### Relax, it's RESTful
|
|
23
23
|
|
data/history.txt
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
|
-
== 0.
|
|
2
|
-
|
|
3
|
-
=== Notes
|
|
4
|
-
|
|
5
|
-
This release slightly modifies the API and if you were using a previous version of CouchRest,
|
|
6
|
-
you will need to make the following modifications.
|
|
7
|
-
|
|
1
|
+
== 0.33
|
|
8
2
|
|
|
3
|
+
* Major enhancements
|
|
9
4
|
|
|
5
|
+
* Added a new Rack logger middleware letting you log/save requests/queries (Matt Aimonetti)
|
|
6
|
+
|
|
7
|
+
* Minor enhancements
|
|
8
|
+
|
|
9
|
+
* Added #amount_pages to a paginated result array (Matt Aimonetti)
|
|
10
|
+
* Ruby 1.9.2 compatible (Matt Aimonetti)
|
|
11
|
+
* Added a property? method for property cast as :boolean (John Wood)
|
|
12
|
+
* Added an option to force the deletion of a attachments (bypass 409s) (Matt Aimonetti)
|
|
13
|
+
* Created a new abstraction layer for the REST API (Matt Aimonetti)
|
|
14
|
+
* Bug fix: made ExtendedDocument#all compatible with Couch 0.10 (tc)
|
|
15
|
+
|
|
16
|
+
== 0.32
|
|
17
|
+
|
|
10
18
|
* Major enhancements
|
|
11
19
|
|
|
12
|
-
*
|
|
20
|
+
* ExtendedDocument.get doesn't raise an exception anymore. If no documents are found nil is returned.
|
|
21
|
+
* ExtendedDocument.get! works the say #get used to work and will raise an exception if a document isn't found.
|
|
13
22
|
|
|
14
23
|
* Minor enhancements
|
|
15
|
-
|
|
24
|
+
|
|
25
|
+
* Bug fix: Model.all(:keys => [1,2]) was not working (Matt Aimonetti)
|
|
26
|
+
* Added ValidationErrors#count in order to play nicely with Rails (Peter Wagenet)
|
|
27
|
+
* Bug fix: class proxy design doc refresh (Daniel Kirsh)
|
|
28
|
+
* Bug fix: the count method on the proxy collection was missing (Daniel Kirsch)
|
|
16
29
|
* Added #amount_pages to a paginated collection. (Matt Aimonetti)
|
|
17
30
|
|
|
18
31
|
== 0.31
|
|
@@ -47,4 +60,4 @@ you will need to make the following modifications.
|
|
|
47
60
|
---
|
|
48
61
|
|
|
49
62
|
Unfortunately, before 0.30 we did not keep a track of the modifications made to CouchRest.
|
|
50
|
-
You can see the full commit history on GitHub: http://github.com/
|
|
63
|
+
You can see the full commit history on GitHub: http://github.com/couchrest/couchrest/commits/master/
|
|
@@ -113,10 +113,21 @@ module CouchRest
|
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
# DELETE an attachment directly from CouchDB
|
|
116
|
-
def delete_attachment
|
|
116
|
+
def delete_attachment(doc, name, force=false)
|
|
117
117
|
uri = url_for_attachment(doc, name)
|
|
118
118
|
# this needs a rev
|
|
119
|
-
|
|
119
|
+
begin
|
|
120
|
+
JSON.parse(HttpAbstraction.delete(uri))
|
|
121
|
+
rescue Exception => error
|
|
122
|
+
if force
|
|
123
|
+
# get over a 409
|
|
124
|
+
doc = get(doc['_id'])
|
|
125
|
+
uri = url_for_attachment(doc, name)
|
|
126
|
+
JSON.parse(HttpAbstraction.delete(uri))
|
|
127
|
+
else
|
|
128
|
+
error
|
|
129
|
+
end
|
|
130
|
+
end
|
|
120
131
|
end
|
|
121
132
|
|
|
122
133
|
# Save a document to CouchDB. This will use the <tt>_id</tt> field from
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module RestAPI
|
|
2
|
+
|
|
3
|
+
def put(uri, doc = nil)
|
|
4
|
+
payload = doc.to_json if doc
|
|
5
|
+
begin
|
|
6
|
+
JSON.parse(HttpAbstraction.put(uri, payload))
|
|
7
|
+
rescue Exception => e
|
|
8
|
+
if $DEBUG
|
|
9
|
+
raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
|
|
10
|
+
else
|
|
11
|
+
raise e
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def get(uri)
|
|
17
|
+
begin
|
|
18
|
+
JSON.parse(HttpAbstraction.get(uri), :max_nesting => false)
|
|
19
|
+
rescue => e
|
|
20
|
+
if $DEBUG
|
|
21
|
+
raise "Error while sending a GET request #{uri}\n: #{e}"
|
|
22
|
+
else
|
|
23
|
+
raise e
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def post(uri, doc = nil)
|
|
29
|
+
payload = doc.to_json if doc
|
|
30
|
+
begin
|
|
31
|
+
JSON.parse(HttpAbstraction.post(uri, payload))
|
|
32
|
+
rescue Exception => e
|
|
33
|
+
if $DEBUG
|
|
34
|
+
raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
|
|
35
|
+
else
|
|
36
|
+
raise e
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def delete(uri)
|
|
42
|
+
JSON.parse(HttpAbstraction.delete(uri))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def copy(uri, destination)
|
|
46
|
+
JSON.parse(HttpAbstraction.copy(uri, {'Destination' => destination}))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
####################################
|
|
2
|
+
# USAGE
|
|
3
|
+
#
|
|
4
|
+
# in your rack.rb file
|
|
5
|
+
# require this file and then:
|
|
6
|
+
#
|
|
7
|
+
# couch = CouchRest.new
|
|
8
|
+
# LOG_DB = couch.database!('couchrest-logger')
|
|
9
|
+
# use CouchRest::Logger, LOG_DB
|
|
10
|
+
#
|
|
11
|
+
# Note:
|
|
12
|
+
# to require just this middleware, if you have the gem installed do:
|
|
13
|
+
# require 'couchrest/middlewares/logger'
|
|
14
|
+
#
|
|
15
|
+
# For log processing examples, see examples at the bottom of this file
|
|
16
|
+
|
|
17
|
+
module CouchRest
|
|
18
|
+
class Logger
|
|
19
|
+
|
|
20
|
+
def self.log
|
|
21
|
+
Thread.current["couchrest.logger"] ||= {:queries => []}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def initialize(app, db=nil)
|
|
25
|
+
@app = app
|
|
26
|
+
@db = db
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.record(log_info)
|
|
30
|
+
log[:queries] << log_info
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def log
|
|
34
|
+
Thread.current["couchrest.logger"] ||= {:queries => []}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def reset_log
|
|
38
|
+
Thread.current["couchrest.logger"] = nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def call(env)
|
|
42
|
+
reset_log
|
|
43
|
+
log['started_at'] = Time.now
|
|
44
|
+
log['env'] = env
|
|
45
|
+
log['url'] = 'http://' + env['HTTP_HOST'] + env['REQUEST_URI']
|
|
46
|
+
response = @app.call(env)
|
|
47
|
+
log['ended_at'] = Time.now
|
|
48
|
+
log['duration'] = log['ended_at'] - log['started_at']
|
|
49
|
+
# let's report the log in a different thread so we don't slow down the app
|
|
50
|
+
@db ? Thread.new(@db, log){|db, rlog| db.save_doc(rlog);} : p(log.inspect)
|
|
51
|
+
response
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# inject our logger into CouchRest HTTP abstraction layer
|
|
57
|
+
module HttpAbstraction
|
|
58
|
+
|
|
59
|
+
def self.get(uri, headers=nil)
|
|
60
|
+
start_query = Time.now
|
|
61
|
+
log = {:method => :get, :uri => uri, :headers => headers}
|
|
62
|
+
response = super(uri, headers=nil)
|
|
63
|
+
end_query = Time.now
|
|
64
|
+
log[:duration] = (end_query - start_query)
|
|
65
|
+
CouchRest::Logger.record(log)
|
|
66
|
+
response
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.post(uri, payload, headers=nil)
|
|
70
|
+
start_query = Time.now
|
|
71
|
+
log = {:method => :post, :uri => uri, :payload => (payload ? (JSON.load(payload) rescue 'parsing error') : nil), :headers => headers}
|
|
72
|
+
response = super(uri, payload, headers=nil)
|
|
73
|
+
end_query = Time.now
|
|
74
|
+
log[:duration] = (end_query - start_query)
|
|
75
|
+
CouchRest::Logger.record(log)
|
|
76
|
+
response
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.put(uri, payload, headers=nil)
|
|
80
|
+
start_query = Time.now
|
|
81
|
+
log = {:method => :put, :uri => uri, :payload => (payload ? (JSON.load(payload) rescue 'parsing error') : nil), :headers => headers}
|
|
82
|
+
response = super(uri, payload, headers=nil)
|
|
83
|
+
end_query = Time.now
|
|
84
|
+
log[:duration] = (end_query - start_query)
|
|
85
|
+
CouchRest::Logger.record(log)
|
|
86
|
+
response
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.delete(uri, headers=nil)
|
|
90
|
+
start_query = Time.now
|
|
91
|
+
log = {:method => :delete, :uri => uri, :headers => headers}
|
|
92
|
+
response = super(uri, headers=nil)
|
|
93
|
+
end_query = Time.now
|
|
94
|
+
log[:duration] = (end_query - start_query)
|
|
95
|
+
CouchRest::Logger.record(log)
|
|
96
|
+
response
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# Advanced usage example
|
|
103
|
+
#
|
|
104
|
+
#
|
|
105
|
+
# # DB VIEWS
|
|
106
|
+
# by_url = {
|
|
107
|
+
# :map =>
|
|
108
|
+
# "function(doc) {
|
|
109
|
+
# if(doc['url']){ emit(doc['url'], 1) };
|
|
110
|
+
# }",
|
|
111
|
+
# :reduce =>
|
|
112
|
+
# 'function (key, values, rereduce) {
|
|
113
|
+
# return(sum(values));
|
|
114
|
+
# };'
|
|
115
|
+
# }
|
|
116
|
+
# req_duration = {
|
|
117
|
+
# :map =>
|
|
118
|
+
# "function(doc) {
|
|
119
|
+
# if(doc['duration']){ emit(doc['url'], doc['duration']) };
|
|
120
|
+
# }",
|
|
121
|
+
# :reduce =>
|
|
122
|
+
# 'function (key, values, rereduce) {
|
|
123
|
+
# return(sum(values)/values.length);
|
|
124
|
+
# };'
|
|
125
|
+
# }
|
|
126
|
+
#
|
|
127
|
+
# query_duration = {
|
|
128
|
+
# :map =>
|
|
129
|
+
# "function(doc) {
|
|
130
|
+
# if(doc['queries']){
|
|
131
|
+
# doc.queries.forEach(function(query){
|
|
132
|
+
# if(query['duration'] && query['method']){
|
|
133
|
+
# emit(query['method'], query['duration'])
|
|
134
|
+
# }
|
|
135
|
+
# });
|
|
136
|
+
# };
|
|
137
|
+
# }" ,
|
|
138
|
+
# :reduce =>
|
|
139
|
+
# 'function (key, values, rereduce) {
|
|
140
|
+
# return(sum(values)/values.length);
|
|
141
|
+
# };'
|
|
142
|
+
# }
|
|
143
|
+
#
|
|
144
|
+
# action_queries = {
|
|
145
|
+
# :map =>
|
|
146
|
+
# "function(doc) {
|
|
147
|
+
# if(doc['queries']){
|
|
148
|
+
# emit(doc['url'], doc['queries'].length)
|
|
149
|
+
# };
|
|
150
|
+
# }",
|
|
151
|
+
# :reduce =>
|
|
152
|
+
# 'function (key, values, rereduce) {
|
|
153
|
+
# return(sum(values)/values.length);
|
|
154
|
+
# };'
|
|
155
|
+
# }
|
|
156
|
+
#
|
|
157
|
+
# action_time_spent_in_db = {
|
|
158
|
+
# :map =>
|
|
159
|
+
# "function(doc) {
|
|
160
|
+
# if(doc['queries']){
|
|
161
|
+
# var totalDuration = 0;
|
|
162
|
+
# doc.queries.forEach(function(query){
|
|
163
|
+
# totalDuration += query['duration']
|
|
164
|
+
# })
|
|
165
|
+
# emit(doc['url'], totalDuration)
|
|
166
|
+
# };
|
|
167
|
+
# }",
|
|
168
|
+
# :reduce =>
|
|
169
|
+
# 'function (key, values, rereduce) {
|
|
170
|
+
# return(sum(values)/values.length);
|
|
171
|
+
# };'
|
|
172
|
+
# }
|
|
173
|
+
#
|
|
174
|
+
# show_queries = %Q~function(doc, req) {
|
|
175
|
+
# var body = ""
|
|
176
|
+
# body += "<h1>" + doc['url'] + "</h1>"
|
|
177
|
+
# body += "<h2>Request duration in seconds: " + doc['duration'] + "</h2>"
|
|
178
|
+
# body += "<h3>" + doc['queries'].length + " queries</h3><ul>"
|
|
179
|
+
# if (doc.queries){
|
|
180
|
+
# doc.queries.forEach(function(query){
|
|
181
|
+
# body += "<li>"+ query['uri'] +"</li>"
|
|
182
|
+
# });
|
|
183
|
+
# };
|
|
184
|
+
# body += "</ul>"
|
|
185
|
+
# if(doc){ return { body: body} }
|
|
186
|
+
# }~
|
|
187
|
+
#
|
|
188
|
+
#
|
|
189
|
+
# couch = CouchRest.new
|
|
190
|
+
# LOG_DB = couch.database!('couchrest-logger')
|
|
191
|
+
# design_doc = LOG_DB.get("_design/stats") rescue nil
|
|
192
|
+
# LOG_DB.delete_doc design_doc rescue nil
|
|
193
|
+
# LOG_DB.save_doc({
|
|
194
|
+
# "_id" => "_design/stats",
|
|
195
|
+
# :views => {
|
|
196
|
+
# :by_url => by_url,
|
|
197
|
+
# :request_duration => req_duration,
|
|
198
|
+
# :query_duration => query_duration,
|
|
199
|
+
# :action_queries => action_queries,
|
|
200
|
+
# :action_time_spent_in_db => action_time_spent_in_db
|
|
201
|
+
# },
|
|
202
|
+
# :shows => {
|
|
203
|
+
# :queries => show_queries
|
|
204
|
+
# }
|
|
205
|
+
# })
|
|
206
|
+
#
|
|
207
|
+
# module CouchRest
|
|
208
|
+
# class Logger
|
|
209
|
+
#
|
|
210
|
+
# def self.roundup(value)
|
|
211
|
+
# begin
|
|
212
|
+
# value = Float(value)
|
|
213
|
+
# (value * 100).round.to_f / 100
|
|
214
|
+
# rescue
|
|
215
|
+
# value
|
|
216
|
+
# end
|
|
217
|
+
# end
|
|
218
|
+
#
|
|
219
|
+
# # Usage example:
|
|
220
|
+
# # CouchRest::Logger.average_request_duration(LOG_DB)['rows'].first['value']
|
|
221
|
+
# def self.average_request_duration(db)
|
|
222
|
+
# raw = db.view('stats/request_duration', :reduce => true)
|
|
223
|
+
# (raw.has_key?('rows') && !raw['rows'].empty?) ? roundup(raw['rows'].first['value']) : 'not available yet'
|
|
224
|
+
# end
|
|
225
|
+
#
|
|
226
|
+
# def self.average_query_duration(db)
|
|
227
|
+
# raw = db.view('stats/query_duration', :reduce => true)
|
|
228
|
+
# (raw.has_key?('rows') && !raw['rows'].empty?) ? roundup(raw['rows'].first['value']) : 'not available yet'
|
|
229
|
+
# end
|
|
230
|
+
#
|
|
231
|
+
# def self.average_get_query_duration(db)
|
|
232
|
+
# raw = db.view('stats/query_duration', :key => 'get', :reduce => true)
|
|
233
|
+
# (raw.has_key?('rows') && !raw['rows'].empty?) ? roundup(raw['rows'].first['value']) : 'not available yet'
|
|
234
|
+
# end
|
|
235
|
+
#
|
|
236
|
+
# def self.average_post_query_duration(db)
|
|
237
|
+
# raw = db.view('stats/query_duration', :key => 'post', :reduce => true)
|
|
238
|
+
# (raw.has_key?('rows') && !raw['rows'].empty?) ? roundup(raw['rows'].first['value']) : 'not available yet'
|
|
239
|
+
# end
|
|
240
|
+
#
|
|
241
|
+
# def self.average_queries_per_action(db)
|
|
242
|
+
# raw = db.view('stats/action_queries', :reduce => true)
|
|
243
|
+
# (raw.has_key?('rows') && !raw['rows'].empty?) ? roundup(raw['rows'].first['value']) : 'not available yet'
|
|
244
|
+
# end
|
|
245
|
+
#
|
|
246
|
+
# def self.average_db_time_per_action(db)
|
|
247
|
+
# raw = db.view('stats/action_time_spent_in_db', :reduce => true)
|
|
248
|
+
# (raw.has_key?('rows') && !raw['rows'].empty?) ? roundup(raw['rows'].first['value']) : 'not available yet'
|
|
249
|
+
# end
|
|
250
|
+
#
|
|
251
|
+
# def self.stats(db)
|
|
252
|
+
# Thread.new(db){|db|
|
|
253
|
+
# puts "=== STATS ===\n"
|
|
254
|
+
# puts "average request duration: #{average_request_duration(db)}\n"
|
|
255
|
+
# puts "average query duration: #{average_query_duration(db)}\n"
|
|
256
|
+
# puts "average queries per action : #{average_queries_per_action(db)}\n"
|
|
257
|
+
# puts "average time spent in DB (per action): #{average_db_time_per_action(db)}\n"
|
|
258
|
+
# puts "===============\n"
|
|
259
|
+
# }
|
|
260
|
+
# end
|
|
261
|
+
#
|
|
262
|
+
# end
|
|
263
|
+
# end
|
|
@@ -19,9 +19,9 @@ module CouchRest
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# deletes an attachment directly from couchdb
|
|
22
|
-
def delete_attachment(name)
|
|
22
|
+
def delete_attachment(name, force=false)
|
|
23
23
|
raise ArgumentError, "doc.database required to delete_attachment" unless database
|
|
24
|
-
result = database.delete_attachment(self, name)
|
|
24
|
+
result = database.delete_attachment(self, name, force)
|
|
25
25
|
self['_rev'] = result['rev']
|
|
26
26
|
result['ok']
|
|
27
27
|
end
|
|
@@ -59,6 +59,10 @@ module CouchRest
|
|
|
59
59
|
@klass.all({:database => @database}.merge(opts), &block)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
def count(opts = {}, &block)
|
|
63
|
+
@klass.all({:database => @database, :raw => true, :limit => 0}.merge(opts), &block)['total_rows']
|
|
64
|
+
end
|
|
65
|
+
|
|
62
66
|
def first(opts = {})
|
|
63
67
|
@klass.first({:database => @database}.merge(opts))
|
|
64
68
|
end
|
|
@@ -100,7 +104,7 @@ module CouchRest
|
|
|
100
104
|
end
|
|
101
105
|
|
|
102
106
|
def refresh_design_doc
|
|
103
|
-
@klass.
|
|
107
|
+
@klass.refresh_design_doc_on(@database)
|
|
104
108
|
end
|
|
105
109
|
|
|
106
110
|
def save_design_doc
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
module CouchRest
|
|
2
2
|
module Mixins
|
|
3
|
+
module PaginatedResults
|
|
4
|
+
def amount_pages
|
|
5
|
+
@amount_pages ||= 0
|
|
6
|
+
end
|
|
7
|
+
def amount_pages=(value)
|
|
8
|
+
@amount_pages = value
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
3
12
|
module Collection
|
|
4
13
|
|
|
5
14
|
def self.included(base)
|
|
@@ -115,7 +124,10 @@ module CouchRest
|
|
|
115
124
|
results = @database.view(@view_name, pagination_options(page, per_page))
|
|
116
125
|
@amount_pages ||= (results['total_rows'].to_f / per_page.to_f).ceil
|
|
117
126
|
remember_where_we_left_off(results, page)
|
|
118
|
-
convert_to_container_array(results)
|
|
127
|
+
results = convert_to_container_array(results)
|
|
128
|
+
results.extend(PaginatedResults)
|
|
129
|
+
results.amount_pages = @amount_pages
|
|
130
|
+
results
|
|
119
131
|
end
|
|
120
132
|
|
|
121
133
|
# See Collection.paginated_each
|
|
@@ -181,7 +193,7 @@ module CouchRest
|
|
|
181
193
|
@target.inspect
|
|
182
194
|
end
|
|
183
195
|
|
|
184
|
-
def convert_to_container_array(results)
|
|
196
|
+
def convert_to_container_array(results)
|
|
185
197
|
if @container_class.nil?
|
|
186
198
|
results
|
|
187
199
|
else
|
|
@@ -35,7 +35,7 @@ module CouchRest
|
|
|
35
35
|
'all' => {
|
|
36
36
|
'map' => "function(doc) {
|
|
37
37
|
if (doc['couchrest-type'] == '#{self.to_s}') {
|
|
38
|
-
emit(
|
|
38
|
+
emit(doc['_id'],1);
|
|
39
39
|
}
|
|
40
40
|
}"
|
|
41
41
|
}
|
|
@@ -48,6 +48,11 @@ module CouchRest
|
|
|
48
48
|
save_design_doc
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
+
def refresh_design_doc_on(db)
|
|
52
|
+
reset_design_doc
|
|
53
|
+
save_design_doc_on(db)
|
|
54
|
+
end
|
|
55
|
+
|
|
51
56
|
# Save the design doc onto the default database, and update the
|
|
52
57
|
# design_doc attribute
|
|
53
58
|
def save_design_doc
|
|
@@ -12,7 +12,7 @@ module CouchRest
|
|
|
12
12
|
# name of the current class. Take the standard set of
|
|
13
13
|
# CouchRest::Database#view options.
|
|
14
14
|
def all(opts = {}, &block)
|
|
15
|
-
view(:all,
|
|
15
|
+
view(:all, opts, &block)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# Returns the number of documents that have the "couchrest-type" field
|
|
@@ -39,7 +39,38 @@ module CouchRest
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
# Load a document from the database by id
|
|
42
|
+
# No exceptions will be raised if the document isn't found
|
|
43
|
+
#
|
|
44
|
+
# ==== Returns
|
|
45
|
+
# Object:: if the document was found
|
|
46
|
+
# or
|
|
47
|
+
# Nil::
|
|
48
|
+
#
|
|
49
|
+
# === Parameters
|
|
50
|
+
# id<String, Integer>:: Document ID
|
|
51
|
+
# db<Database>:: optional option to pass a custom database to use
|
|
42
52
|
def get(id, db = database)
|
|
53
|
+
begin
|
|
54
|
+
doc = db.get id
|
|
55
|
+
rescue
|
|
56
|
+
nil
|
|
57
|
+
else
|
|
58
|
+
new(doc)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Load a document from the database by id
|
|
63
|
+
# An exception will be raised if the document isn't found
|
|
64
|
+
#
|
|
65
|
+
# ==== Returns
|
|
66
|
+
# Object:: if the document was found
|
|
67
|
+
# or
|
|
68
|
+
# Exception
|
|
69
|
+
#
|
|
70
|
+
# === Parameters
|
|
71
|
+
# id<String, Integer>:: Document ID
|
|
72
|
+
# db<Database>:: optional option to pass a custom database to use
|
|
73
|
+
def get!(id, db = database)
|
|
43
74
|
doc = db.get id
|
|
44
75
|
new(doc)
|
|
45
76
|
end
|
|
@@ -65,9 +65,8 @@ module CouchRest
|
|
|
65
65
|
key = self.has_key?(property.name) ? property.name : property.name.to_sym
|
|
66
66
|
# Don't cast the property unless it has a value
|
|
67
67
|
return unless self[key]
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
klass = ::CouchRest.constantize(target[0])
|
|
68
|
+
if property.type.is_a?(Array)
|
|
69
|
+
klass = ::CouchRest.constantize(property.type[0])
|
|
71
70
|
arr = self[key].dup.collect do |value|
|
|
72
71
|
unless value.instance_of?(klass)
|
|
73
72
|
value = convert_property_value(property, klass, value)
|
|
@@ -78,7 +77,12 @@ module CouchRest
|
|
|
78
77
|
self[key] = klass != String ? CastedArray.new(arr) : arr
|
|
79
78
|
self[key].casted_by = self if self[key].respond_to?(:casted_by)
|
|
80
79
|
else
|
|
81
|
-
|
|
80
|
+
if property.type == 'boolean'
|
|
81
|
+
klass = TrueClass
|
|
82
|
+
else
|
|
83
|
+
klass = ::CouchRest.constantize(property.type)
|
|
84
|
+
end
|
|
85
|
+
|
|
82
86
|
unless self[key].instance_of?(klass)
|
|
83
87
|
self[key] = convert_property_value(property, klass, self[property.name])
|
|
84
88
|
end
|
|
@@ -93,12 +97,15 @@ module CouchRest
|
|
|
93
97
|
end
|
|
94
98
|
|
|
95
99
|
def convert_property_value(property, klass, value)
|
|
96
|
-
if ((property.init_method == 'new') && klass
|
|
100
|
+
if ((property.init_method == 'new') && klass == Time)
|
|
97
101
|
# Using custom time parsing method because Ruby's default method is toooo slow
|
|
98
102
|
value.is_a?(String) ? Time.mktime_with_offset(value.dup) : value
|
|
99
103
|
# Float instances don't get initialized with #new
|
|
100
|
-
elsif ((property.init_method == 'new') && klass
|
|
104
|
+
elsif ((property.init_method == 'new') && klass == Float)
|
|
101
105
|
cast_float(value)
|
|
106
|
+
# 'boolean' type is simply used to generate a property? accessor method
|
|
107
|
+
elsif ((property.init_method == 'new') && klass == TrueClass)
|
|
108
|
+
value
|
|
102
109
|
else
|
|
103
110
|
klass.send(property.init_method, value.dup)
|
|
104
111
|
end
|
|
@@ -150,6 +157,18 @@ module CouchRest
|
|
|
150
157
|
end
|
|
151
158
|
EOS
|
|
152
159
|
|
|
160
|
+
if property.type == 'boolean'
|
|
161
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
|
162
|
+
def #{property.name}?
|
|
163
|
+
if self['#{property.name}'].nil? || self['#{property.name}'] == false || self['#{property.name}'].to_s.downcase == 'false'
|
|
164
|
+
false
|
|
165
|
+
else
|
|
166
|
+
true
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
EOS
|
|
170
|
+
end
|
|
171
|
+
|
|
153
172
|
if property.alias
|
|
154
173
|
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
|
155
174
|
alias #{property.alias.to_sym} #{property.name.to_sym}
|
|
@@ -95,11 +95,11 @@ module CouchRest
|
|
|
95
95
|
|
|
96
96
|
# Dispatches to any named view.
|
|
97
97
|
def view(name, query={}, &block)
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
db = query.delete(:database) || database
|
|
99
|
+
unless design_doc_fresh
|
|
100
|
+
refresh_design_doc_on(db)
|
|
100
101
|
end
|
|
101
102
|
query[:raw] = true if query[:reduce]
|
|
102
|
-
db = query.delete(:database) || database
|
|
103
103
|
raw = query.delete(:raw)
|
|
104
104
|
fetch_view_with_docs(db, name, query, raw, &block)
|
|
105
105
|
end
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
require File.
|
|
1
|
+
require File.expand_path('../../mixins/properties', __FILE__)
|
|
2
|
+
|
|
2
3
|
|
|
3
4
|
module CouchRest
|
|
4
5
|
module CastedModel
|
|
5
6
|
|
|
6
7
|
def self.included(base)
|
|
7
|
-
base.send(:include, CouchRest::Callbacks)
|
|
8
|
-
base.send(:include, CouchRest::Mixins::Properties)
|
|
8
|
+
base.send(:include, ::CouchRest::Callbacks)
|
|
9
|
+
base.send(:include, ::CouchRest::Mixins::Properties)
|
|
9
10
|
base.send(:attr_accessor, :casted_by)
|
|
10
11
|
base.send(:attr_accessor, :document_saved)
|
|
11
12
|
end
|
|
@@ -104,6 +104,13 @@ module CouchRest
|
|
|
104
104
|
entries.empty?
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
+
# Return size of errors hash
|
|
108
|
+
#
|
|
109
|
+
# Allows us to play nicely with Rails' helpers
|
|
110
|
+
def count
|
|
111
|
+
errors.size
|
|
112
|
+
end
|
|
113
|
+
|
|
107
114
|
def method_missing(meth, *args, &block)
|
|
108
115
|
errors.send(meth, *args, &block)
|
|
109
116
|
end
|
data/lib/couchrest.rb
CHANGED
|
@@ -28,7 +28,7 @@ require 'couchrest/monkeypatches'
|
|
|
28
28
|
|
|
29
29
|
# = CouchDB, close to the metal
|
|
30
30
|
module CouchRest
|
|
31
|
-
VERSION = '0.
|
|
31
|
+
VERSION = '0.33' unless self.const_defined?("VERSION")
|
|
32
32
|
|
|
33
33
|
autoload :Server, 'couchrest/core/server'
|
|
34
34
|
autoload :Database, 'couchrest/core/database'
|
|
@@ -45,9 +45,14 @@ module CouchRest
|
|
|
45
45
|
autoload :ExtendedDocument, 'couchrest/more/extended_document'
|
|
46
46
|
autoload :CastedModel, 'couchrest/more/casted_model'
|
|
47
47
|
|
|
48
|
+
require File.join(File.dirname(__FILE__), 'couchrest', 'core', 'rest_api')
|
|
48
49
|
require File.join(File.dirname(__FILE__), 'couchrest', 'core', 'http_abstraction')
|
|
49
50
|
require File.join(File.dirname(__FILE__), 'couchrest', 'mixins')
|
|
50
51
|
require File.join(File.dirname(__FILE__), 'couchrest', 'support', 'rails') if defined?(Rails)
|
|
52
|
+
|
|
53
|
+
# we extend CouchRest with the RestAPI module which gives us acess to
|
|
54
|
+
# the get, post, put, delete and copy
|
|
55
|
+
CouchRest.extend(::RestAPI)
|
|
51
56
|
|
|
52
57
|
# The CouchRest module methods handle the basic JSON serialization
|
|
53
58
|
# and deserialization, as well as query parameters. The module also includes
|
|
@@ -140,52 +145,6 @@ module CouchRest
|
|
|
140
145
|
cr.database(parsed[:database])
|
|
141
146
|
end
|
|
142
147
|
|
|
143
|
-
def put(uri, doc = nil)
|
|
144
|
-
payload = doc.to_json if doc
|
|
145
|
-
begin
|
|
146
|
-
JSON.parse(HttpAbstraction.put(uri, payload))
|
|
147
|
-
rescue Exception => e
|
|
148
|
-
if $DEBUG
|
|
149
|
-
raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
|
|
150
|
-
else
|
|
151
|
-
raise e
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def get(uri)
|
|
157
|
-
begin
|
|
158
|
-
JSON.parse(HttpAbstraction.get(uri), :max_nesting => false)
|
|
159
|
-
rescue => e
|
|
160
|
-
if $DEBUG
|
|
161
|
-
raise "Error while sending a GET request #{uri}\n: #{e}"
|
|
162
|
-
else
|
|
163
|
-
raise e
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def post uri, doc = nil
|
|
169
|
-
payload = doc.to_json if doc
|
|
170
|
-
begin
|
|
171
|
-
JSON.parse(HttpAbstraction.post(uri, payload))
|
|
172
|
-
rescue Exception => e
|
|
173
|
-
if $DEBUG
|
|
174
|
-
raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
|
|
175
|
-
else
|
|
176
|
-
raise e
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def delete uri
|
|
182
|
-
JSON.parse(HttpAbstraction.delete(uri))
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
def copy uri, destination
|
|
186
|
-
JSON.parse(HttpAbstraction.copy(uri, {'Destination' => destination}))
|
|
187
|
-
end
|
|
188
|
-
|
|
189
148
|
def paramify_url url, params = {}
|
|
190
149
|
if params && !params.empty?
|
|
191
150
|
query = params.collect do |k,v|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.
|
|
1
|
+
require File.expand_path("../../../spec_helper", __FILE__)
|
|
2
2
|
|
|
3
3
|
describe CouchRest::Database do
|
|
4
4
|
before(:each) do
|
|
@@ -263,7 +263,11 @@ describe CouchRest::Database do
|
|
|
263
263
|
r['ok'].should == true
|
|
264
264
|
doc = @db.get("attach-this")
|
|
265
265
|
attachment = @db.fetch_attachment(doc,"couchdb.png")
|
|
266
|
-
attachment.
|
|
266
|
+
if attachment.respond_to?(:net_http_res)
|
|
267
|
+
attachment.net_http_res.body.should == image
|
|
268
|
+
else
|
|
269
|
+
attachment.should == image
|
|
270
|
+
end
|
|
267
271
|
end
|
|
268
272
|
end
|
|
269
273
|
|
|
@@ -368,8 +372,18 @@ describe CouchRest::Database do
|
|
|
368
372
|
end
|
|
369
373
|
it "should delete the attachment" do
|
|
370
374
|
lambda { @db.fetch_attachment(@doc,'test.html') }.should_not raise_error
|
|
371
|
-
@db.delete_attachment(@doc, "test.html")
|
|
372
|
-
|
|
375
|
+
@db.delete_attachment(@doc, "test.html")
|
|
376
|
+
@doc = @db.get('mydocwithattachment') # avoid getting a 409
|
|
377
|
+
lambda{ @db.fetch_attachment(@doc,'test.html')}.should raise_error
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
it "should force a delete even if we get a 409" do
|
|
381
|
+
@doc['new_attribute'] = 'something new'
|
|
382
|
+
@db.put_attachment(@doc, 'test', File.open(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'attachments', 'test.html')).read)
|
|
383
|
+
# at this point the revision number changed, if we try to save doc one more time
|
|
384
|
+
# we would get a 409.
|
|
385
|
+
lambda{ @db.save_doc(@doc) }.should raise_error
|
|
386
|
+
lambda{ @db.delete_attachment(@doc, "test", true) }.should_not raise_error
|
|
373
387
|
end
|
|
374
388
|
end
|
|
375
389
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
-
require File.
|
|
3
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
4
4
|
require File.join(FIXTURE_PATH, 'more', 'card')
|
|
5
5
|
require File.join(FIXTURE_PATH, 'more', 'cat')
|
|
6
6
|
require File.join(FIXTURE_PATH, 'more', 'person')
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.
|
|
1
|
+
require File.expand_path("../../../spec_helper", __FILE__)
|
|
2
2
|
require File.join(FIXTURE_PATH, 'more', 'article')
|
|
3
3
|
require File.join(FIXTURE_PATH, 'more', 'course')
|
|
4
4
|
require File.join(FIXTURE_PATH, 'more', 'cat')
|
|
@@ -270,6 +270,15 @@ describe "ExtendedDocument" do
|
|
|
270
270
|
foundart = Article.get @art.id
|
|
271
271
|
foundart.title.should == "All About Getting"
|
|
272
272
|
end
|
|
273
|
+
|
|
274
|
+
it "should return nil if `get` is used and the document doesn't exist" do
|
|
275
|
+
foundart = Article.get 'matt aimonetti'
|
|
276
|
+
foundart.should be_nil
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "should raise an error if `get!` is used and the document doesn't exist" do
|
|
280
|
+
lambda{foundart = Article.get!('matt aimonetti')}.should raise_error
|
|
281
|
+
end
|
|
273
282
|
end
|
|
274
283
|
|
|
275
284
|
describe "getting a model with a subobjects array" do
|
|
@@ -561,7 +570,7 @@ describe "ExtendedDocument" do
|
|
|
561
570
|
end
|
|
562
571
|
it "should make it go away" do
|
|
563
572
|
@dobj.destroy
|
|
564
|
-
lambda{Basic.get(@dobj.id)}.should raise_error
|
|
573
|
+
lambda{Basic.get!(@dobj.id)}.should raise_error
|
|
565
574
|
end
|
|
566
575
|
end
|
|
567
576
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.
|
|
1
|
+
require File.expand_path("../../../spec_helper", __FILE__)
|
|
2
2
|
require File.join(FIXTURE_PATH, 'more', 'article')
|
|
3
3
|
require File.join(FIXTURE_PATH, 'more', 'course')
|
|
4
4
|
|
|
@@ -168,8 +168,11 @@ describe "ExtendedDocument views" do
|
|
|
168
168
|
end
|
|
169
169
|
things[0]["doc"]["title"].should =='aaa'
|
|
170
170
|
end
|
|
171
|
-
it "should
|
|
172
|
-
|
|
171
|
+
it "should return nil on get if no database given" do
|
|
172
|
+
Unattached.get("aaa").should be_nil
|
|
173
|
+
end
|
|
174
|
+
it "should barf on get! if no database given" do
|
|
175
|
+
lambda{Unattached.get!("aaa")}.should raise_error
|
|
173
176
|
end
|
|
174
177
|
it "should get from specific database" do
|
|
175
178
|
u = Unattached.get(@first_id, @db)
|
|
@@ -200,7 +203,7 @@ describe "ExtendedDocument views" do
|
|
|
200
203
|
before(:all) do
|
|
201
204
|
reset_test_db!
|
|
202
205
|
# setup the class default doc to save the design doc
|
|
203
|
-
Unattached.use_database
|
|
206
|
+
Unattached.use_database nil # just to be sure it is really unattached
|
|
204
207
|
@us = Unattached.on(DB)
|
|
205
208
|
%w{aaa bbb ddd eee}.each do |title|
|
|
206
209
|
u = @us.new(:title => title)
|
|
@@ -212,6 +215,9 @@ describe "ExtendedDocument views" do
|
|
|
212
215
|
rs = @us.all
|
|
213
216
|
rs.length.should == 4
|
|
214
217
|
end
|
|
218
|
+
it "should count" do
|
|
219
|
+
@us.count.should == 4
|
|
220
|
+
end
|
|
215
221
|
it "should make the design doc upon first query" do
|
|
216
222
|
@us.by_title
|
|
217
223
|
doc = @us.design_doc
|
|
@@ -348,7 +354,8 @@ describe "ExtendedDocument views" do
|
|
|
348
354
|
a = Article.new(:title => title, :date => Date.today)
|
|
349
355
|
a.save
|
|
350
356
|
end
|
|
351
|
-
end
|
|
357
|
+
end
|
|
358
|
+
require 'date'
|
|
352
359
|
it "should return a proxy that looks like an array of 7 Article objects" do
|
|
353
360
|
articles = Article.by_date :key => Date.today
|
|
354
361
|
articles.class.should == Array
|
|
@@ -368,8 +375,7 @@ describe "ExtendedDocument views" do
|
|
|
368
375
|
end
|
|
369
376
|
it "should have the amount of paginated pages" do
|
|
370
377
|
articles = Article.by_date :key => Date.today
|
|
371
|
-
articles.paginate(:per_page => 3)
|
|
372
|
-
articles.amount_pages.should == 3
|
|
378
|
+
articles.paginate(:per_page => 3).amount_pages.should == 3
|
|
373
379
|
end
|
|
374
380
|
it "should provide a class method to access the collection directly" do
|
|
375
381
|
articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
2
|
require File.join(FIXTURE_PATH, 'more', 'person')
|
|
3
3
|
require File.join(FIXTURE_PATH, 'more', 'card')
|
|
4
4
|
require File.join(FIXTURE_PATH, 'more', 'invoice')
|
|
@@ -164,6 +164,33 @@ describe "ExtendedDocument properties" do
|
|
|
164
164
|
end
|
|
165
165
|
end
|
|
166
166
|
|
|
167
|
+
describe "casting to a boolean value" do
|
|
168
|
+
class RootBeerFloat < CouchRest::ExtendedDocument
|
|
169
|
+
use_database DB
|
|
170
|
+
property :tasty, :cast_as => :boolean
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it "should add an accessor with a '?' for boolean attributes that returns true or false" do
|
|
174
|
+
RootBeerFloat.new(:tasty => true).tasty?.should == true
|
|
175
|
+
RootBeerFloat.new(:tasty => 'you bet').tasty?.should == true
|
|
176
|
+
RootBeerFloat.new(:tasty => 123).tasty?.should == true
|
|
177
|
+
|
|
178
|
+
RootBeerFloat.new(:tasty => false).tasty?.should == false
|
|
179
|
+
RootBeerFloat.new(:tasty => 'false').tasty?.should == false
|
|
180
|
+
RootBeerFloat.new(:tasty => 'FaLsE').tasty?.should == false
|
|
181
|
+
RootBeerFloat.new(:tasty => nil).tasty?.should == false
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should return the real value when the default accessor is used" do
|
|
185
|
+
RootBeerFloat.new(:tasty => true).tasty.should == true
|
|
186
|
+
RootBeerFloat.new(:tasty => 'you bet').tasty.should == 'you bet'
|
|
187
|
+
RootBeerFloat.new(:tasty => 123).tasty.should == 123
|
|
188
|
+
RootBeerFloat.new(:tasty => 'false').tasty.should == 'false'
|
|
189
|
+
RootBeerFloat.new(:tasty => false).tasty.should == false
|
|
190
|
+
RootBeerFloat.new(:tasty => nil).tasty.should == nil
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
167
194
|
end
|
|
168
195
|
end
|
|
169
196
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sporkd-couchrest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: "0.
|
|
4
|
+
version: "0.33"
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- J. Chris Anderson
|
|
@@ -78,12 +78,15 @@ files:
|
|
|
78
78
|
- lib/couchrest/core/document.rb
|
|
79
79
|
- lib/couchrest/core/http_abstraction.rb
|
|
80
80
|
- lib/couchrest/core/response.rb
|
|
81
|
+
- lib/couchrest/core/rest_api.rb
|
|
81
82
|
- lib/couchrest/core/server.rb
|
|
82
83
|
- lib/couchrest/core/view.rb
|
|
83
84
|
- lib/couchrest/helper
|
|
84
85
|
- lib/couchrest/helper/pager.rb
|
|
85
86
|
- lib/couchrest/helper/streamer.rb
|
|
86
87
|
- lib/couchrest/helper/upgrade.rb
|
|
88
|
+
- lib/couchrest/middlewares
|
|
89
|
+
- lib/couchrest/middlewares/logger.rb
|
|
87
90
|
- lib/couchrest/mixins
|
|
88
91
|
- lib/couchrest/mixins/attachments.rb
|
|
89
92
|
- lib/couchrest/mixins/callbacks.rb
|
|
@@ -169,6 +172,7 @@ files:
|
|
|
169
172
|
- utils/subset.rb
|
|
170
173
|
has_rdoc: false
|
|
171
174
|
homepage: http://github.com/jchris/couchrest
|
|
175
|
+
licenses:
|
|
172
176
|
post_install_message:
|
|
173
177
|
rdoc_options: []
|
|
174
178
|
|
|
@@ -189,7 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
189
193
|
requirements: []
|
|
190
194
|
|
|
191
195
|
rubyforge_project:
|
|
192
|
-
rubygems_version: 1.
|
|
196
|
+
rubygems_version: 1.3.5
|
|
193
197
|
signing_key:
|
|
194
198
|
specification_version: 3
|
|
195
199
|
summary: Lean and RESTful interface to CouchDB.
|