couch_potato 0.6.0 → 0.7.0.pre.1
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/.gitignore +0 -1
- data/.travis.yml +9 -1
- data/CHANGES.md +12 -0
- data/Gemfile.lock +29 -23
- data/MIT-LICENSE.txt +1 -1
- data/README.md +68 -38
- data/Rakefile +19 -60
- data/active_support_3_0.lock +4 -0
- data/active_support_3_1.lock +4 -0
- data/active_support_3_2 +4 -0
- data/active_support_3_2.lock +55 -0
- data/couch_potato.gemspec +1 -0
- data/lib/couch_potato/database.rb +55 -27
- data/lib/couch_potato/persistence/active_model_compliance.rb +6 -2
- data/lib/couch_potato/persistence/callbacks.rb +0 -1
- data/lib/couch_potato/persistence/dirty_attributes.rb +8 -17
- data/lib/couch_potato/persistence/json.rb +3 -2
- data/lib/couch_potato/persistence/properties.rb +19 -8
- data/lib/couch_potato/persistence/simple_property.rb +1 -3
- data/lib/couch_potato/persistence/type_caster.rb +7 -2
- data/lib/couch_potato/persistence.rb +27 -13
- data/lib/couch_potato/railtie.rb +1 -1
- data/lib/couch_potato/rspec/matchers/list_as_matcher.rb +12 -12
- data/lib/couch_potato/rspec/matchers/map_to_matcher.rb +8 -8
- data/lib/couch_potato/rspec/matchers/reduce_to_matcher.rb +10 -10
- data/lib/couch_potato/rspec/matchers.rb +8 -7
- data/lib/couch_potato/validation.rb +15 -11
- data/lib/couch_potato/version.rb +1 -1
- data/lib/couch_potato/view/base_view_spec.rb +14 -12
- data/lib/couch_potato/view/model_view_spec.rb +134 -39
- data/lib/couch_potato/view/properties_view_spec.rb +11 -7
- data/lib/couch_potato/view/view_query.rb +10 -9
- data/lib/couch_potato.rb +25 -10
- data/spec/callbacks_spec.rb +88 -0
- data/spec/create_spec.rb +22 -4
- data/spec/default_property_spec.rb +6 -0
- data/spec/property_spec.rb +81 -44
- data/spec/railtie_spec.rb +20 -18
- data/spec/spec_helper.rb +19 -1
- data/spec/unit/active_model_compliance_spec.rb +17 -11
- data/spec/unit/attributes_spec.rb +33 -10
- data/spec/unit/base_view_spec_spec.rb +19 -5
- data/spec/unit/couch_potato_spec.rb +1 -20
- data/spec/unit/create_spec.rb +2 -2
- data/spec/unit/database_spec.rb +113 -47
- data/spec/unit/dirty_attributes_spec.rb +19 -19
- data/spec/unit/model_view_spec_spec.rb +78 -1
- data/spec/unit/properties_view_spec_spec.rb +18 -5
- data/spec/unit/validation_spec.rb +1 -55
- data/spec/unit/view_query_spec.rb +48 -26
- data/spec/{custom_view_spec.rb → views_spec.rb} +59 -17
- metadata +88 -90
- data/.rvmrc +0 -1
- data/lib/core_ext/object.rb +0 -5
- data/lib/core_ext/string.rb +0 -12
- data/lib/core_ext/symbol.rb +0 -15
- data/lib/couch_potato/validation/with_active_model.rb +0 -27
- data/lib/couch_potato/validation/with_validatable.rb +0 -41
@@ -26,23 +26,4 @@ describe CouchPotato, '.models' do
|
|
26
26
|
|
27
27
|
CouchPotato.models.should include(clazz)
|
28
28
|
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe CouchPotato, 'validation_framework' do
|
32
|
-
before(:each) do
|
33
|
-
@original_validation_framework = CouchPotato::Config.validation_framework
|
34
|
-
end
|
35
|
-
after(:each) do
|
36
|
-
CouchPotato::Config.validation_framework = @original_validation_framework
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should allow setting the validation_framework to :active_model" do
|
40
|
-
CouchPotato::Config.validation_framework = :active_model
|
41
|
-
CouchPotato::Config.validation_framework.should == :active_model
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should allow setting the validation_framework to :validatable" do
|
45
|
-
CouchPotato::Config.validation_framework = :validatable
|
46
|
-
CouchPotato::Config.validation_framework.should == :validatable
|
47
|
-
end
|
48
|
-
end
|
29
|
+
end
|
data/spec/unit/create_spec.rb
CHANGED
@@ -23,14 +23,14 @@ describe "create" do
|
|
23
23
|
|
24
24
|
it "should set created at in the current time zone" do
|
25
25
|
Time.zone = 'Europe/Berlin'
|
26
|
-
Timecop.travel 2010
|
26
|
+
Timecop.travel Time.zone.parse('2010-01-01 12:00 +0100') do
|
27
27
|
create_comment.created_at.to_s.should == '2010-01-01 12:00:00 +0100'
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should set updated at in the current time zone" do
|
32
32
|
Time.zone = 'Europe/Berlin'
|
33
|
-
Timecop.travel 2010
|
33
|
+
Timecop.travel Time.zone.parse('2010-01-01 12:00 +0100') do
|
34
34
|
create_comment.updated_at.to_s.should == '2010-01-01 12:00:00 +0100'
|
35
35
|
end
|
36
36
|
end
|
data/spec/unit/database_spec.rb
CHANGED
@@ -27,17 +27,17 @@ describe CouchPotato::Database, 'full_url_to_database' do
|
|
27
27
|
after(:all) do
|
28
28
|
CouchPotato::Config.database_name = @database_url
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
it "should return the full URL when it starts with https" do
|
32
32
|
CouchPotato::Config.database_name = "https://example.com/database"
|
33
33
|
CouchPotato.full_url_to_database.should == 'https://example.com/database'
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
it "should return the full URL when it starts with http" do
|
37
37
|
CouchPotato::Config.database_name = "http://example.com/database"
|
38
38
|
CouchPotato.full_url_to_database.should == 'http://example.com/database'
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
it "should use localhost when no protocol was specified" do
|
42
42
|
CouchPotato::Config.database_name = "database"
|
43
43
|
CouchPotato.full_url_to_database.should == 'http://127.0.0.1:5984/database'
|
@@ -45,8 +45,11 @@ describe CouchPotato::Database, 'full_url_to_database' do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
describe CouchPotato::Database, 'load' do
|
48
|
+
|
49
|
+
let(:couchrest_db) { stub('couchrest db', :info => nil) }
|
50
|
+
let(:db) { CouchPotato::Database.new couchrest_db }
|
51
|
+
|
48
52
|
it "should raise an exception if nil given" do
|
49
|
-
db = CouchPotato::Database.new(stub('couchrest db', :info => nil))
|
50
53
|
lambda {
|
51
54
|
db.load nil
|
52
55
|
}.should raise_error("Can't load a document without an id (got nil)")
|
@@ -55,33 +58,95 @@ describe CouchPotato::Database, 'load' do
|
|
55
58
|
it "should set itself on the model" do
|
56
59
|
user = mock('user').as_null_object
|
57
60
|
DbTestUser.stub!(:new).and_return(user)
|
58
|
-
|
61
|
+
couchrest_db.stub(:get).and_return DbTestUser.json_create({JSON.create_id => 'DbTestUser'})
|
59
62
|
user.should_receive(:database=).with(db)
|
60
63
|
db.load '1'
|
61
64
|
end
|
62
65
|
|
63
66
|
it "should load namespaced models" do
|
64
|
-
|
67
|
+
couchrest_db.stub(:get).and_return Parent::Child.json_create({JSON.create_id => 'Parent::Child'})
|
65
68
|
db.load('1').class.should == Parent::Child
|
66
69
|
end
|
70
|
+
|
71
|
+
context "when several ids given" do
|
72
|
+
|
73
|
+
let(:doc1) { DbTestUser.new }
|
74
|
+
let(:doc2) { DbTestUser.new }
|
75
|
+
let(:response) do
|
76
|
+
{"rows" => [{}, {"doc" => doc1}, {"doc" => doc2}]}
|
77
|
+
end
|
78
|
+
|
79
|
+
before(:each) do
|
80
|
+
couchrest_db.stub(:bulk_load).and_return response
|
81
|
+
end
|
82
|
+
|
83
|
+
it "requests the couchrest bulk method" do
|
84
|
+
couchrest_db.should_receive(:bulk_load).with(['1', '2', '3'])
|
85
|
+
db.load ['1', '2', '3']
|
86
|
+
end
|
87
|
+
|
88
|
+
it "returns only found documents" do
|
89
|
+
db.load(['1', '2', '3']).should have(2).items
|
90
|
+
end
|
91
|
+
|
92
|
+
it "writes itself to each of the documents" do
|
93
|
+
db.load(['1', '2', '3']).each do |doc|
|
94
|
+
doc.database.should eql(db)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
67
98
|
end
|
68
99
|
|
69
100
|
describe CouchPotato::Database, 'load!' do
|
101
|
+
|
102
|
+
let(:db) { CouchPotato::Database.new(stub('couchrest db', :info => nil).as_null_object) }
|
103
|
+
|
70
104
|
it "should raise an error if no document found" do
|
71
|
-
|
72
|
-
couchrest_db.stub(:get).and_raise(RestClient::ResourceNotFound)
|
73
|
-
db = CouchPotato::Database.new(couchrest_db)
|
105
|
+
db.couchrest_database.stub(:get).and_raise(RestClient::ResourceNotFound)
|
74
106
|
lambda {
|
75
107
|
db.load! '1'
|
76
108
|
}.should raise_error(CouchPotato::NotFound)
|
77
109
|
end
|
110
|
+
|
111
|
+
it 'returns the found document' do
|
112
|
+
doc = stub(:doc).as_null_object
|
113
|
+
db.couchrest_database.stub(:get) {doc}
|
114
|
+
db.load!('1').should == doc
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when several ids given" do
|
118
|
+
|
119
|
+
let(:docs) do
|
120
|
+
[
|
121
|
+
DbTestUser.new(:id => '1'),
|
122
|
+
DbTestUser.new(:id => '2')
|
123
|
+
]
|
124
|
+
end
|
125
|
+
|
126
|
+
before(:each) do
|
127
|
+
db.stub(:load).and_return(docs)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "raises an exception when not all documents could be found" do
|
131
|
+
lambda {
|
132
|
+
db.load! ['1', '2', '3', '4']
|
133
|
+
}.should raise_error(CouchPotato::NotFound, '3, 4')
|
134
|
+
end
|
135
|
+
|
136
|
+
it "raises no exception when all documents are found" do
|
137
|
+
docs << DbTestUser.new(:id => '3')
|
138
|
+
lambda {
|
139
|
+
db.load! ['1', '2', '3']
|
140
|
+
}.should_not raise_error(CouchPotato::NotFound)
|
141
|
+
end
|
142
|
+
end
|
78
143
|
end
|
79
144
|
|
80
145
|
describe CouchPotato::Database, 'save_document' do
|
81
146
|
before(:each) do
|
82
147
|
@db = CouchPotato::Database.new(stub('couchrest db').as_null_object)
|
83
148
|
end
|
84
|
-
|
149
|
+
|
85
150
|
it "should set itself on the model for a new object before doing anything else" do
|
86
151
|
@db.stub(:valid_document?).and_return false
|
87
152
|
user = stub('user', :new? => true).as_null_object
|
@@ -94,18 +159,18 @@ describe CouchPotato::Database, 'save_document' do
|
|
94
159
|
property :name
|
95
160
|
validates_presence_of :name
|
96
161
|
end
|
97
|
-
|
162
|
+
|
98
163
|
it "should return false when creating a new document and the validations failed" do
|
99
164
|
CouchPotato.database.save_document(Category.new).should == false
|
100
165
|
end
|
101
|
-
|
166
|
+
|
102
167
|
it "should return false when saving an existing document and the validations failed" do
|
103
168
|
category = Category.new(:name => "pizza")
|
104
169
|
CouchPotato.database.save_document(category).should == true
|
105
170
|
category.name = nil
|
106
171
|
CouchPotato.database.save_document(category).should == false
|
107
172
|
end
|
108
|
-
|
173
|
+
|
109
174
|
describe "when creating with validate options" do
|
110
175
|
it "should not run the validations when saved with false" do
|
111
176
|
category = Category.new
|
@@ -155,27 +220,27 @@ describe CouchPotato::Database, 'save_document' do
|
|
155
220
|
category.dirty?.should == true
|
156
221
|
end
|
157
222
|
end
|
158
|
-
|
223
|
+
|
159
224
|
describe "when saving documents with errors set in callbacks" do
|
160
225
|
class Vulcan
|
161
226
|
include CouchPotato::Persistence
|
162
227
|
before_validation_on_create :set_errors
|
163
228
|
before_validation_on_update :set_errors
|
164
|
-
|
229
|
+
|
165
230
|
property :name
|
166
231
|
validates_presence_of :name
|
167
|
-
|
232
|
+
|
168
233
|
def set_errors
|
169
234
|
errors.add(:validation, "failed")
|
170
235
|
end
|
171
236
|
end
|
172
|
-
|
237
|
+
|
173
238
|
it "should keep errors added in before_validation_on_* callbacks when creating a new object" do
|
174
239
|
spock = Vulcan.new(:name => 'spock')
|
175
240
|
@db.save_document(spock)
|
176
241
|
spock.errors[:validation].should == ['failed']
|
177
242
|
end
|
178
|
-
|
243
|
+
|
179
244
|
it "should keep errors added in before_validation_on_* callbacks when creating a new object" do
|
180
245
|
spock = Vulcan.new(:name => 'spock')
|
181
246
|
@db.save_document(spock, false)
|
@@ -184,36 +249,36 @@ describe CouchPotato::Database, 'save_document' do
|
|
184
249
|
@db.save_document(spock)
|
185
250
|
spock.errors[:validation].should == ['failed']
|
186
251
|
end
|
187
|
-
|
252
|
+
|
188
253
|
it "should keep errors generated from normal validations together with errors set in normal validations" do
|
189
254
|
spock = Vulcan.new
|
190
255
|
@db.save_document(spock)
|
191
256
|
spock.errors[:validation].should == ['failed']
|
192
257
|
spock.errors[:name].first.should =~ /can't be (empty|blank)/
|
193
258
|
end
|
194
|
-
|
259
|
+
|
195
260
|
it "should clear errors on subsequent, valid saves when creating" do
|
196
261
|
spock = Vulcan.new
|
197
262
|
@db.save_document(spock)
|
198
|
-
|
263
|
+
|
199
264
|
spock.name = 'Spock'
|
200
265
|
@db.save_document(spock)
|
201
266
|
spock.errors[:name].should == []
|
202
267
|
end
|
203
|
-
|
268
|
+
|
204
269
|
it "should clear errors on subsequent, valid saves when updating" do
|
205
270
|
spock = Vulcan.new(:name => 'spock')
|
206
271
|
@db.save_document(spock, false)
|
207
|
-
|
272
|
+
|
208
273
|
spock.name = nil
|
209
274
|
@db.save_document(spock)
|
210
275
|
spock.errors[:name].first.should =~ /can't be (empty|blank)/
|
211
|
-
|
276
|
+
|
212
277
|
spock.name = 'Spock'
|
213
278
|
@db.save_document(spock)
|
214
279
|
spock.errors[:name].should == []
|
215
280
|
end
|
216
|
-
|
281
|
+
|
217
282
|
end
|
218
283
|
end
|
219
284
|
|
@@ -225,11 +290,11 @@ describe CouchPotato::Database, 'first' do
|
|
225
290
|
@spec = stub('view spec', :process_results => [@result]).as_null_object
|
226
291
|
CouchPotato::View::ViewQuery.stub(:new => stub('view query', :query_view! => {'rows' => [@result]}))
|
227
292
|
end
|
228
|
-
|
293
|
+
|
229
294
|
it "should return the first result from a view query" do
|
230
295
|
@db.first(@spec).should == @result
|
231
296
|
end
|
232
|
-
|
297
|
+
|
233
298
|
it "should return nil if there are no results" do
|
234
299
|
@spec.stub(:process_results => [])
|
235
300
|
@db.first(@spec).should be_nil
|
@@ -244,12 +309,12 @@ describe CouchPotato::Database, 'first!' do
|
|
244
309
|
@spec = stub('view spec', :process_results => [@result]).as_null_object
|
245
310
|
CouchPotato::View::ViewQuery.stub(:new => stub('view query', :query_view! => {'rows' => [@result]}))
|
246
311
|
end
|
247
|
-
|
248
|
-
it "
|
312
|
+
|
313
|
+
it "returns the first result from a view query" do
|
249
314
|
@db.first!(@spec).should == @result
|
250
315
|
end
|
251
|
-
|
252
|
-
it "
|
316
|
+
|
317
|
+
it "raises an error if there are no results" do
|
253
318
|
@spec.stub(:process_results => [])
|
254
319
|
lambda {
|
255
320
|
@db.first!(@spec)
|
@@ -265,11 +330,11 @@ describe CouchPotato::Database, 'view' do
|
|
265
330
|
@spec = stub('view spec', :process_results => [@result]).as_null_object
|
266
331
|
CouchPotato::View::ViewQuery.stub(:new => stub('view query', :query_view! => {'rows' => [@result]}))
|
267
332
|
end
|
268
|
-
|
269
|
-
it "
|
333
|
+
|
334
|
+
it "initialzes a view query with map/reduce/list funtions" do
|
270
335
|
@spec.stub(:design_document => 'design_doc', :view_name => 'my_view',
|
271
336
|
:map_function => '<map_code>', :reduce_function => '<reduce_code>',
|
272
|
-
:list_name => 'my_list', :list_function => '<list_code>')
|
337
|
+
:list_name => 'my_list', :list_function => '<list_code>', :language => 'javascript')
|
273
338
|
CouchPotato::View::ViewQuery.should_receive(:new).with(
|
274
339
|
@couchrest_db,
|
275
340
|
'design_doc',
|
@@ -277,41 +342,42 @@ describe CouchPotato::Database, 'view' do
|
|
277
342
|
:map => '<map_code>',
|
278
343
|
:reduce => '<reduce_code>'
|
279
344
|
}},
|
280
|
-
{'my_list' => '<list_code>'}
|
345
|
+
{'my_list' => '<list_code>'},
|
346
|
+
'javascript')
|
281
347
|
@db.view(@spec)
|
282
348
|
end
|
283
|
-
|
284
|
-
it "
|
349
|
+
|
350
|
+
it "initialzes a view query with only map/reduce functions" do
|
285
351
|
@spec.stub(:design_document => 'design_doc', :view_name => 'my_view',
|
286
352
|
:map_function => '<map_code>', :reduce_function => '<reduce_code>',
|
287
|
-
:list_name => nil, :list_function => nil)
|
353
|
+
:list_name => nil, :list_function => nil).as_null_object
|
288
354
|
CouchPotato::View::ViewQuery.should_receive(:new).with(
|
289
355
|
@couchrest_db,
|
290
356
|
'design_doc',
|
291
357
|
{'my_view' => {
|
292
358
|
:map => '<map_code>',
|
293
359
|
:reduce => '<reduce_code>'
|
294
|
-
}}, nil)
|
360
|
+
}}, nil, anything)
|
295
361
|
@db.view(@spec)
|
296
362
|
end
|
297
|
-
|
298
|
-
it "
|
363
|
+
|
364
|
+
it "sets itself on returned results that have an accessor" do
|
299
365
|
@result.stub(:respond_to?).with(:database=).and_return(true)
|
300
366
|
@result.should_receive(:database=).with(@db)
|
301
367
|
@db.view(@spec)
|
302
368
|
end
|
303
|
-
|
304
|
-
it "
|
369
|
+
|
370
|
+
it "does not set itself on returned results that don't have an accessor" do
|
305
371
|
@result.stub(:respond_to?).with(:database=).and_return(false)
|
306
372
|
@result.should_not_receive(:database=).with(@db)
|
307
373
|
@db.view(@spec)
|
308
374
|
end
|
309
|
-
|
310
|
-
it "
|
375
|
+
|
376
|
+
it "does not try to set itself on result sets that are not collections" do
|
311
377
|
lambda {
|
312
378
|
@spec.stub(:process_results => 1)
|
313
379
|
}.should_not raise_error
|
314
|
-
|
380
|
+
|
315
381
|
@db.view(@spec)
|
316
382
|
end
|
317
|
-
end
|
383
|
+
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
class Plate
|
4
4
|
include CouchPotato::Persistence
|
5
|
-
|
5
|
+
|
6
6
|
property :food
|
7
7
|
end
|
8
8
|
|
@@ -11,7 +11,7 @@ describe 'dirty attribute tracking' do
|
|
11
11
|
@couchrest_db = stub('database', :save_doc => {'id' => '1', 'rev' => '2'}, :info => nil)
|
12
12
|
@db = CouchPotato::Database.new(@couchrest_db)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
describe "save" do
|
16
16
|
it "should not save when nothing dirty" do
|
17
17
|
plate = Plate.new :food => 'sushi'
|
@@ -19,13 +19,13 @@ describe 'dirty attribute tracking' do
|
|
19
19
|
@couchrest_db.should_not_receive(:save_doc)
|
20
20
|
@db.save_document(plate)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it "should return true when not dirty" do
|
24
24
|
plate = Plate.new :food => 'sushi'
|
25
25
|
@db.save_document!(plate)
|
26
26
|
@db.save_document(plate).should be_true
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
it "should save when there are dirty attributes" do
|
30
30
|
plate = Plate.new :food => 'sushi'
|
31
31
|
@db.save_document!(plate)
|
@@ -34,19 +34,19 @@ describe 'dirty attribute tracking' do
|
|
34
34
|
@db.save_document(plate)
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
describe "newly created object" do
|
39
|
-
|
39
|
+
|
40
40
|
before(:each) do
|
41
41
|
@plate = Plate.new :food => 'sushi'
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
describe "access old values" do
|
45
45
|
it "should return the old value" do
|
46
46
|
@plate.food = 'burger'
|
47
47
|
@plate.food_was.should == 'sushi'
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
describe "with type BigDecimal" do
|
51
51
|
before(:each) do
|
52
52
|
class Bowl
|
@@ -57,16 +57,16 @@ describe 'dirty attribute tracking' do
|
|
57
57
|
it "should not dup BigDecimal" do
|
58
58
|
|
59
59
|
lambda {
|
60
|
-
Bowl.new :price => BigDecimal.new("5.23")
|
60
|
+
Bowl.new :price => BigDecimal.new("5.23")
|
61
61
|
}.should_not raise_error(TypeError)
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
it "should return the old value" do
|
65
|
-
bowl = Bowl.new :price => BigDecimal.new("5.23")
|
65
|
+
bowl = Bowl.new :price => BigDecimal.new("5.23")
|
66
66
|
bowl.price = BigDecimal.new("2.23")
|
67
67
|
bowl.price_was.should == 5.23
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -79,20 +79,20 @@ describe 'dirty attribute tracking' do
|
|
79
79
|
it "should return false if attribute not changed" do
|
80
80
|
Plate.new.should_not be_food_changed
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
it "should return true if forced dirty" do
|
84
84
|
@plate.is_dirty
|
85
85
|
@plate.should be_dirty
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
describe "object loaded from database" do
|
91
91
|
before(:each) do
|
92
92
|
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil)
|
93
93
|
@plate = CouchPotato::Database.new(couchrest_db).load_document '1'
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
96
|
describe "access old values" do
|
97
97
|
it "should return the old value" do
|
98
98
|
@plate.food = 'burger'
|
@@ -111,8 +111,8 @@ describe 'dirty attribute tracking' do
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
114
|
-
|
115
|
-
|
114
|
+
|
115
|
+
|
116
116
|
describe "after save" do
|
117
117
|
it "should reset all attributes to not dirty" do
|
118
118
|
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil, :save_doc => {})
|
@@ -122,7 +122,7 @@ describe 'dirty attribute tracking' do
|
|
122
122
|
db.save! @plate
|
123
123
|
@plate.should_not be_food_changed
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
it "should reset a forced dirty state" do
|
127
127
|
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil, :save_doc => {'rev' => '3'})
|
128
128
|
db = CouchPotato::Database.new(couchrest_db)
|
@@ -132,5 +132,5 @@ describe 'dirty attribute tracking' do
|
|
132
132
|
@plate.should_not be_dirty
|
133
133
|
end
|
134
134
|
end
|
135
|
-
|
135
|
+
|
136
136
|
end
|
@@ -5,9 +5,86 @@ describe CouchPotato::View::ModelViewSpec, 'map_function' do
|
|
5
5
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:conditions => 'doc.closed = true'}, {}
|
6
6
|
spec.map_function.should include('if(doc.ruby_class && doc.ruby_class == \'Object\' && (doc.closed = true))')
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
|
+
it 'generates an erlang map function with a single key if the language is erlang' do
|
10
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:key => :name, :language => :erlang}, {}
|
11
|
+
spec.map_function.should eql_ignoring_indentation(<<-ERL
|
12
|
+
fun({Doc}) ->
|
13
|
+
case proplists:get_value(<<"ruby_class">>, Doc) of
|
14
|
+
<<"Object">> ->
|
15
|
+
Key = proplists:get_value(<<"name">>, Doc, null),
|
16
|
+
Emit(Key, 1);
|
17
|
+
_ ->
|
18
|
+
ok
|
19
|
+
end
|
20
|
+
end.
|
21
|
+
ERL
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'generates an erlang map function with a composite key if the language is erlang' do
|
26
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:key => [:code, :name], :language => :erlang}, {}
|
27
|
+
spec.map_function.should eql_ignoring_indentation(<<-ERL
|
28
|
+
fun({Doc}) ->
|
29
|
+
case proplists:get_value(<<"ruby_class">>, Doc) of
|
30
|
+
<<"Object">> ->
|
31
|
+
Key_0 = proplists:get_value(<<"code">>, Doc, null),
|
32
|
+
Key_1 = proplists:get_value(<<"name">>, Doc, null),
|
33
|
+
Emit([Key_0, Key_1], 1);
|
34
|
+
_ ->
|
35
|
+
ok
|
36
|
+
end
|
37
|
+
end.
|
38
|
+
ERL
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'does not support conditions in erlang' do
|
43
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:language => :erlang, :conditions => 'abc'}, {}
|
44
|
+
lambda {
|
45
|
+
spec.map_function
|
46
|
+
}.should raise_error(NotImplementedError)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'does not support a custom emit value in erlang' do
|
50
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:language => :erlang, :emit_value => :count}, {}
|
51
|
+
lambda {
|
52
|
+
spec.map_function
|
53
|
+
}.should raise_error(NotImplementedError)
|
54
|
+
end
|
55
|
+
|
9
56
|
it "should not include conditions when they are nil" do
|
10
57
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {}, {}
|
11
58
|
spec.map_function.should include('if(doc.ruby_class && doc.ruby_class == \'Object\')')
|
12
59
|
end
|
60
|
+
|
61
|
+
it "should have a custom emit value when specified as symbol" do
|
62
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => :count}, {}
|
63
|
+
spec.map_function.should include(%{emit(doc[''], doc['count'])})
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should have a custom emit value when specified as string" do
|
67
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => "doc['a'] + doc['b']"}, {}
|
68
|
+
spec.map_function.should include("emit(doc[''], doc['a'] + doc['b'])")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should have a custom emit value when specified as integer" do
|
72
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => 7}, {}
|
73
|
+
spec.map_function.should include("emit(doc[''], 7)")
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should have a custom emit value when specified as float" do
|
77
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => 7.2}, {}
|
78
|
+
spec.map_function.should include("emit(doc[''], 7.2")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should have a emit value of 1 when nothing is specified" do
|
82
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {}, {}
|
83
|
+
spec.map_function.should include("emit(doc[''], 1")
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should raise exception when emit value cannot be handled" do
|
87
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => []}, {}
|
88
|
+
lambda { spec.map_function }.should raise_error
|
89
|
+
end
|
13
90
|
end
|
@@ -3,29 +3,42 @@ require 'couch_potato/rspec'
|
|
3
3
|
|
4
4
|
class Contract
|
5
5
|
include CouchPotato::Persistence
|
6
|
-
|
6
|
+
|
7
7
|
property :date
|
8
8
|
property :terms
|
9
|
-
|
9
|
+
|
10
10
|
view :by_date, :type => :properties, :key => :_id, :properties => [:date]
|
11
11
|
end
|
12
12
|
|
13
13
|
describe CouchPotato::View::PropertiesViewSpec do
|
14
|
+
before(:each) do
|
15
|
+
@default_language = CouchPotato::Config.default_language
|
16
|
+
end
|
17
|
+
|
18
|
+
after(:each) do
|
19
|
+
CouchPotato::Config.default_language = @default_language
|
20
|
+
end
|
21
|
+
|
14
22
|
it "should map the given properties" do
|
15
23
|
Contract.by_date.should map(
|
16
24
|
Contract.new(:date => '2010-01-01', :_id => '1')
|
17
25
|
).to(['1', {"date" => "2010-01-01"}])
|
18
26
|
end
|
19
|
-
|
27
|
+
|
20
28
|
it "should reduce to the number of documents" do
|
21
29
|
Contract.by_date.should reduce(
|
22
30
|
['1', {"date" => "2010-01-01"}], ['2', {"date" => "2010-01-02"}]
|
23
31
|
).to(2)
|
24
32
|
end
|
25
|
-
|
33
|
+
|
26
34
|
it "should rereduce the number of documents" do
|
27
35
|
Contract.by_date.should rereduce(
|
28
36
|
nil, [12, 13]
|
29
37
|
).to(25)
|
30
38
|
end
|
31
|
-
|
39
|
+
|
40
|
+
it 'always uses javascript' do
|
41
|
+
CouchPotato::Config.default_language = :erlang
|
42
|
+
CouchPotato::View::PropertiesViewSpec.new(Contract, 'all', {}, {}).language.should == :javascript
|
43
|
+
end
|
44
|
+
end
|