couchrest 0.34 → 0.35
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/Rakefile +9 -0
- data/history.txt +23 -1
- data/lib/couchrest/core/adapters/restclient.rb +5 -5
- data/lib/couchrest/core/database.rb +28 -2
- data/lib/couchrest/mixins/class_proxy.rb +12 -4
- data/lib/couchrest/mixins/collection.rb +1 -1
- data/lib/couchrest/mixins/document_queries.rb +3 -5
- data/lib/couchrest/mixins/extended_attachments.rb +3 -7
- data/lib/couchrest/mixins/properties.rb +2 -2
- data/lib/couchrest/mixins/views.rb +3 -3
- data/lib/couchrest/more/extended_document.rb +23 -8
- data/lib/couchrest.rb +1 -1
- data/spec/couchrest/core/database_spec.rb +48 -1
- data/spec/couchrest/more/attribute_protection_spec.rb +56 -0
- data/spec/couchrest/more/casted_extended_doc_spec.rb +2 -2
- data/spec/couchrest/more/extended_doc_inherited_spec.rb +40 -0
- data/spec/couchrest/more/extended_doc_view_spec.rb +43 -20
- metadata +4 -2
data/Rakefile
CHANGED
@@ -56,3 +56,12 @@ end
|
|
56
56
|
|
57
57
|
desc "Run the rspec"
|
58
58
|
task :default => :spec
|
59
|
+
|
60
|
+
module Rake
|
61
|
+
def self.remove_task(task_name)
|
62
|
+
Rake.application.instance_variable_get('@tasks').delete(task_name.to_s)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
Rake.remove_task("github:release")
|
67
|
+
Rake.remove_task("release")
|
data/history.txt
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
== Next Version
|
2
|
+
|
3
|
+
* Major enhancements
|
4
|
+
|
5
|
+
* Minor enhancements
|
6
|
+
|
7
|
+
== 0.35
|
8
|
+
|
9
|
+
* Major enhancements
|
10
|
+
* CouchRest::ExtendedDocument allow chaining the inherit class callback (Kenneth Kalmer) - http://github.com/couchrest/couchrest/issues#issue/8
|
11
|
+
|
12
|
+
* Minor enhancements
|
13
|
+
* Fix attachment bug (Johannes Jörg Schmidt)
|
14
|
+
* Fix create database exception bug (Damien Mathieu)
|
15
|
+
* Compatible with restclient >= 1.4.0 new responses (Julien Kirch)
|
16
|
+
* Bug fix: Attribute protection no longer strips attributes coming from the database (Will Leinweber)
|
17
|
+
* Bug fix: Remove double CGI escape when PUTting an attachment (nzoschke)
|
18
|
+
* Bug fix: Changing Class proxy to set database on result sets (Peter Gumeson)
|
19
|
+
* Bug fix: Updated time regexp (Nolan Darilek)
|
20
|
+
* Added an update_doc method to database to handle conflicts during atomic updates. (Pierre Larochelle)
|
21
|
+
* Bug fix: http://github.com/couchrest/couchrest/issues/#issue/2 (Luke Burton)
|
22
|
+
|
1
23
|
== 0.34
|
2
24
|
|
3
25
|
* Major enhancements
|
@@ -85,4 +107,4 @@
|
|
85
107
|
---
|
86
108
|
|
87
109
|
Unfortunately, before 0.30 we did not keep a track of the modifications made to CouchRest.
|
88
|
-
You can see the full commit history on GitHub: http://github.com/couchrest/couchrest/commits/master/
|
110
|
+
You can see the full commit history on GitHub: http://github.com/couchrest/couchrest/commits/master/
|
@@ -10,25 +10,25 @@ module RestClientAdapter
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def get(uri, headers={})
|
13
|
-
RestClient.get(uri, headers)
|
13
|
+
RestClient.get(uri, headers).to_s
|
14
14
|
end
|
15
15
|
|
16
16
|
def post(uri, payload, headers={})
|
17
|
-
RestClient.post(uri, payload, headers)
|
17
|
+
RestClient.post(uri, payload, headers).to_s
|
18
18
|
end
|
19
19
|
|
20
20
|
def put(uri, payload, headers={})
|
21
|
-
RestClient.put(uri, payload, headers)
|
21
|
+
RestClient.put(uri, payload, headers).to_s
|
22
22
|
end
|
23
23
|
|
24
24
|
def delete(uri, headers={})
|
25
|
-
RestClient.delete(uri, headers)
|
25
|
+
RestClient.delete(uri, headers).to_s
|
26
26
|
end
|
27
27
|
|
28
28
|
def copy(uri, headers)
|
29
29
|
RestClient::Request.execute( :method => :copy,
|
30
30
|
:url => uri,
|
31
|
-
:headers => headers)
|
31
|
+
:headers => headers).to_s
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -107,7 +107,6 @@ module CouchRest
|
|
107
107
|
# PUT an attachment directly to CouchDB
|
108
108
|
def put_attachment(doc, name, file, options = {})
|
109
109
|
docid = escape_docid(doc['_id'])
|
110
|
-
name = CGI.escape(name)
|
111
110
|
uri = url_for_attachment(doc, name)
|
112
111
|
JSON.parse(HttpAbstraction.put(uri, file, options))
|
113
112
|
end
|
@@ -250,6 +249,33 @@ module CouchRest
|
|
250
249
|
CouchRest.copy "#{@root}/#{slug}", destination
|
251
250
|
end
|
252
251
|
|
252
|
+
# Updates the given doc by yielding the current state of the doc
|
253
|
+
# and trying to update update_limit times. Returns the new doc
|
254
|
+
# if the doc was successfully updated without hitting the limit
|
255
|
+
def update_doc(doc_id, params = {}, update_limit=10)
|
256
|
+
resp = {'ok' => false}
|
257
|
+
new_doc = nil
|
258
|
+
last_fail = nil
|
259
|
+
|
260
|
+
until resp['ok'] or update_limit <= 0
|
261
|
+
doc = self.get(doc_id, params) # grab the doc
|
262
|
+
new_doc = yield doc # give it to the caller to be updated
|
263
|
+
begin
|
264
|
+
resp = self.save_doc new_doc # try to PUT the updated doc into the db
|
265
|
+
rescue RestClient::RequestFailed => e
|
266
|
+
if e.http_code == 409 # Update collision
|
267
|
+
update_limit -= 1
|
268
|
+
last_fail = e
|
269
|
+
else # some other error
|
270
|
+
raise e
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
raise last_fail unless resp['ok']
|
276
|
+
new_doc
|
277
|
+
end
|
278
|
+
|
253
279
|
# Compact the database, removing old document revisions and optimizing space use.
|
254
280
|
def compact!
|
255
281
|
CouchRest.post "#{@root}/_compact"
|
@@ -265,7 +291,7 @@ module CouchRest
|
|
265
291
|
def recreate!
|
266
292
|
delete!
|
267
293
|
create!
|
268
|
-
rescue
|
294
|
+
rescue RestClient::ResourceNotFound
|
269
295
|
ensure
|
270
296
|
create!
|
271
297
|
end
|
@@ -56,7 +56,9 @@ module CouchRest
|
|
56
56
|
# Mixins::DocumentQueries
|
57
57
|
|
58
58
|
def all(opts = {}, &block)
|
59
|
-
@klass.all({:database => @database}.merge(opts), &block)
|
59
|
+
docs = @klass.all({:database => @database}.merge(opts), &block)
|
60
|
+
docs.each { |doc| doc.database = @database if doc.respond_to?(:database) } if docs
|
61
|
+
docs
|
60
62
|
end
|
61
63
|
|
62
64
|
def count(opts = {}, &block)
|
@@ -64,11 +66,15 @@ module CouchRest
|
|
64
66
|
end
|
65
67
|
|
66
68
|
def first(opts = {})
|
67
|
-
@klass.first({:database => @database}.merge(opts))
|
69
|
+
doc = @klass.first({:database => @database}.merge(opts))
|
70
|
+
doc.database = @database if doc && doc.respond_to?(:database)
|
71
|
+
doc
|
68
72
|
end
|
69
73
|
|
70
74
|
def get(id)
|
71
|
-
@klass.get(id, @database)
|
75
|
+
doc = @klass.get(id, @database)
|
76
|
+
doc.database = @database if doc && doc.respond_to?(:database)
|
77
|
+
doc
|
72
78
|
end
|
73
79
|
|
74
80
|
# Mixins::Views
|
@@ -78,7 +84,9 @@ module CouchRest
|
|
78
84
|
end
|
79
85
|
|
80
86
|
def view(name, query={}, &block)
|
81
|
-
@klass.view(name, {:database => @database}.merge(query), &block)
|
87
|
+
docs = @klass.view(name, {:database => @database}.merge(query), &block)
|
88
|
+
docs.each { |doc| doc.database = @database if doc.respond_to?(:database) } if docs
|
89
|
+
docs
|
82
90
|
end
|
83
91
|
|
84
92
|
def all_design_doc_versions
|
@@ -183,7 +183,7 @@ module CouchRest
|
|
183
183
|
if @container_class.nil?
|
184
184
|
results
|
185
185
|
else
|
186
|
-
results['rows'].collect { |row| @container_class.
|
186
|
+
results['rows'].collect { |row| @container_class.create_from_database(row['doc']) } unless results['rows'].nil?
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
@@ -51,11 +51,9 @@ module CouchRest
|
|
51
51
|
# db<Database>:: optional option to pass a custom database to use
|
52
52
|
def get(id, db = database)
|
53
53
|
begin
|
54
|
-
|
54
|
+
get!(id, db)
|
55
55
|
rescue
|
56
56
|
nil
|
57
|
-
else
|
58
|
-
new(doc)
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
@@ -72,11 +70,11 @@ module CouchRest
|
|
72
70
|
# db<Database>:: optional option to pass a custom database to use
|
73
71
|
def get!(id, db = database)
|
74
72
|
doc = db.get id
|
75
|
-
|
73
|
+
create_from_database(doc)
|
76
74
|
end
|
77
75
|
|
78
76
|
end
|
79
77
|
|
80
78
|
end
|
81
79
|
end
|
82
|
-
end
|
80
|
+
end
|
@@ -14,7 +14,7 @@ module CouchRest
|
|
14
14
|
|
15
15
|
# reads the data from an attachment
|
16
16
|
def read_attachment(attachment_name)
|
17
|
-
|
17
|
+
database.fetch_attachment(self, attachment_name)
|
18
18
|
end
|
19
19
|
|
20
20
|
# modifies a file attachment on the current doc
|
@@ -52,10 +52,6 @@ module CouchRest
|
|
52
52
|
|
53
53
|
private
|
54
54
|
|
55
|
-
def encode_attachment(data)
|
56
|
-
::Base64.encode64(data).gsub(/\r|\n/,'')
|
57
|
-
end
|
58
|
-
|
59
55
|
def get_mime_type(file)
|
60
56
|
::MIME::Types.type_for(file.path).empty? ?
|
61
57
|
'text\/plain' : MIME::Types.type_for(file.path).first.content_type.gsub(/\//,'\/')
|
@@ -65,10 +61,10 @@ module CouchRest
|
|
65
61
|
content_type = args[:content_type] ? args[:content_type] : get_mime_type(args[:file])
|
66
62
|
self['_attachments'][args[:name]] = {
|
67
63
|
'content_type' => content_type,
|
68
|
-
'data' =>
|
64
|
+
'data' => args[:file].read
|
69
65
|
}
|
70
66
|
end
|
71
67
|
|
72
68
|
end # module ExtendedAttachments
|
73
69
|
end
|
74
|
-
end
|
70
|
+
end
|
@@ -4,7 +4,7 @@ require File.join(File.dirname(__FILE__), '..', 'more', 'property')
|
|
4
4
|
class Time
|
5
5
|
# returns a local time value much faster than Time.parse
|
6
6
|
def self.mktime_with_offset(string)
|
7
|
-
string =~ /(\d{4})
|
7
|
+
string =~ /(\d{4})[\-|\/](\d{2})[\-|\/](\d{2})[T|\s](\d{2}):(\d{2}):(\d{2})([\+|\s|\-])*(\d{2}):?(\d{2})/
|
8
8
|
# $1 = year
|
9
9
|
# $2 = month
|
10
10
|
# $3 = day
|
@@ -197,4 +197,4 @@ module CouchRest
|
|
197
197
|
|
198
198
|
end
|
199
199
|
end
|
200
|
-
end
|
200
|
+
end
|
@@ -137,13 +137,13 @@ module CouchRest
|
|
137
137
|
collection_proxy_for(design_doc, name, opts.merge({:include_docs => true}))
|
138
138
|
else
|
139
139
|
view = fetch_view db, name, opts.merge({:include_docs => true}), &block
|
140
|
-
view['rows'].collect{|r|
|
140
|
+
view['rows'].collect{|r|create_from_database(r['doc'])} if view['rows']
|
141
141
|
end
|
142
142
|
rescue
|
143
143
|
# fallback for old versions of couchdb that don't
|
144
144
|
# have include_docs support
|
145
145
|
view = fetch_view(db, name, opts, &block)
|
146
|
-
view['rows'].collect{|r|
|
146
|
+
view['rows'].collect{|r|create_from_database(db.get(r['id']))} if view['rows']
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
@@ -170,4 +170,4 @@ module CouchRest
|
|
170
170
|
|
171
171
|
end
|
172
172
|
end
|
173
|
-
end
|
173
|
+
end
|
@@ -21,9 +21,11 @@ module CouchRest
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def self.inherited(subklass)
|
24
|
+
super
|
24
25
|
subklass.send(:include, CouchRest::Mixins::Properties)
|
25
26
|
subklass.class_eval <<-EOS, __FILE__, __LINE__ + 1
|
26
27
|
def self.inherited(subklass)
|
28
|
+
super
|
27
29
|
subklass.properties = self.properties.dup
|
28
30
|
end
|
29
31
|
EOS
|
@@ -38,11 +40,20 @@ module CouchRest
|
|
38
40
|
define_callbacks :save, "result == :halt"
|
39
41
|
define_callbacks :update, "result == :halt"
|
40
42
|
define_callbacks :destroy, "result == :halt"
|
43
|
+
|
44
|
+
# Creates a new instance, bypassing attribute protection
|
45
|
+
#
|
46
|
+
# ==== Returns
|
47
|
+
# a document instance
|
48
|
+
def self.create_from_database(passed_keys={})
|
49
|
+
new(passed_keys, :directly_set_attributes => true)
|
50
|
+
end
|
41
51
|
|
42
|
-
def initialize(passed_keys={})
|
52
|
+
def initialize(passed_keys={}, options={})
|
43
53
|
apply_defaults # defined in CouchRest::Mixins::Properties
|
44
|
-
|
45
|
-
|
54
|
+
remove_protected_attributes(passed_keys) unless options[:directly_set_attributes]
|
55
|
+
directly_set_attributes(passed_keys) unless passed_keys.nil?
|
56
|
+
super(passed_keys)
|
46
57
|
cast_keys # defined in CouchRest::Mixins::Properties
|
47
58
|
unless self['_id'] && self['_rev']
|
48
59
|
self['couchrest-type'] = self.class.to_s
|
@@ -281,14 +292,18 @@ module CouchRest
|
|
281
292
|
raise NoMethodError, "#{attribute_name}= method not available, use property :#{attribute_name}" unless self.respond_to?("#{attribute_name}=")
|
282
293
|
end
|
283
294
|
end
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
attrs.each do |attribute_name, attribute_value|
|
295
|
+
|
296
|
+
def directly_set_attributes(hash)
|
297
|
+
hash.each do |attribute_name, attribute_value|
|
288
298
|
if self.respond_to?("#{attribute_name}=")
|
289
|
-
self.send("#{attribute_name}=",
|
299
|
+
self.send("#{attribute_name}=", hash.delete(attribute_name))
|
290
300
|
end
|
291
301
|
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def set_attributes(hash)
|
305
|
+
attrs = remove_protected_attributes(hash)
|
306
|
+
directly_set_attributes(attrs)
|
292
307
|
end
|
293
308
|
end
|
294
309
|
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.35' unless self.const_defined?("VERSION")
|
32
32
|
|
33
33
|
autoload :Server, 'couchrest/core/server'
|
34
34
|
autoload :Database, 'couchrest/core/database'
|
@@ -551,6 +551,53 @@ describe CouchRest::Database do
|
|
551
551
|
|
552
552
|
end
|
553
553
|
|
554
|
+
describe "UPDATE existing document" do
|
555
|
+
before :each do
|
556
|
+
@id = @db.save_doc({
|
557
|
+
'article' => 'Pete Doherty Kicked Out For Nazi Anthem',
|
558
|
+
'upvotes' => 10,
|
559
|
+
'link' => 'http://beatcrave.com/2009-11-30/pete-doherty-kicked-out-for-nazi-anthem/'})['id']
|
560
|
+
end
|
561
|
+
it "should work under normal conditions" do
|
562
|
+
@db.update_doc @id do |doc|
|
563
|
+
doc['upvotes'] += 1
|
564
|
+
doc
|
565
|
+
end
|
566
|
+
@db.get(@id)['upvotes'].should == 11
|
567
|
+
end
|
568
|
+
it "should fail if update_limit is reached" do
|
569
|
+
lambda do
|
570
|
+
@db.update_doc @id do |doc|
|
571
|
+
# modify and save the doc so that a collision happens
|
572
|
+
conflicting_doc = @db.get @id
|
573
|
+
conflicting_doc['upvotes'] += 1
|
574
|
+
@db.save_doc conflicting_doc
|
575
|
+
|
576
|
+
# then try saving it through the update
|
577
|
+
doc['upvotes'] += 1
|
578
|
+
doc
|
579
|
+
end
|
580
|
+
end.should raise_error(RestClient::RequestFailed)
|
581
|
+
end
|
582
|
+
it "should not fail if update_limit is not reached" do
|
583
|
+
limit = 5
|
584
|
+
lambda do
|
585
|
+
@db.update_doc @id do |doc|
|
586
|
+
# same as the last spec except we're only forcing 5 conflicts
|
587
|
+
if limit > 0
|
588
|
+
conflicting_doc = @db.get @id
|
589
|
+
conflicting_doc['upvotes'] += 1
|
590
|
+
@db.save_doc conflicting_doc
|
591
|
+
limit -= 1
|
592
|
+
end
|
593
|
+
doc['upvotes'] += 1
|
594
|
+
doc
|
595
|
+
end
|
596
|
+
end.should_not raise_error
|
597
|
+
@db.get(@id)['upvotes'].should == 16
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
554
601
|
describe "COPY existing document" do
|
555
602
|
before :each do
|
556
603
|
@r = @db.save_doc({'artist' => 'Zappa', 'title' => 'Muffin Man'})
|
@@ -716,7 +763,7 @@ describe CouchRest::Database do
|
|
716
763
|
|
717
764
|
it "should recreate a db even tho it doesn't exist" do
|
718
765
|
@cr.databases.should_not include(@db2.name)
|
719
|
-
|
766
|
+
@db2.recreate!
|
720
767
|
@cr.databases.should include(@db2.name)
|
721
768
|
end
|
722
769
|
|
@@ -21,6 +21,17 @@ describe "ExtendedDocument", "no declarations" do
|
|
21
21
|
user.name.should == "will"
|
22
22
|
user.phone.should == "555-5555"
|
23
23
|
end
|
24
|
+
|
25
|
+
it "should recreate from the database properly" do
|
26
|
+
user = NoProtection.new
|
27
|
+
user.name = "will"
|
28
|
+
user.phone = "555-5555"
|
29
|
+
user.save!
|
30
|
+
|
31
|
+
user = NoProtection.get(user.id)
|
32
|
+
user.name.should == "will"
|
33
|
+
user.phone.should == "555-5555"
|
34
|
+
end
|
24
35
|
end
|
25
36
|
|
26
37
|
describe "ExtendedDocument", "accessible flag" do
|
@@ -92,3 +103,48 @@ describe "ExtendedDocument", "protected flag" do
|
|
92
103
|
lambda { WithBoth.new }.should raise_error
|
93
104
|
end
|
94
105
|
end
|
106
|
+
|
107
|
+
describe "ExtendedDocument", "from database" do
|
108
|
+
class WithProtected < CouchRest::ExtendedDocument
|
109
|
+
use_database TEST_SERVER.default_database
|
110
|
+
property :name
|
111
|
+
property :admin, :default => false, :protected => true
|
112
|
+
view_by :name
|
113
|
+
end
|
114
|
+
|
115
|
+
before(:each) do
|
116
|
+
@user = WithProtected.new
|
117
|
+
@user.name = "will"
|
118
|
+
@user.admin = true
|
119
|
+
@user.save!
|
120
|
+
end
|
121
|
+
|
122
|
+
def verify_attrs(user)
|
123
|
+
user.name.should == "will"
|
124
|
+
user.admin.should == true
|
125
|
+
end
|
126
|
+
|
127
|
+
it "ExtendedDocument#get should not strip protected attributes" do
|
128
|
+
reloaded = WithProtected.get( @user.id )
|
129
|
+
verify_attrs reloaded
|
130
|
+
end
|
131
|
+
|
132
|
+
it "ExtendedDocument#get! should not strip protected attributes" do
|
133
|
+
reloaded = WithProtected.get!( @user.id )
|
134
|
+
verify_attrs reloaded
|
135
|
+
end
|
136
|
+
|
137
|
+
it "ExtendedDocument#all should not strip protected attributes" do
|
138
|
+
# all creates a CollectionProxy
|
139
|
+
docs = WithProtected.all(:key => @user.id)
|
140
|
+
docs.size.should == 1
|
141
|
+
reloaded = docs.first
|
142
|
+
verify_attrs reloaded
|
143
|
+
end
|
144
|
+
|
145
|
+
it "views should not strip protected attributes" do
|
146
|
+
docs = WithProtected.by_name(:startkey => "will", :endkey => "will")
|
147
|
+
reloaded = docs.first
|
148
|
+
verify_attrs reloaded
|
149
|
+
end
|
150
|
+
end
|
@@ -49,7 +49,7 @@ describe "assigning a value to casted attribute after initializing an object" do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
it "should cast attribute" do
|
52
|
-
@car.driver = JSON.parse(
|
52
|
+
@car.driver = JSON.parse(@driver.to_json)
|
53
53
|
@car.driver.should be_instance_of(Driver)
|
54
54
|
end
|
55
55
|
|
@@ -60,7 +60,7 @@ describe "casting an extended document from parsed JSON" do
|
|
60
60
|
before(:each) do
|
61
61
|
@driver = Driver.new(:name => 'Matt')
|
62
62
|
@car = Car.new(:name => 'Renault 306', :driver => @driver)
|
63
|
-
@new_car = Car.new(JSON.parse(
|
63
|
+
@new_car = Car.new(JSON.parse(@car.to_json))
|
64
64
|
end
|
65
65
|
|
66
66
|
it "should cast casted attribute" do
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rubygems' unless ENV['SKIP_RUBYGEMS']
|
5
|
+
require 'activesupport'
|
6
|
+
ActiveSupport::JSON.backend = :JSONGem
|
7
|
+
|
8
|
+
class PlainParent
|
9
|
+
class_inheritable_accessor :foo
|
10
|
+
self.foo = :bar
|
11
|
+
end
|
12
|
+
|
13
|
+
class PlainChild < PlainParent
|
14
|
+
end
|
15
|
+
|
16
|
+
class ExtendedParent < CouchRest::ExtendedDocument
|
17
|
+
class_inheritable_accessor :foo
|
18
|
+
self.foo = :bar
|
19
|
+
end
|
20
|
+
|
21
|
+
class ExtendedChild < ExtendedParent
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "Using chained inheritance without CouchRest::ExtendedDocument" do
|
25
|
+
it "should preserve inheritable attributes" do
|
26
|
+
PlainParent.foo.should == :bar
|
27
|
+
PlainChild.foo.should == :bar
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "Using chained inheritance with CouchRest::ExtendedDocument" do
|
32
|
+
it "should preserve inheritable attributes" do
|
33
|
+
ExtendedParent.foo.should == :bar
|
34
|
+
ExtendedChild.foo.should == :bar
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
rescue LoadError
|
39
|
+
puts "This spec requires 'active_support' to be loaded"
|
40
|
+
end
|
@@ -25,39 +25,33 @@ describe "ExtendedDocument views" do
|
|
25
25
|
written_at += 24 * 3600
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
29
28
|
it "should have a design doc" do
|
30
29
|
Article.design_doc["views"]["by_date"].should_not be_nil
|
31
30
|
end
|
32
|
-
|
33
31
|
it "should save the design doc" do
|
34
32
|
Article.by_date #rescue nil
|
35
33
|
doc = Article.database.get Article.design_doc.id
|
36
34
|
doc['views']['by_date'].should_not be_nil
|
37
35
|
end
|
38
|
-
|
39
36
|
it "should return the matching raw view result" do
|
40
37
|
view = Article.by_date :raw => true
|
41
38
|
view['rows'].length.should == 4
|
42
39
|
end
|
43
|
-
|
44
40
|
it "should not include non-Articles" do
|
45
41
|
Article.database.save_doc({"date" => 1})
|
46
42
|
view = Article.by_date :raw => true
|
47
43
|
view['rows'].length.should == 4
|
48
44
|
end
|
49
|
-
|
50
45
|
it "should return the matching objects (with default argument :descending => true)" do
|
51
46
|
articles = Article.by_date
|
52
47
|
articles.collect{|a|a.title}.should == @titles.reverse
|
53
48
|
end
|
54
|
-
|
55
49
|
it "should allow you to override default args" do
|
56
50
|
articles = Article.by_date :descending => false
|
57
51
|
articles.collect{|a|a.title}.should == @titles
|
58
52
|
end
|
59
53
|
end
|
60
|
-
|
54
|
+
|
61
55
|
describe "another model with a simple view" do
|
62
56
|
before(:all) do
|
63
57
|
reset_test_db!
|
@@ -96,8 +90,7 @@ describe "ExtendedDocument views" do
|
|
96
90
|
courses[0]["doc"]["title"].should =='aaa'
|
97
91
|
end
|
98
92
|
end
|
99
|
-
|
100
|
-
|
93
|
+
|
101
94
|
describe "a ducktype view" do
|
102
95
|
before(:all) do
|
103
96
|
reset_test_db!
|
@@ -117,7 +110,7 @@ describe "ExtendedDocument views" do
|
|
117
110
|
@as[0]['_id'].should == @id
|
118
111
|
end
|
119
112
|
end
|
120
|
-
|
113
|
+
|
121
114
|
describe "a model class not tied to a database" do
|
122
115
|
before(:all) do
|
123
116
|
reset_test_db!
|
@@ -198,7 +191,7 @@ describe "ExtendedDocument views" do
|
|
198
191
|
Unattached.model_design_doc(@db)['_rev'].should_not == original_revision
|
199
192
|
end
|
200
193
|
end
|
201
|
-
|
194
|
+
|
202
195
|
describe "class proxy" do
|
203
196
|
before(:all) do
|
204
197
|
reset_test_db!
|
@@ -254,6 +247,36 @@ describe "ExtendedDocument views" do
|
|
254
247
|
u = @us.first
|
255
248
|
u.title.should =~ /\A...\z/
|
256
249
|
end
|
250
|
+
it "should set database on first retreived document" do
|
251
|
+
u = @us.first
|
252
|
+
u.database.should === DB
|
253
|
+
end
|
254
|
+
it "should set database on all retreived documents" do
|
255
|
+
@us.all.each do |u|
|
256
|
+
u.database.should === DB
|
257
|
+
end
|
258
|
+
end
|
259
|
+
it "should set database on each retreived document" do
|
260
|
+
rs = @us.by_title :startkey=>"bbb", :endkey=>"eee"
|
261
|
+
rs.length.should == 3
|
262
|
+
rs.each do |u|
|
263
|
+
u.database.should === DB
|
264
|
+
end
|
265
|
+
end
|
266
|
+
it "should set database on document retreived by id" do
|
267
|
+
u = @us.get(@first_id)
|
268
|
+
u.database.should === DB
|
269
|
+
end
|
270
|
+
it "should not attempt to set database on raw results using :all" do
|
271
|
+
@us.all(:raw => true).each do |u|
|
272
|
+
u.respond_to?(:database).should be_false
|
273
|
+
end
|
274
|
+
end
|
275
|
+
it "should not attempt to set database on raw results using view" do
|
276
|
+
@us.by_title(:raw => true).each do |u|
|
277
|
+
u.respond_to?(:database).should be_false
|
278
|
+
end
|
279
|
+
end
|
257
280
|
it "should clean up design docs left around on specific database" do
|
258
281
|
@us.by_title
|
259
282
|
original_id = @us.model_design_doc['_rev']
|
@@ -262,7 +285,7 @@ describe "ExtendedDocument views" do
|
|
262
285
|
@us.model_design_doc['_rev'].should_not == original_id
|
263
286
|
end
|
264
287
|
end
|
265
|
-
|
288
|
+
|
266
289
|
describe "a model with a compound key view" do
|
267
290
|
before(:all) do
|
268
291
|
Article.by_user_id_and_date.each{|a| a.destroy(true)}
|
@@ -295,7 +318,7 @@ describe "ExtendedDocument views" do
|
|
295
318
|
articles[0].title.should == "even more interesting"
|
296
319
|
end
|
297
320
|
end
|
298
|
-
|
321
|
+
|
299
322
|
describe "with a custom view" do
|
300
323
|
before(:all) do
|
301
324
|
@titles = ["very uniq one", "even less interesting", "some fun",
|
@@ -311,18 +334,18 @@ describe "ExtendedDocument views" do
|
|
311
334
|
view = Article.by_tags :raw => true
|
312
335
|
view['rows'].length.should == 5
|
313
336
|
end
|
314
|
-
|
337
|
+
|
315
338
|
it "should be default to :reduce => false" do
|
316
339
|
ars = Article.by_tags
|
317
340
|
ars.first.tags.first.should == 'cool'
|
318
341
|
end
|
319
|
-
|
342
|
+
|
320
343
|
it "should be raw when reduce is true" do
|
321
344
|
view = Article.by_tags :reduce => true, :group => true
|
322
345
|
view['rows'].find{|r|r['key'] == 'cool'}['value'].should == 3
|
323
346
|
end
|
324
347
|
end
|
325
|
-
|
348
|
+
|
326
349
|
# TODO: moved to Design, delete
|
327
350
|
describe "adding a view" do
|
328
351
|
before(:each) do
|
@@ -344,7 +367,7 @@ describe "ExtendedDocument views" do
|
|
344
367
|
Article.design_doc["views"].keys.should include("by_updated_at")
|
345
368
|
end
|
346
369
|
end
|
347
|
-
|
370
|
+
|
348
371
|
describe "with a collection" do
|
349
372
|
before(:all) do
|
350
373
|
reset_test_db!
|
@@ -354,7 +377,7 @@ describe "ExtendedDocument views" do
|
|
354
377
|
a = Article.new(:title => title, :date => Date.today)
|
355
378
|
a.save
|
356
379
|
end
|
357
|
-
|
380
|
+
|
358
381
|
titles = ["yesterday very uniq one", "yesterday really interesting", "yesterday some fun",
|
359
382
|
"yesterday really awesome", "yesterday crazy bob", "yesterday this rocks"]
|
360
383
|
titles.each_with_index do |title,i|
|
@@ -390,11 +413,11 @@ describe "ExtendedDocument views" do
|
|
390
413
|
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
391
414
|
:per_page => 3, :descending => true, :key => Date.today, :include_docs => true)
|
392
415
|
articles.size.should == 3
|
393
|
-
|
416
|
+
|
394
417
|
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
395
418
|
:per_page => 3, :page => 2, :descending => true, :key => Date.today, :include_docs => true)
|
396
419
|
articles.size.should == 3
|
397
|
-
|
420
|
+
|
398
421
|
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
399
422
|
:per_page => 3, :page => 3, :descending => true, :key => Date.today, :include_docs => true)
|
400
423
|
articles.size.should == 1
|
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.
|
4
|
+
version: "0.35"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- J. Chris Anderson
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2010-
|
14
|
+
date: 2010-02-27 00:00:00 -03:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- spec/couchrest/more/casted_extended_doc_spec.rb
|
122
122
|
- spec/couchrest/more/casted_model_spec.rb
|
123
123
|
- spec/couchrest/more/extended_doc_attachment_spec.rb
|
124
|
+
- spec/couchrest/more/extended_doc_inherited_spec.rb
|
124
125
|
- spec/couchrest/more/extended_doc_spec.rb
|
125
126
|
- spec/couchrest/more/extended_doc_subclass_spec.rb
|
126
127
|
- spec/couchrest/more/extended_doc_view_spec.rb
|
@@ -187,6 +188,7 @@ test_files:
|
|
187
188
|
- spec/couchrest/more/casted_extended_doc_spec.rb
|
188
189
|
- spec/couchrest/more/casted_model_spec.rb
|
189
190
|
- spec/couchrest/more/extended_doc_attachment_spec.rb
|
191
|
+
- spec/couchrest/more/extended_doc_inherited_spec.rb
|
190
192
|
- spec/couchrest/more/extended_doc_spec.rb
|
191
193
|
- spec/couchrest/more/extended_doc_subclass_spec.rb
|
192
194
|
- spec/couchrest/more/extended_doc_view_spec.rb
|