couchrest 0.32 → 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 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 mattetti-couchrest
20
+ $ sudo gem install couchrest-couchrest
21
21
 
22
22
  ### Relax, it's RESTful
23
23
 
data/history.txt CHANGED
@@ -1,3 +1,18 @@
1
+ == 0.33
2
+
3
+ * Major enhancements
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
+
1
16
  == 0.32
2
17
 
3
18
  * Major enhancements
@@ -45,4 +60,4 @@
45
60
  ---
46
61
 
47
62
  Unfortunately, before 0.30 we did not keep a track of the modifications made to CouchRest.
48
- You can see the full commit history on GitHub: http://github.com/mattetti/couchrest/commits/master/
63
+ You can see the full commit history on GitHub: http://github.com/couchrest/couchrest/commits/master/
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.32' unless self.const_defined?("VERSION")
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,8 +45,13 @@ 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')
51
+
52
+ # we extend CouchRest with the RestAPI module which gives us acess to
53
+ # the get, post, put, delete and copy
54
+ CouchRest.extend(::RestAPI)
50
55
 
51
56
  # The CouchRest module methods handle the basic JSON serialization
52
57
  # and deserialization, as well as query parameters. The module also includes
@@ -139,52 +144,6 @@ module CouchRest
139
144
  cr.database(parsed[:database])
140
145
  end
141
146
 
142
- def put(uri, doc = nil)
143
- payload = doc.to_json if doc
144
- begin
145
- JSON.parse(HttpAbstraction.put(uri, payload))
146
- rescue Exception => e
147
- if $DEBUG
148
- raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
149
- else
150
- raise e
151
- end
152
- end
153
- end
154
-
155
- def get(uri)
156
- begin
157
- JSON.parse(HttpAbstraction.get(uri), :max_nesting => false)
158
- rescue => e
159
- if $DEBUG
160
- raise "Error while sending a GET request #{uri}\n: #{e}"
161
- else
162
- raise e
163
- end
164
- end
165
- end
166
-
167
- def post uri, doc = nil
168
- payload = doc.to_json if doc
169
- begin
170
- JSON.parse(HttpAbstraction.post(uri, payload))
171
- rescue Exception => e
172
- if $DEBUG
173
- raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
174
- else
175
- raise e
176
- end
177
- end
178
- end
179
-
180
- def delete uri
181
- JSON.parse(HttpAbstraction.delete(uri))
182
- end
183
-
184
- def copy uri, destination
185
- JSON.parse(HttpAbstraction.copy(uri, {'Destination' => destination}))
186
- end
187
-
188
147
  def paramify_url url, params = {}
189
148
  if params && !params.empty?
190
149
  query = params.collect do |k,v|
@@ -113,10 +113,21 @@ module CouchRest
113
113
  end
114
114
 
115
115
  # DELETE an attachment directly from CouchDB
116
- def delete_attachment doc, name
116
+ def delete_attachment(doc, name, force=false)
117
117
  uri = url_for_attachment(doc, name)
118
118
  # this needs a rev
119
- JSON.parse(HttpAbstraction.delete(uri))
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
@@ -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
@@ -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, {:reduce => false}.merge(opts), &block)
15
+ view(:all, opts, &block)
16
16
  end
17
17
 
18
18
  # Returns the number of documents that have the "couchrest-type" field
@@ -77,6 +77,9 @@ module CouchRest
77
77
  # Float instances don't get initialized with #new
78
78
  elsif ((property.init_method == 'new') && target == 'Float')
79
79
  cast_float(self[key])
80
+ # 'boolean' type is simply used to generate a property? accessor method
81
+ elsif ((property.init_method == 'new') && target == 'boolean')
82
+ self[key]
80
83
  else
81
84
  # Let people use :send as a Time parse arg
82
85
  klass = ::CouchRest.constantize(target)
@@ -128,6 +131,18 @@ module CouchRest
128
131
  end
129
132
  EOS
130
133
 
134
+ if property.type == 'boolean'
135
+ class_eval <<-EOS, __FILE__, __LINE__
136
+ def #{property.name}?
137
+ if self['#{property.name}'].nil? || self['#{property.name}'] == false || self['#{property.name}'].to_s.downcase == 'false'
138
+ false
139
+ else
140
+ true
141
+ end
142
+ end
143
+ EOS
144
+ end
145
+
131
146
  if property.alias
132
147
  class_eval <<-EOS, __FILE__, __LINE__
133
148
  alias #{property.alias.to_sym} #{property.name.to_sym}
@@ -1,10 +1,11 @@
1
- require File.join(File.dirname(__FILE__), '..', 'mixins', 'properties')
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::Mixins::Properties)
8
+ base.send(:include, ::CouchRest::Mixins::Properties)
8
9
  base.send(:attr_accessor, :casted_by)
