couchrest 0.34 → 0.35
Sign up to get free protection for your applications and to get access to all the features.
- 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
|