9
10
  end
10
11
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
2
 
3
3
  describe CouchRest do
4
4
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
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.should == image
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
- lambda { @db.fetch_attachment(@doc,'test.html') }.should raise_error(RestClient::ResourceNotFound)
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,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
2
 
3
3
  describe CouchRest::Design do
4
4
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
2
 
3
3
  class Video < CouchRest::Document; end
4
4
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
2
 
3
3
  describe CouchRest::Server do
4
4
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
2
 
3
3
  describe CouchRest::Pager do
4
4
  before(:all) do
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
2
 
3
3
  describe CouchRest::Streamer do
4
4
  before(:all) do
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
2
  require File.join(FIXTURE_PATH, 'more', 'card')
3
3
 
4
4
  class Car < CouchRest::ExtendedDocument
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
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.dirname(__FILE__) + '/../../spec_helper'
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
2
 
3
3
  describe "ExtendedDocument attachments" do
4
4
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
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
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
2
  require File.join(FIXTURE_PATH, 'more', 'card')
3
3
  require File.join(FIXTURE_PATH, 'more', 'course')
4
4
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
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
 
@@ -354,7 +354,8 @@ describe "ExtendedDocument views" do
354
354
  a = Article.new(:title => title, :date => Date.today)
355
355
  a.save
356
356
  end
357
- end
357
+ end
358
+ require 'date'
358
359
  it "should return a proxy that looks like an array of 7 Article objects" do
359
360
  articles = Article.by_date :key => Date.today
360
361
  articles.class.should == Array
@@ -374,8 +375,7 @@ describe "ExtendedDocument views" do
374
375
  end
375
376
  it "should have the amount of paginated pages" do
376
377
  articles = Article.by_date :key => Date.today
377
- articles.paginate(:per_page => 3)
378
- articles.amount_pages.should == 3
378
+ articles.paginate(:per_page => 3).amount_pages.should == 3
379
379
  end
380
380
  it "should provide a class method to access the collection directly" do
381
381
  articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
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')
@@ -161,9 +161,35 @@ describe "ExtendedDocument properties" do
161
161
  it "should work fine when a float is being passed" do
162
162
  RootBeerFloat.new(:price => 9.99).price.should == 9.99
163
163
  end
164
-
165
164
  end
166
165
 
166
+ describe "casting to a boolean value" do
167
+ class RootBeerFloat < CouchRest::ExtendedDocument
168
+ use_database DB
169
+ property :tasty, :cast_as => :boolean
170
+ end
171
+
172
+ it "should add an accessor with a '?' for boolean attributes that returns true or false" do
173
+ RootBeerFloat.new(:tasty => true).tasty?.should == true
174
+ RootBeerFloat.new(:tasty => 'you bet').tasty?.should == true
175
+ RootBeerFloat.new(:tasty => 123).tasty?.should == true
176
+
177
+ RootBeerFloat.new(:tasty => false).tasty?.should == false
178
+ RootBeerFloat.new(:tasty => 'false').tasty?.should == false
179
+ RootBeerFloat.new(:tasty => 'FaLsE').tasty?.should == false
180
+ RootBeerFloat.new(:tasty => nil).tasty?.should == false
181
+ end
182
+
183
+ it "should return the real value when the default accessor is used" do
184
+ RootBeerFloat.new(:tasty => true).tasty.should == true
185
+ RootBeerFloat.new(:tasty => 'you bet').tasty.should == 'you bet'
186
+ RootBeerFloat.new(:tasty => 123).tasty.should == 123
187
+ RootBeerFloat.new(:tasty => 'false').tasty.should == 'false'
188
+ RootBeerFloat.new(:tasty => false).tasty.should == false
189
+ RootBeerFloat.new(:tasty => nil).tasty.should == nil
190
+ end
191
+ end
192
+
167
193
  end
168
194
 
169
195
  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.32"
4
+ version: "0.33"
5
5
  platform: ruby
6
6
  authors:
7
7
  - J. Chris Anderson
@@ -68,11 +68,13 @@ files:
68
68
  - lib/couchrest/core/document.rb
69
69
  - lib/couchrest/core/http_abstraction.rb
70
70
  - lib/couchrest/core/response.rb
71
+ - lib/couchrest/core/rest_api.rb
71
72
  - lib/couchrest/core/server.rb
72
73
  - lib/couchrest/core/view.rb
73
74
  - lib/couchrest/helper/pager.rb
74
75
  - lib/couchrest/helper/streamer.rb
75
76
  - lib/couchrest/helper/upgrade.rb
77
+ - lib/couchrest/middlewares/logger.rb
76
78
  - lib/couchrest/mixins/attachments.rb
77
79
  - lib/couchrest/mixins/callbacks.rb
78
80
  - lib/couchrest/mixins/class_proxy.rb