couchrest_model 2.1.0.rc1 → 2.2.0.beta1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +15 -4
- data/Gemfile.activesupport-4.x +4 -0
- data/Gemfile.activesupport-5.x +4 -0
- data/README.md +2 -0
- data/VERSION +1 -1
- data/couchrest_model.gemspec +3 -2
- data/history.md +14 -1
- data/lib/couchrest/model/associations.rb +3 -8
- data/lib/couchrest/model/base.rb +15 -7
- data/lib/couchrest/model/casted_array.rb +22 -34
- data/lib/couchrest/model/configuration.rb +2 -0
- data/lib/couchrest/model/design.rb +4 -3
- data/lib/couchrest/model/designs/view.rb +37 -32
- data/lib/couchrest/model/dirty.rb +93 -19
- data/lib/couchrest/model/embeddable.rb +2 -14
- data/lib/couchrest/model/extended_attachments.rb +2 -4
- data/lib/couchrest/model/persistence.rb +14 -17
- data/lib/couchrest/model/properties.rb +46 -54
- data/lib/couchrest/model/property.rb +0 -3
- data/lib/couchrest/model/proxyable.rb +20 -4
- data/lib/couchrest/model/validations/uniqueness.rb +4 -1
- data/lib/couchrest_model.rb +2 -2
- data/spec/fixtures/models/article.rb +1 -1
- data/spec/fixtures/models/card.rb +2 -1
- data/spec/fixtures/models/person.rb +1 -0
- data/spec/fixtures/models/project.rb +3 -0
- data/spec/unit/assocations_spec.rb +73 -73
- data/spec/unit/attachment_spec.rb +34 -34
- data/spec/unit/base_spec.rb +102 -102
- data/spec/unit/casted_array_spec.rb +7 -7
- data/spec/unit/casted_spec.rb +7 -7
- data/spec/unit/configuration_spec.rb +11 -11
- data/spec/unit/connection_spec.rb +30 -30
- data/spec/unit/core_extensions/{time_parsing.rb → time_parsing_spec.rb} +21 -21
- data/spec/unit/design_spec.rb +38 -38
- data/spec/unit/designs/design_mapper_spec.rb +26 -26
- data/spec/unit/designs/migrations_spec.rb +13 -13
- data/spec/unit/designs/view_spec.rb +319 -274
- data/spec/unit/designs_spec.rb +39 -39
- data/spec/unit/dirty_spec.rb +188 -103
- data/spec/unit/embeddable_spec.rb +119 -117
- data/spec/unit/inherited_spec.rb +4 -4
- data/spec/unit/persistence_spec.rb +122 -122
- data/spec/unit/properties_spec.rb +466 -16
- data/spec/unit/property_protection_spec.rb +32 -32
- data/spec/unit/property_spec.rb +45 -436
- data/spec/unit/proxyable_spec.rb +140 -82
- data/spec/unit/subclass_spec.rb +14 -14
- data/spec/unit/translations_spec.rb +5 -5
- data/spec/unit/typecast_spec.rb +131 -131
- data/spec/unit/utils/migrate_spec.rb +2 -2
- data/spec/unit/validations_spec.rb +31 -31
- metadata +27 -12
- data/lib/couchrest/model/casted_hash.rb +0 -84
data/spec/unit/design_spec.rb
CHANGED
@@ -31,11 +31,11 @@ describe CouchRest::Model::Design do
|
|
31
31
|
|
32
32
|
describe ".method_name" do
|
33
33
|
it "should return standard method name" do
|
34
|
-
@klass.method_name.
|
34
|
+
expect(@klass.method_name).to eql('design_doc')
|
35
35
|
end
|
36
36
|
|
37
37
|
it "should add prefix to standard method name" do
|
38
|
-
@klass.method_name('stats').
|
38
|
+
expect(@klass.method_name('stats')).to eql('stats_design_doc')
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -45,23 +45,23 @@ describe CouchRest::Model::Design do
|
|
45
45
|
|
46
46
|
before :each do
|
47
47
|
@model = double("ModelExample")
|
48
|
-
@model.
|
48
|
+
allow(@model).to receive(:to_s).and_return("ModelExample")
|
49
49
|
@obj = CouchRest::Model::Design.new(@model)
|
50
50
|
end
|
51
51
|
|
52
52
|
|
53
53
|
describe "initialisation without prefix" do
|
54
54
|
it "should associate model and set method name" do
|
55
|
-
@obj.model.
|
56
|
-
@obj.method_name.
|
55
|
+
expect(@obj.model).to eql(@model)
|
56
|
+
expect(@obj.method_name).to eql("design_doc")
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should generate correct id" do
|
60
|
-
@obj['_id'].
|
60
|
+
expect(@obj['_id']).to eql("_design/ModelExample")
|
61
61
|
end
|
62
62
|
|
63
63
|
it "should apply defaults" do
|
64
|
-
@obj['language'].
|
64
|
+
expect(@obj['language']).to eql('javascript')
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
@@ -69,13 +69,13 @@ describe CouchRest::Model::Design do
|
|
69
69
|
|
70
70
|
it "should associate model and set method name" do
|
71
71
|
@obj = CouchRest::Model::Design.new(@model, 'stats')
|
72
|
-
@obj.model.
|
73
|
-
@obj.method_name.
|
72
|
+
expect(@obj.model).to eql(@model)
|
73
|
+
expect(@obj.method_name).to eql("stats_design_doc")
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should generate correct id with prefix" do
|
77
77
|
@obj = CouchRest::Model::Design.new(@model, 'stats')
|
78
|
-
@obj['_id'].
|
78
|
+
expect(@obj['_id']).to eql("_design/ModelExample_stats")
|
79
79
|
end
|
80
80
|
|
81
81
|
end
|
@@ -86,7 +86,7 @@ describe CouchRest::Model::Design do
|
|
86
86
|
|
87
87
|
it "should skip if auto update disabled" do
|
88
88
|
@obj.auto_update = false
|
89
|
-
@obj.
|
89
|
+
expect(@obj).not_to receive(:sync!)
|
90
90
|
@obj.sync
|
91
91
|
end
|
92
92
|
|
@@ -110,28 +110,28 @@ describe CouchRest::Model::Design do
|
|
110
110
|
# This would fail if changes were not detected!
|
111
111
|
@doc.sync
|
112
112
|
doc = @db.get(@doc['_id'])
|
113
|
-
doc['views']['all']['map'].
|
113
|
+
expect(doc['views']['all']['map']).to eql(@doc['views']['all']['map'])
|
114
114
|
end
|
115
115
|
|
116
116
|
it "should not save a design that is not in cache and has not changed" do
|
117
117
|
@doc.sync # put doc in cache
|
118
118
|
@doc.send(:set_cache_checksum, @doc.database, nil)
|
119
119
|
|
120
|
-
@db.
|
121
|
-
@doc.
|
120
|
+
expect(@db).not_to receive(:save_doc)
|
121
|
+
expect(@doc).to receive(:set_cache_checksum)
|
122
122
|
@doc.sync
|
123
123
|
end
|
124
124
|
|
125
125
|
it "should not reload a design that is in cache and has not changed" do
|
126
126
|
@doc.sync
|
127
|
-
@doc.
|
127
|
+
expect(@doc).not_to receive(:load_from_database)
|
128
128
|
@doc.sync
|
129
129
|
end
|
130
130
|
|
131
131
|
it "should be re-created if database destroyed" do
|
132
132
|
@doc.sync # saved
|
133
133
|
reset_test_db!
|
134
|
-
@db.
|
134
|
+
expect(@db).to receive(:save_doc).with(@doc)
|
135
135
|
@doc.sync
|
136
136
|
end
|
137
137
|
|
@@ -142,8 +142,8 @@ describe CouchRest::Model::Design do
|
|
142
142
|
@db.save_doc(doc)
|
143
143
|
@doc.send(:set_cache_checksum, @doc.database, nil)
|
144
144
|
@doc.sync
|
145
|
-
@doc['views'].
|
146
|
-
@doc['_rev'].
|
145
|
+
expect(@doc['views']).not_to have_key('test')
|
146
|
+
expect(@doc['_rev']).to be_nil
|
147
147
|
end
|
148
148
|
|
149
149
|
it "should save a non existant design" do
|
@@ -155,8 +155,8 @@ describe CouchRest::Model::Design do
|
|
155
155
|
@db.delete_doc(doc) if doc
|
156
156
|
@doc.sync!
|
157
157
|
doc = @db.get(@doc['_id'])
|
158
|
-
doc.
|
159
|
-
doc['views']['all'].
|
158
|
+
expect(doc).not_to be_nil
|
159
|
+
expect(doc['views']['all']).to eql(@doc['views']['all'])
|
160
160
|
end
|
161
161
|
|
162
162
|
end
|
@@ -172,19 +172,19 @@ describe CouchRest::Model::Design do
|
|
172
172
|
end
|
173
173
|
|
174
174
|
it "should return fresh checksum when not calculated earlier" do
|
175
|
-
@doc.checksum.
|
175
|
+
expect(@doc.checksum).not_to be_blank
|
176
176
|
end
|
177
177
|
|
178
178
|
it "should provide same checksum without refresh on re-request" do
|
179
179
|
chk = @doc.checksum
|
180
|
-
@doc.
|
181
|
-
@doc.checksum.
|
180
|
+
expect(@doc).not_to receive(:checksum!)
|
181
|
+
expect(@doc.checksum).to eql(chk)
|
182
182
|
end
|
183
183
|
|
184
184
|
it "should provide new checksum if the design has changed" do
|
185
185
|
chk = @doc.checksum
|
186
186
|
@doc['views']['all']['map'] += '// comment'
|
187
|
-
@doc.checksum.
|
187
|
+
expect(@doc.checksum).not_to eql(chk)
|
188
188
|
end
|
189
189
|
|
190
190
|
end
|
@@ -193,7 +193,7 @@ describe CouchRest::Model::Design do
|
|
193
193
|
it "should provide model's database" do
|
194
194
|
@mod = DesignSampleModel
|
195
195
|
@doc = @mod.design_doc
|
196
|
-
@mod.
|
196
|
+
expect(@mod).to receive(:database)
|
197
197
|
@doc.database
|
198
198
|
end
|
199
199
|
end
|
@@ -202,13 +202,13 @@ describe CouchRest::Model::Design do
|
|
202
202
|
describe "#uri" do
|
203
203
|
it "should provide complete url" do
|
204
204
|
@doc = DesignSampleModel.design_doc
|
205
|
-
@doc.uri.
|
205
|
+
expect(@doc.uri).to eql("#{DesignSampleModel.database.root}/_design/DesignSampleModel")
|
206
206
|
end
|
207
207
|
end
|
208
208
|
|
209
209
|
describe "#view" do
|
210
210
|
it "should instantiate a new view and pass options" do
|
211
|
-
CouchRest::Model::Designs::View.
|
211
|
+
expect(CouchRest::Model::Designs::View).to receive(:new).with(@obj, @model, {}, 'by_test')
|
212
212
|
@obj.view('by_test', {})
|
213
213
|
end
|
214
214
|
end
|
@@ -216,7 +216,7 @@ describe CouchRest::Model::Design do
|
|
216
216
|
describe "#view_names" do
|
217
217
|
it "should provide a list of all the views available" do
|
218
218
|
@doc = DesignSampleModel.design_doc
|
219
|
-
@doc.view_names.
|
219
|
+
expect(@doc.view_names).to eql(['by_name', 'all'])
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
@@ -226,15 +226,15 @@ describe CouchRest::Model::Design do
|
|
226
226
|
end
|
227
227
|
|
228
228
|
it "should tell us if a view exists" do
|
229
|
-
@doc.has_view?('by_name').
|
229
|
+
expect(@doc.has_view?('by_name')).to be_truthy
|
230
230
|
end
|
231
231
|
|
232
232
|
it "should tell us if a view exists as symbol" do
|
233
|
-
@doc.has_view?(:by_name).
|
233
|
+
expect(@doc.has_view?(:by_name)).to be_truthy
|
234
234
|
end
|
235
235
|
|
236
236
|
it "should tell us if a view does not exist" do
|
237
|
-
@doc.has_view?(:by_foobar).
|
237
|
+
expect(@doc.has_view?(:by_foobar)).to be_falsey
|
238
238
|
end
|
239
239
|
end
|
240
240
|
|
@@ -245,12 +245,12 @@ describe CouchRest::Model::Design do
|
|
245
245
|
end
|
246
246
|
|
247
247
|
it "should forward view creation to View model" do
|
248
|
-
CouchRest::Model::Designs::View.
|
248
|
+
expect(CouchRest::Model::Designs::View).to receive(:define_and_create).with(@doc, 'by_other_name', {})
|
249
249
|
@doc.create_view('by_other_name')
|
250
250
|
end
|
251
251
|
|
252
252
|
it "should forward view creation to View model with opts" do
|
253
|
-
CouchRest::Model::Designs::View.
|
253
|
+
expect(CouchRest::Model::Designs::View).to receive(:define_and_create).with(@doc, 'by_other_name', {:by => 'name'})
|
254
254
|
@doc.create_view('by_other_name', :by => 'name')
|
255
255
|
end
|
256
256
|
end
|
@@ -263,7 +263,7 @@ describe CouchRest::Model::Design do
|
|
263
263
|
|
264
264
|
it "should add simple filter" do
|
265
265
|
@doc.create_filter('test', 'foobar')
|
266
|
-
@doc['filters']['test'].
|
266
|
+
expect(@doc['filters']['test']).to eql('foobar')
|
267
267
|
@doc['filters'] = nil # cleanup
|
268
268
|
end
|
269
269
|
end
|
@@ -275,7 +275,7 @@ describe CouchRest::Model::Design do
|
|
275
275
|
|
276
276
|
it "should add simple view lib" do
|
277
277
|
@doc.create_view_lib('test', 'foobar')
|
278
|
-
@doc['views']['lib']['test'].
|
278
|
+
expect(@doc['views']['lib']['test']).to eql('foobar')
|
279
279
|
@doc['views']['lib'] = nil # cleanup
|
280
280
|
end
|
281
281
|
end
|
@@ -286,17 +286,17 @@ describe CouchRest::Model::Design do
|
|
286
286
|
|
287
287
|
it "should calculate a consistent checksum for model" do
|
288
288
|
#WithTemplateAndUniqueID.design_doc.checksum.should eql('caa2b4c27abb82b4e37421de76d96ffc')
|
289
|
-
WithTemplateAndUniqueID.design_doc.checksum.
|
289
|
+
expect(WithTemplateAndUniqueID.design_doc.checksum).to eql('7f44e88afbce06204010c49b76f31bcf')
|
290
290
|
end
|
291
291
|
|
292
292
|
it "should calculate checksum for complex model" do
|
293
293
|
#Article.design_doc.checksum.should eql('70dff8caea143bf40fad09adf0701104')
|
294
|
-
Article.design_doc.checksum.
|
294
|
+
expect(Article.design_doc.checksum).to eql('81f6553c44ecc3fe12a39331b0cdee46')
|
295
295
|
end
|
296
296
|
|
297
297
|
it "should cache the generated checksum value" do
|
298
298
|
Article.design_doc.checksum
|
299
|
-
Article.design_doc['couchrest-hash'].
|
299
|
+
expect(Article.design_doc['couchrest-hash']).not_to be_blank
|
300
300
|
Article.first
|
301
301
|
end
|
302
302
|
|
@@ -15,22 +15,22 @@ describe CouchRest::Model::Designs::DesignMapper do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should set basic variables" do
|
18
|
-
@object.send(:model).
|
19
|
-
@object.send(:prefix).
|
20
|
-
@object.send(:method).
|
18
|
+
expect(@object.send(:model)).to eql(DesignModel)
|
19
|
+
expect(@object.send(:prefix)).to be_nil
|
20
|
+
expect(@object.send(:method)).to eql('design_doc')
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should add design doc to list" do
|
24
|
-
@object.model.design_docs.
|
24
|
+
expect(@object.model.design_docs).to include(@object.model.design_doc)
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should create a design doc method" do
|
28
|
-
@object.model.
|
29
|
-
@object.design_doc.
|
28
|
+
expect(@object.model).to respond_to('design_doc')
|
29
|
+
expect(@object.design_doc).to eql(@object.model.design_doc)
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should use default for autoupdate" do
|
33
|
-
@object.design_doc.auto_update.
|
33
|
+
expect(@object.design_doc.auto_update).to be_truthy
|
34
34
|
end
|
35
35
|
|
36
36
|
end
|
@@ -41,22 +41,22 @@ describe CouchRest::Model::Designs::DesignMapper do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should set basics" do
|
44
|
-
@object.send(:model).
|
45
|
-
@object.send(:prefix).
|
46
|
-
@object.send(:method).
|
44
|
+
expect(@object.send(:model)).to eql(DesignModel)
|
45
|
+
expect(@object.send(:prefix)).to eql('stats')
|
46
|
+
expect(@object.send(:method)).to eql('stats_design_doc')
|
47
47
|
end
|
48
48
|
|
49
49
|
it "should add design doc to list" do
|
50
|
-
@object.model.design_docs.
|
50
|
+
expect(@object.model.design_docs).to include(@object.model.stats_design_doc)
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should not create an all method" do
|
54
|
-
@object.model.
|
54
|
+
expect(@object.model).not_to respond_to('all')
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should create a design doc method" do
|
58
|
-
@object.model.
|
59
|
-
@object.design_doc.
|
58
|
+
expect(@object.model).to respond_to('stats_design_doc')
|
59
|
+
expect(@object.design_doc).to eql(@object.model.stats_design_doc)
|
60
60
|
end
|
61
61
|
|
62
62
|
end
|
@@ -65,7 +65,7 @@ describe CouchRest::Model::Designs::DesignMapper do
|
|
65
65
|
it "should disable auto updates" do
|
66
66
|
@object = @klass.new(DesignModel)
|
67
67
|
@object.disable_auto_update
|
68
|
-
@object.design_doc.auto_update.
|
68
|
+
expect(@object.design_doc.auto_update).to be_falsey
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -73,14 +73,14 @@ describe CouchRest::Model::Designs::DesignMapper do
|
|
73
73
|
it "should enable auto updates" do
|
74
74
|
@object = @klass.new(DesignModel)
|
75
75
|
@object.enable_auto_update
|
76
|
-
@object.design_doc.auto_update.
|
76
|
+
expect(@object.design_doc.auto_update).to be_truthy
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
80
|
describe "#model_type_key" do
|
81
81
|
it "should return models type key" do
|
82
82
|
@object = @klass.new(DesignModel)
|
83
|
-
@object.model_type_key.
|
83
|
+
expect(@object.model_type_key).to eql(@object.model.model_type_key)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -91,18 +91,18 @@ describe CouchRest::Model::Designs::DesignMapper do
|
|
91
91
|
end
|
92
92
|
|
93
93
|
it "should call create method on view" do
|
94
|
-
CouchRest::Model::Designs::View.
|
94
|
+
expect(CouchRest::Model::Designs::View).to receive(:define).with(@object.design_doc, 'test', {})
|
95
95
|
@object.view('test')
|
96
96
|
end
|
97
97
|
|
98
98
|
it "should create a method on parent model" do
|
99
|
-
CouchRest::Model::Designs::View.
|
99
|
+
allow(CouchRest::Model::Designs::View).to receive(:define)
|
100
100
|
@object.view('test_view')
|
101
|
-
DesignModel.
|
101
|
+
expect(DesignModel).to respond_to(:test_view)
|
102
102
|
end
|
103
103
|
|
104
104
|
it "should create a method for view instance" do
|
105
|
-
@object.design_doc.
|
105
|
+
expect(@object.design_doc).to receive(:create_view).with('test', {})
|
106
106
|
@object.view('test')
|
107
107
|
end
|
108
108
|
end
|
@@ -115,8 +115,8 @@ describe CouchRest::Model::Designs::DesignMapper do
|
|
115
115
|
|
116
116
|
it "should add the provided function to the design doc" do
|
117
117
|
@object.filter(:important, "function(doc, req) { return doc.priority == 'high'; }")
|
118
|
-
DesignModel.design_doc['filters'].
|
119
|
-
DesignModel.design_doc['filters']['important'].
|
118
|
+
expect(DesignModel.design_doc['filters']).not_to be_empty
|
119
|
+
expect(DesignModel.design_doc['filters']['important']).not_to be_blank
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
@@ -128,9 +128,9 @@ describe CouchRest::Model::Designs::DesignMapper do
|
|
128
128
|
it "should add the #view_lib function to the design doc" do
|
129
129
|
val = "exports.bar = 42;"
|
130
130
|
@object.view_lib(:foo, val)
|
131
|
-
DesignModel.design_doc['views']['lib'].
|
132
|
-
DesignModel.design_doc['views']['lib'].
|
133
|
-
DesignModel.design_doc['views']['lib']['foo'].
|
131
|
+
expect(DesignModel.design_doc['views']['lib']).not_to be_empty
|
132
|
+
expect(DesignModel.design_doc['views']['lib']).not_to be_blank
|
133
|
+
expect(DesignModel.design_doc['views']['lib']['foo']).to eql(val)
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
@@ -34,24 +34,24 @@ describe CouchRest::Model::Designs::Migrations do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should create new design if non exists" do
|
37
|
-
@db.
|
37
|
+
expect(@db).to receive(:view).with("#{@doc.name}/#{@doc['views'].keys.first}", {
|
38
38
|
:limit => 1, :stale => 'update_after', :reduce => false
|
39
39
|
})
|
40
40
|
callback = @doc.migrate do |res|
|
41
|
-
res.
|
41
|
+
expect(res).to eql(:created)
|
42
42
|
end
|
43
43
|
doc = @db.get(@doc['_id'])
|
44
|
-
doc['views']['all'].
|
45
|
-
callback.
|
44
|
+
expect(doc['views']['all']).to eql(@doc['views']['all'])
|
45
|
+
expect(callback).to be_nil
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should not change anything if design is up to date" do
|
49
49
|
@doc.sync
|
50
|
-
@db.
|
50
|
+
expect(@db).not_to receive(:view)
|
51
51
|
callback = @doc.migrate do |res|
|
52
|
-
res.
|
52
|
+
expect(res).to eql(:no_change)
|
53
53
|
end
|
54
|
-
callback.
|
54
|
+
expect(callback).to be_nil
|
55
55
|
end
|
56
56
|
|
57
57
|
end
|
@@ -72,28 +72,28 @@ describe CouchRest::Model::Designs::Migrations do
|
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should save new migration design doc" do
|
75
|
-
@db.
|
75
|
+
expect(@db).to receive(:view).with("#{@doc.name}_migration/by_name", {
|
76
76
|
:limit => 1, :reduce => false, :stale => 'update_after'
|
77
77
|
})
|
78
78
|
@callback = @doc.migrate do |res|
|
79
|
-
res.
|
79
|
+
expect(res).to eql(:migrated)
|
80
80
|
end
|
81
|
-
@callback.
|
81
|
+
expect(@callback).not_to be_nil
|
82
82
|
|
83
83
|
# should not have updated original view until cleanup
|
84
84
|
doc = @db.get(@doc['_id'])
|
85
|
-
doc['views'].
|
85
|
+
expect(doc['views']).not_to have_key('by_name_and_surname')
|
86
86
|
|
87
87
|
# Should have created the migration
|
88
88
|
new_doc = @db.get(@doc_id)
|
89
|
-
new_doc.
|
89
|
+
expect(new_doc).not_to be_nil
|
90
90
|
|
91
91
|
# should be possible to perform cleanup
|
92
92
|
@callback.call
|
93
93
|
expect(@db.get(@doc_id)).to be_nil
|
94
94
|
|
95
95
|
doc = @db.get(@doc['_id'])
|
96
|
-
doc['views'].
|
96
|
+
expect(doc['views']).to have_key('by_name_and_surname')
|
97
97
|
end
|
98
98
|
|
99
99
|
end
|
@@ -24,7 +24,7 @@ describe "Design View" do
|
|
24
24
|
|
25
25
|
describe "with invalid parent model" do
|
26
26
|
it "should burn" do
|
27
|
-
|
27
|
+
expect { @klass.new(String, nil) }.to raise_error(/View cannot be initialized without a parent Model/)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -32,14 +32,14 @@ describe "Design View" do
|
|
32
32
|
|
33
33
|
it "should setup attributes" do
|
34
34
|
@obj = @klass.new(@mod.design_doc, @mod, {}, 'test_view')
|
35
|
-
@obj.design_doc.
|
36
|
-
@obj.model.
|
37
|
-
@obj.name.
|
38
|
-
@obj.query.
|
35
|
+
expect(@obj.design_doc).to eql(@mod.design_doc)
|
36
|
+
expect(@obj.model).to eql(@mod)
|
37
|
+
expect(@obj.name).to eql('test_view')
|
38
|
+
expect(@obj.query).to be_empty
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should complain if there is no name" do
|
42
|
-
|
42
|
+
expect { @klass.new(@mod.design_doc, @mod, {}, nil) }.to raise_error(/Name must be provided/)
|
43
43
|
end
|
44
44
|
|
45
45
|
end
|
@@ -52,14 +52,14 @@ describe "Design View" do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
it "should copy attributes" do
|
55
|
-
@obj.model.
|
56
|
-
@obj.name.
|
57
|
-
@obj.query.
|
55
|
+
expect(@obj.model).to eql(@mod)
|
56
|
+
expect(@obj.name).to eql('test_view')
|
57
|
+
expect(@obj.query).to eql({:foo => :bar})
|
58
58
|
end
|
59
59
|
|
60
60
|
it "should delete query keys if :delete defined" do
|
61
61
|
@obj2 = @klass.new(@mod.design_doc, @obj, {:delete => [:foo]})
|
62
|
-
@obj2.query.
|
62
|
+
expect(@obj2.query).not_to include(:foo)
|
63
63
|
end
|
64
64
|
|
65
65
|
end
|
@@ -68,7 +68,7 @@ describe "Design View" do
|
|
68
68
|
it "should set model to proxy object and remove from query" do
|
69
69
|
proxy = double("Proxy")
|
70
70
|
@obj = @klass.new(@mod.design_doc, @mod, {:proxy => proxy}, 'test_view')
|
71
|
-
@obj.model.
|
71
|
+
expect(@obj.model).to eql(proxy)
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
@@ -76,9 +76,9 @@ describe "Design View" do
|
|
76
76
|
it "should set the model to proxy object instead of parents model" do
|
77
77
|
proxy = double("Proxy")
|
78
78
|
@obj = @klass.new(@mod.design_doc, @mod, {}, 'test_view')
|
79
|
-
@obj.model.
|
79
|
+
expect(@obj.model).to eql(@mod)
|
80
80
|
@obj = @obj.proxy(proxy)
|
81
|
-
@obj.model.
|
81
|
+
expect(@obj.model).to eql(proxy)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -90,14 +90,14 @@ describe "Design View" do
|
|
90
90
|
end
|
91
91
|
|
92
92
|
it "should call define and create_model_methods method" do
|
93
|
-
@klass.
|
94
|
-
@klass.
|
93
|
+
expect(@klass).to receive(:define).with(@design_doc, 'test', {}).and_return(nil)
|
94
|
+
expect(@klass).to receive(:create_model_methods).with(@design_doc, 'test', {}).and_return(nil)
|
95
95
|
@klass.define_and_create(@design_doc, 'test')
|
96
96
|
end
|
97
97
|
|
98
98
|
it "should call define and create_model_methods method with opts" do
|
99
|
-
@klass.
|
100
|
-
@klass.
|
99
|
+
expect(@klass).to receive(:define).with(@design_doc, 'test', {:foo => :bar}).and_return(nil)
|
100
|
+
expect(@klass).to receive(:create_model_methods).with(@design_doc, 'test', {:foo => :bar}).and_return(nil)
|
101
101
|
@klass.define_and_create(@design_doc, 'test', {:foo => :bar})
|
102
102
|
end
|
103
103
|
|
@@ -109,53 +109,71 @@ describe "Design View" do
|
|
109
109
|
|
110
110
|
before :each do
|
111
111
|
@design_doc = { }
|
112
|
-
@design_doc.
|
112
|
+
allow(@design_doc).to receive(:model).and_return(DesignViewModel)
|
113
113
|
end
|
114
114
|
|
115
115
|
it "should add a basic view" do
|
116
116
|
@klass.define(@design_doc, 'test_view', :map => 'foo')
|
117
|
-
@design_doc['views']['test_view'].
|
117
|
+
expect(@design_doc['views']['test_view']).not_to be_nil
|
118
118
|
end
|
119
119
|
|
120
120
|
it "should not overwrite reduce if set" do
|
121
121
|
@klass.define(@design_doc, 'by_title', :reduce => true)
|
122
|
-
@design_doc['views']['by_title']['map'].
|
123
|
-
@design_doc['views']['by_title']['reduce'].
|
122
|
+
expect(@design_doc['views']['by_title']['map']).not_to be_blank
|
123
|
+
expect(@design_doc['views']['by_title']['reduce']).to eql(true)
|
124
124
|
end
|
125
125
|
|
126
126
|
it "should replace reduce symbol with string name" do
|
127
127
|
@klass.define(@design_doc, 'by_title', :reduce => :sum)
|
128
|
-
@design_doc['views']['by_title']['map'].
|
129
|
-
@design_doc['views']['by_title']['reduce'].
|
128
|
+
expect(@design_doc['views']['by_title']['map']).not_to be_blank
|
129
|
+
expect(@design_doc['views']['by_title']['reduce']).to eql('_sum')
|
130
130
|
end
|
131
131
|
|
132
132
|
it "should replace reduce symbol with string if map function present" do
|
133
133
|
@klass.define(@design_doc, 'by_title', :map => "function(d) { }", :reduce => :sum)
|
134
|
-
@design_doc['views']['by_title']['map'].
|
135
|
-
@design_doc['views']['by_title']['reduce'].
|
134
|
+
expect(@design_doc['views']['by_title']['map']).not_to be_blank
|
135
|
+
expect(@design_doc['views']['by_title']['reduce']).to eql('_sum')
|
136
136
|
end
|
137
137
|
|
138
138
|
it "should auto generate mapping from name" do
|
139
|
-
|
139
|
+
expect { @klass.define(@design_doc, 'by_title') }.not_to raise_error
|
140
140
|
str = @design_doc['views']['by_title']['map']
|
141
|
-
str.
|
142
|
-
str.
|
141
|
+
expect(str).to include("((doc['#{DesignViewModel.model_type_key}'] == 'DesignViewModel') && (doc['title'] != null))")
|
142
|
+
expect(str).to include("emit(doc['title'], 1);")
|
143
143
|
str = @design_doc['views']['by_title']['reduce']
|
144
|
-
str.
|
144
|
+
expect(str).to include("_sum")
|
145
145
|
end
|
146
146
|
|
147
147
|
it "should auto generate mapping from name with and" do
|
148
148
|
@klass.define(@design_doc, 'by_title_and_name')
|
149
149
|
str = @design_doc['views']['by_title_and_name']['map']
|
150
|
-
str.
|
151
|
-
str.
|
150
|
+
expect(str).to include("(doc['title'] != null) && (doc['name'] != null)")
|
151
|
+
expect(str).to include("emit([doc['title'], doc['name']], 1);")
|
152
152
|
str = @design_doc['views']['by_title_and_name']['reduce']
|
153
|
-
str.
|
153
|
+
expect(str).to include("_sum")
|
154
154
|
end
|
155
155
|
|
156
156
|
it "should allow reduce methods as symbols" do
|
157
157
|
@klass.define(@design_doc, 'by_title', :reduce => :stats)
|
158
|
-
@design_doc['views']['by_title']['reduce'].
|
158
|
+
expect(@design_doc['views']['by_title']['reduce']).to eql('_stats')
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should allow the emit value to be overridden" do
|
162
|
+
@klass.define(@design_doc, 'by_title', :emit => :name)
|
163
|
+
str = @design_doc['views']['by_title']['map']
|
164
|
+
expect(str).to include("emit(doc['title'], doc['name']);")
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should forward a non-symbol emit value straight into the view" do
|
168
|
+
@klass.define(@design_doc, 'by_title', :emit => 3)
|
169
|
+
str = @design_doc['views']['by_title']['map']
|
170
|
+
expect(str).to include("emit(doc['title'], 3);")
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should support emitting an array" do
|
174
|
+
@klass.define(@design_doc, 'by_title', :emit => [1, :name])
|
175
|
+
str = @design_doc['views']['by_title']['map']
|
176
|
+
expect(str).to include("emit(doc['title'], [1, doc['name']]);")
|
159
177
|
end
|
160
178
|
end
|
161
179
|
|
@@ -163,42 +181,42 @@ describe "Design View" do
|
|
163
181
|
before :each do
|
164
182
|
@model = DesignViewModel
|
165
183
|
@design_doc = { }
|
166
|
-
@design_doc.
|
167
|
-
@design_doc.
|
168
|
-
@model.
|
184
|
+
allow(@design_doc).to receive(:model).and_return(@model)
|
185
|
+
allow(@design_doc).to receive(:method_name).and_return("design_doc")
|
186
|
+
allow(@model).to receive('design_doc').and_return(@design_doc)
|
169
187
|
end
|
170
188
|
it "should create standard view method" do
|
171
189
|
@klass.create_model_methods(@design_doc, 'by_name')
|
172
|
-
@model.
|
173
|
-
@design_doc.
|
190
|
+
expect(@model).to respond_to('by_name')
|
191
|
+
expect(@design_doc).to receive('view').with('by_name', {})
|
174
192
|
@model.by_name
|
175
193
|
end
|
176
194
|
it "should create find_ view method" do
|
177
195
|
@klass.create_model_methods(@design_doc, 'by_name')
|
178
|
-
@model.
|
196
|
+
expect(@model).to respond_to('find_by_name')
|
179
197
|
view = double("View")
|
180
|
-
view.
|
181
|
-
view.
|
182
|
-
@design_doc.
|
198
|
+
expect(view).to receive('key').with('fred').and_return(view)
|
199
|
+
expect(view).to receive('first').and_return(nil)
|
200
|
+
expect(@design_doc).to receive('view').and_return(view)
|
183
201
|
@model.find_by_name('fred')
|
184
202
|
end
|
185
203
|
it "should create find_! view method" do
|
186
204
|
@klass.create_model_methods(@design_doc, 'by_name')
|
187
|
-
@model.
|
205
|
+
expect(@model).to respond_to('find_by_name!')
|
188
206
|
obj = double("SomeKlass")
|
189
207
|
view = double("View")
|
190
|
-
view.
|
191
|
-
view.
|
192
|
-
@design_doc.
|
193
|
-
@model.find_by_name!('fred').
|
208
|
+
expect(view).to receive('key').with('fred').and_return(view)
|
209
|
+
expect(view).to receive('first').and_return(obj)
|
210
|
+
expect(@design_doc).to receive('view').and_return(view)
|
211
|
+
expect(@model.find_by_name!('fred')).to eql(obj)
|
194
212
|
end
|
195
213
|
it "should create find_! view method and raise error when nil" do
|
196
214
|
@klass.create_model_methods(@design_doc, 'by_name')
|
197
215
|
view = double("View")
|
198
|
-
view.
|
199
|
-
view.
|
200
|
-
@design_doc.
|
201
|
-
|
216
|
+
expect(view).to receive('key').with('fred').and_return(view)
|
217
|
+
expect(view).to receive('first').and_return(nil)
|
218
|
+
expect(@design_doc).to receive('view').and_return(view)
|
219
|
+
expect { @model.find_by_name!('fred') }.to raise_error(CouchRest::Model::DocumentNotFound)
|
202
220
|
end
|
203
221
|
|
204
222
|
end
|
@@ -213,15 +231,15 @@ describe "Design View" do
|
|
213
231
|
|
214
232
|
describe "#rows" do
|
215
233
|
it "should execute query" do
|
216
|
-
@obj.
|
217
|
-
@obj.
|
218
|
-
@obj.rows.
|
234
|
+
expect(@obj).to receive(:execute).and_return(true)
|
235
|
+
expect(@obj).to receive(:result).twice.and_return({'rows' => []})
|
236
|
+
expect(@obj.rows).to be_empty
|
219
237
|
end
|
220
238
|
|
221
239
|
it "should wrap rows in ViewRow class" do
|
222
|
-
@obj.
|
223
|
-
@obj.
|
224
|
-
CouchRest::Model::Designs::ViewRow.
|
240
|
+
expect(@obj).to receive(:execute).and_return(true)
|
241
|
+
expect(@obj).to receive(:result).twice.and_return({'rows' => [{:foo => :bar}]})
|
242
|
+
expect(CouchRest::Model::Designs::ViewRow).to receive(:new).with({:foo => :bar}, @obj.model, DB)
|
225
243
|
@obj.rows
|
226
244
|
end
|
227
245
|
|
@@ -250,24 +268,24 @@ describe "Design View" do
|
|
250
268
|
|
251
269
|
describe "#all" do
|
252
270
|
it "should ensure docs included and call docs" do
|
253
|
-
@obj.
|
254
|
-
@obj.
|
271
|
+
expect(@obj).to receive(:include_docs!)
|
272
|
+
expect(@obj).to receive(:docs)
|
255
273
|
@obj.all
|
256
274
|
end
|
257
275
|
it "should pass on a block" do
|
258
|
-
block = lambda { }
|
259
|
-
expect(@obj).to receive(:docs).
|
260
|
-
@obj.all(&block)
|
276
|
+
block = lambda { 'ok' }
|
277
|
+
expect(@obj).to receive(:docs) { block.call() }
|
278
|
+
expect(@obj.all(&block)).to eql('ok')
|
261
279
|
end
|
262
280
|
end
|
263
281
|
|
264
282
|
describe "#docs" do
|
265
283
|
it "should provide docs from rows" do
|
266
|
-
@obj.
|
284
|
+
expect(@obj).to receive(:rows).and_return([])
|
267
285
|
@obj.docs
|
268
286
|
end
|
269
287
|
it "should cache the results" do
|
270
|
-
@obj.
|
288
|
+
expect(@obj).to receive(:rows).once.and_return([])
|
271
289
|
@obj.docs
|
272
290
|
@obj.docs
|
273
291
|
end
|
@@ -296,369 +314,369 @@ describe "Design View" do
|
|
296
314
|
|
297
315
|
describe "#first" do
|
298
316
|
it "should provide the first result of loaded query" do
|
299
|
-
@obj.
|
300
|
-
@obj.
|
301
|
-
@obj.first.
|
317
|
+
expect(@obj).to receive(:result).and_return(true)
|
318
|
+
expect(@obj).to receive(:all).and_return([:foo])
|
319
|
+
expect(@obj.first).to eql(:foo)
|
302
320
|
end
|
303
321
|
it "should perform a query if no results cached" do
|
304
322
|
view = double('SubView')
|
305
|
-
@obj.
|
306
|
-
@obj.
|
307
|
-
view.
|
308
|
-
@obj.first.
|
323
|
+
expect(@obj).to receive(:result).and_return(nil)
|
324
|
+
expect(@obj).to receive(:limit).with(1).and_return(view)
|
325
|
+
expect(view).to receive(:all).and_return([:foo])
|
326
|
+
expect(@obj.first).to eql(:foo)
|
309
327
|
end
|
310
328
|
end
|
311
329
|
|
312
330
|
describe "#last" do
|
313
331
|
it "should provide the last result of loaded query" do
|
314
|
-
@obj.
|
315
|
-
@obj.
|
316
|
-
@obj.first.
|
332
|
+
expect(@obj).to receive(:result).and_return(true)
|
333
|
+
expect(@obj).to receive(:all).and_return([:foo, :bar])
|
334
|
+
expect(@obj.first).to eql(:foo)
|
317
335
|
end
|
318
336
|
it "should perform a query if no results cached" do
|
319
337
|
view = double('SubView')
|
320
|
-
@obj.
|
321
|
-
@obj.
|
322
|
-
view.
|
323
|
-
view.
|
324
|
-
@obj.last.
|
338
|
+
expect(@obj).to receive(:result).and_return(nil)
|
339
|
+
expect(@obj).to receive(:limit).with(1).and_return(view)
|
340
|
+
expect(view).to receive(:descending).and_return(view)
|
341
|
+
expect(view).to receive(:all).and_return([:foo, :bar])
|
342
|
+
expect(@obj.last).to eql(:bar)
|
325
343
|
end
|
326
344
|
end
|
327
345
|
|
328
346
|
describe "#length" do
|
329
347
|
it "should provide a length from the docs array" do
|
330
|
-
@obj.
|
331
|
-
@obj.length.
|
348
|
+
expect(@obj).to receive(:docs).and_return([1, 2, 3])
|
349
|
+
expect(@obj.length).to eql(3)
|
332
350
|
end
|
333
351
|
end
|
334
352
|
|
335
353
|
describe "#count" do
|
336
354
|
it "should raise an error if view prepared for group" do
|
337
|
-
@obj.
|
338
|
-
|
355
|
+
expect(@obj).to receive(:query).and_return({:group => true})
|
356
|
+
expect { @obj.count }.to raise_error(/group/)
|
339
357
|
end
|
340
358
|
|
341
359
|
it "should return first row value if reduce possible" do
|
342
360
|
view = double("SubView")
|
343
361
|
row = double("Row")
|
344
|
-
@obj.
|
345
|
-
@obj.
|
346
|
-
view.
|
347
|
-
view.
|
348
|
-
view.
|
349
|
-
row.
|
350
|
-
@obj.count.
|
362
|
+
expect(@obj).to receive(:can_reduce?).and_return(true)
|
363
|
+
expect(@obj).to receive(:reduce).and_return(view)
|
364
|
+
expect(view).to receive(:skip).with(0).and_return(view)
|
365
|
+
expect(view).to receive(:limit).with(1).and_return(view)
|
366
|
+
expect(view).to receive(:rows).and_return([row])
|
367
|
+
expect(row).to receive(:value).and_return(2)
|
368
|
+
expect(@obj.count).to eql(2)
|
351
369
|
end
|
352
370
|
it "should return 0 if no rows and reduce possible" do
|
353
371
|
view = double("SubView")
|
354
|
-
@obj.
|
355
|
-
@obj.
|
356
|
-
view.
|
357
|
-
view.
|
358
|
-
view.
|
359
|
-
@obj.count.
|
372
|
+
expect(@obj).to receive(:can_reduce?).and_return(true)
|
373
|
+
expect(@obj).to receive(:reduce).and_return(view)
|
374
|
+
expect(view).to receive(:skip).with(0).and_return(view)
|
375
|
+
expect(view).to receive(:limit).with(1).and_return(view)
|
376
|
+
expect(view).to receive(:rows).and_return([])
|
377
|
+
expect(@obj.count).to eql(0)
|
360
378
|
end
|
361
379
|
|
362
380
|
it "should perform limit request for total_rows" do
|
363
381
|
view = double("SubView")
|
364
|
-
@obj.
|
365
|
-
view.
|
366
|
-
@obj.
|
367
|
-
@obj.count.
|
382
|
+
expect(@obj).to receive(:limit).with(0).and_return(view)
|
383
|
+
expect(view).to receive(:total_rows).and_return(4)
|
384
|
+
expect(@obj).to receive(:can_reduce?).and_return(false)
|
385
|
+
expect(@obj.count).to eql(4)
|
368
386
|
end
|
369
387
|
end
|
370
388
|
|
371
389
|
describe "#empty?" do
|
372
390
|
it "should check the #all method for any results" do
|
373
391
|
all = double("All")
|
374
|
-
all.
|
375
|
-
@obj.
|
376
|
-
@obj.empty
|
392
|
+
expect(all).to receive(:empty?).and_return('win')
|
393
|
+
expect(@obj).to receive(:all).and_return(all)
|
394
|
+
expect(@obj.empty?).to eql('win')
|
377
395
|
end
|
378
396
|
end
|
379
397
|
|
380
398
|
describe "#each" do
|
381
399
|
it "should call each method on all" do
|
382
|
-
@obj.
|
400
|
+
expect(@obj).to receive(:all).and_return([])
|
383
401
|
@obj.each
|
384
402
|
end
|
385
403
|
it "should call each and pass block" do
|
386
404
|
set = [:foo, :bar]
|
387
|
-
@obj.
|
405
|
+
expect(@obj).to receive(:all).and_return(set)
|
388
406
|
result = []
|
389
407
|
@obj.each do |s|
|
390
408
|
result << s
|
391
409
|
end
|
392
|
-
result.
|
410
|
+
expect(result).to eql(set)
|
393
411
|
end
|
394
412
|
end
|
395
413
|
|
396
414
|
describe "#offset" do
|
397
415
|
it "should excute" do
|
398
|
-
@obj.
|
399
|
-
@obj.offset.
|
416
|
+
expect(@obj).to receive(:execute).and_return({'offset' => 3})
|
417
|
+
expect(@obj.offset).to eql(3)
|
400
418
|
end
|
401
419
|
end
|
402
420
|
|
403
421
|
describe "#total_rows" do
|
404
422
|
it "should excute" do
|
405
|
-
@obj.
|
406
|
-
@obj.total_rows.
|
423
|
+
expect(@obj).to receive(:execute).and_return({'total_rows' => 3})
|
424
|
+
expect(@obj.total_rows).to eql(3)
|
407
425
|
end
|
408
426
|
end
|
409
427
|
|
410
428
|
describe "#values" do
|
411
429
|
it "should request each row and provide value" do
|
412
430
|
row = double("Row")
|
413
|
-
row.
|
414
|
-
@obj.
|
415
|
-
@obj.values.
|
431
|
+
expect(row).to receive(:value).twice.and_return('foo')
|
432
|
+
expect(@obj).to receive(:rows).and_return([row, row])
|
433
|
+
expect(@obj.values).to eql(['foo', 'foo'])
|
416
434
|
end
|
417
435
|
end
|
418
436
|
|
419
437
|
describe "#[]" do
|
420
438
|
it "should execute and provide requested field" do
|
421
|
-
@obj.
|
422
|
-
@obj['total_rows'].
|
439
|
+
expect(@obj).to receive(:execute).and_return({'total_rows' => 2})
|
440
|
+
expect(@obj['total_rows']).to eql(2)
|
423
441
|
end
|
424
442
|
end
|
425
443
|
|
426
444
|
describe "#info" do
|
427
445
|
it "should raise error" do
|
428
|
-
|
446
|
+
expect { @obj.info }.to raise_error(/Not yet implemented/)
|
429
447
|
end
|
430
448
|
end
|
431
449
|
|
432
450
|
describe "#database" do
|
433
451
|
it "should update query with value" do
|
434
|
-
@obj.
|
452
|
+
expect(@obj).to receive(:update_query).with({:database => 'foo'})
|
435
453
|
@obj.database('foo')
|
436
454
|
end
|
437
455
|
end
|
438
456
|
|
439
457
|
describe "#key" do
|
440
458
|
it "should update query with value" do
|
441
|
-
@obj.
|
459
|
+
expect(@obj).to receive(:update_query).with({:key => 'foo'})
|
442
460
|
@obj.key('foo')
|
443
461
|
end
|
444
462
|
it "should raise error if startkey set" do
|
445
463
|
@obj.query[:startkey] = 'bar'
|
446
|
-
|
464
|
+
expect { @obj.key('foo') }.to raise_error(/View#key cannot be used/)
|
447
465
|
end
|
448
466
|
it "should raise error if endkey set" do
|
449
467
|
@obj.query[:endkey] = 'bar'
|
450
|
-
|
468
|
+
expect { @obj.key('foo') }.to raise_error(/View#key cannot be used/)
|
451
469
|
end
|
452
470
|
it "should raise error if both startkey and endkey set" do
|
453
471
|
@obj.query[:startkey] = 'bar'
|
454
472
|
@obj.query[:endkey] = 'bar'
|
455
|
-
|
473
|
+
expect { @obj.key('foo') }.to raise_error(/View#key cannot be used/)
|
456
474
|
end
|
457
475
|
it "should raise error if keys set" do
|
458
476
|
@obj.query[:keys] = 'bar'
|
459
|
-
|
477
|
+
expect { @obj.key('foo') }.to raise_error(/View#key cannot be used/)
|
460
478
|
end
|
461
479
|
end
|
462
480
|
|
463
481
|
describe "#startkey" do
|
464
482
|
it "should update query with value" do
|
465
|
-
@obj.
|
483
|
+
expect(@obj).to receive(:update_query).with({:startkey => 'foo'})
|
466
484
|
@obj.startkey('foo')
|
467
485
|
end
|
468
486
|
it "should raise and error if key set" do
|
469
487
|
@obj.query[:key] = 'bar'
|
470
|
-
|
488
|
+
expect { @obj.startkey('foo') }.to raise_error(/View#startkey/)
|
471
489
|
end
|
472
490
|
it "should raise and error if keys set" do
|
473
491
|
@obj.query[:keys] = 'bar'
|
474
|
-
|
492
|
+
expect { @obj.startkey('foo') }.to raise_error(/View#startkey/)
|
475
493
|
end
|
476
494
|
end
|
477
495
|
|
478
496
|
describe "#startkey_doc" do
|
479
497
|
it "should update query with value" do
|
480
|
-
@obj.
|
498
|
+
expect(@obj).to receive(:update_query).with({:startkey_docid => 'foo'})
|
481
499
|
@obj.startkey_doc('foo')
|
482
500
|
end
|
483
501
|
it "should update query with object id if available" do
|
484
502
|
doc = double("Document")
|
485
|
-
doc.
|
486
|
-
@obj.
|
503
|
+
expect(doc).to receive(:id).and_return(44)
|
504
|
+
expect(@obj).to receive(:update_query).with({:startkey_docid => 44})
|
487
505
|
@obj.startkey_doc(doc)
|
488
506
|
end
|
489
507
|
end
|
490
508
|
|
491
509
|
describe "#endkey" do
|
492
510
|
it "should update query with value" do
|
493
|
-
@obj.
|
511
|
+
expect(@obj).to receive(:update_query).with({:endkey => 'foo'})
|
494
512
|
@obj.endkey('foo')
|
495
513
|
end
|
496
514
|
it "should raise and error if key set" do
|
497
515
|
@obj.query[:key] = 'bar'
|
498
|
-
|
516
|
+
expect { @obj.endkey('foo') }.to raise_error(/View#endkey/)
|
499
517
|
end
|
500
518
|
it "should raise and error if keys set" do
|
501
519
|
@obj.query[:keys] = 'bar'
|
502
|
-
|
520
|
+
expect { @obj.endkey('foo') }.to raise_error(/View#endkey/)
|
503
521
|
end
|
504
522
|
end
|
505
523
|
|
506
524
|
describe "#endkey_doc" do
|
507
525
|
it "should update query with value" do
|
508
|
-
@obj.
|
526
|
+
expect(@obj).to receive(:update_query).with({:endkey_docid => 'foo'})
|
509
527
|
@obj.endkey_doc('foo')
|
510
528
|
end
|
511
529
|
it "should update query with object id if available" do
|
512
530
|
doc = double("Document")
|
513
|
-
doc.
|
514
|
-
@obj.
|
531
|
+
expect(doc).to receive(:id).and_return(44)
|
532
|
+
expect(@obj).to receive(:update_query).with({:endkey_docid => 44})
|
515
533
|
@obj.endkey_doc(doc)
|
516
534
|
end
|
517
535
|
end
|
518
536
|
|
519
537
|
describe "#keys" do
|
520
538
|
it "should update the query" do
|
521
|
-
@obj.
|
539
|
+
expect(@obj).to receive(:update_query).with({:keys => ['foo', 'bar']})
|
522
540
|
@obj.keys(['foo', 'bar'])
|
523
541
|
end
|
524
542
|
it "should raise and error if key set" do
|
525
543
|
@obj.query[:key] = 'bar'
|
526
|
-
|
544
|
+
expect { @obj.keys('foo') }.to raise_error(/View#keys/)
|
527
545
|
end
|
528
546
|
it "should raise and error if startkey or endkey set" do
|
529
547
|
@obj.query[:startkey] = 'bar'
|
530
|
-
|
548
|
+
expect { @obj.keys('foo') }.to raise_error(/View#keys/)
|
531
549
|
@obj.query.delete(:startkey)
|
532
550
|
@obj.query[:endkey] = 'bar'
|
533
|
-
|
551
|
+
expect { @obj.keys('foo') }.to raise_error(/View#keys/)
|
534
552
|
end
|
535
553
|
end
|
536
554
|
|
537
555
|
describe "#keys (without parameters)" do
|
538
556
|
it "should request each row and provide key value" do
|
539
557
|
row = double("Row")
|
540
|
-
row.
|
541
|
-
@obj.
|
542
|
-
@obj.keys.
|
558
|
+
expect(row).to receive(:key).twice.and_return('foo')
|
559
|
+
expect(@obj).to receive(:rows).and_return([row, row])
|
560
|
+
expect(@obj.keys).to eql(['foo', 'foo'])
|
543
561
|
end
|
544
562
|
end
|
545
563
|
|
546
564
|
describe "#descending" do
|
547
565
|
it "should update query" do
|
548
|
-
@obj.
|
566
|
+
expect(@obj).to receive(:update_query).with({:descending => true})
|
549
567
|
@obj.descending
|
550
568
|
end
|
551
569
|
it "should reverse start and end keys if given" do
|
552
570
|
@obj = @obj.startkey('a').endkey('z')
|
553
571
|
@obj = @obj.descending
|
554
|
-
@obj.query[:endkey].
|
555
|
-
@obj.query[:startkey].
|
572
|
+
expect(@obj.query[:endkey]).to eql('a')
|
573
|
+
expect(@obj.query[:startkey]).to eql('z')
|
556
574
|
end
|
557
575
|
it "should reverse even if start or end nil" do
|
558
576
|
@obj = @obj.startkey('a')
|
559
577
|
@obj = @obj.descending
|
560
|
-
@obj.query[:endkey].
|
561
|
-
@obj.query[:startkey].
|
578
|
+
expect(@obj.query[:endkey]).to eql('a')
|
579
|
+
expect(@obj.query[:startkey]).to be_nil
|
562
580
|
end
|
563
581
|
it "should reverse start_doc and end_doc keys if given" do
|
564
582
|
@obj = @obj.startkey_doc('a').endkey_doc('z')
|
565
583
|
@obj = @obj.descending
|
566
|
-
@obj.query[:endkey_docid].
|
567
|
-
@obj.query[:startkey_docid].
|
584
|
+
expect(@obj.query[:endkey_docid]).to eql('a')
|
585
|
+
expect(@obj.query[:startkey_docid]).to eql('z')
|
568
586
|
end
|
569
587
|
end
|
570
588
|
|
571
589
|
describe "#limit" do
|
572
590
|
it "should update query with value" do
|
573
|
-
@obj.
|
591
|
+
expect(@obj).to receive(:update_query).with({:limit => 3})
|
574
592
|
@obj.limit(3)
|
575
593
|
end
|
576
594
|
end
|
577
595
|
|
578
596
|
describe "#skip" do
|
579
|
-
it "should update query with value" do
|
580
|
-
@obj.
|
597
|
+
it "should update query with value" do
|
598
|
+
expect(@obj).to receive(:update_query).with({:skip => 3})
|
581
599
|
@obj.skip(3)
|
582
600
|
end
|
583
|
-
it "should update query with default value" do
|
584
|
-
@obj.
|
601
|
+
it "should update query with default value" do
|
602
|
+
expect(@obj).to receive(:update_query).with({:skip => 0})
|
585
603
|
@obj.skip
|
586
604
|
end
|
587
605
|
end
|
588
606
|
|
589
607
|
describe "#reduce" do
|
590
608
|
it "should update query" do
|
591
|
-
@obj.
|
592
|
-
@obj.
|
609
|
+
expect(@obj).to receive(:can_reduce?).and_return(true)
|
610
|
+
expect(@obj).to receive(:update_query).with({:reduce => true, :delete => [:include_docs]})
|
593
611
|
@obj.reduce
|
594
612
|
end
|
595
613
|
it "should raise error if query cannot be reduced" do
|
596
|
-
@obj.
|
597
|
-
|
614
|
+
expect(@obj).to receive(:can_reduce?).and_return(false)
|
615
|
+
expect { @obj.reduce }.to raise_error(/Cannot reduce a view without a reduce method/)
|
598
616
|
end
|
599
617
|
end
|
600
618
|
|
601
619
|
describe "#group" do
|
602
620
|
it "should update query" do
|
603
|
-
@obj.
|
604
|
-
@obj.
|
621
|
+
expect(@obj).to receive(:query).and_return({:reduce => true})
|
622
|
+
expect(@obj).to receive(:update_query).with({:group => true})
|
605
623
|
@obj.group
|
606
624
|
end
|
607
625
|
it "should raise error if query not prepared for reduce" do
|
608
|
-
@obj.
|
609
|
-
|
626
|
+
expect(@obj).to receive(:query).and_return({:reduce => false})
|
627
|
+
expect { @obj.group }.to raise_error(/View#reduce must have been set before grouping is permitted/)
|
610
628
|
end
|
611
629
|
end
|
612
630
|
|
613
631
|
describe "#group" do
|
614
632
|
it "should update query" do
|
615
|
-
@obj.
|
616
|
-
@obj.
|
633
|
+
expect(@obj).to receive(:query).and_return({:reduce => true})
|
634
|
+
expect(@obj).to receive(:update_query).with({:group => true})
|
617
635
|
@obj.group
|
618
636
|
end
|
619
637
|
it "should raise error if query not prepared for reduce" do
|
620
|
-
@obj.
|
621
|
-
|
638
|
+
expect(@obj).to receive(:query).and_return({:reduce => false})
|
639
|
+
expect { @obj.group }.to raise_error(/View#reduce must have been set before grouping is permitted/)
|
622
640
|
end
|
623
641
|
end
|
624
642
|
|
625
643
|
describe "#group_level" do
|
626
644
|
it "should update query" do
|
627
|
-
@obj.
|
628
|
-
@obj.
|
645
|
+
expect(@obj).to receive(:group).and_return(@obj)
|
646
|
+
expect(@obj).to receive(:update_query).with({:group_level => 3})
|
629
647
|
@obj.group_level(3)
|
630
648
|
end
|
631
649
|
end
|
632
650
|
|
633
651
|
describe "#stale" do
|
634
652
|
it "should update query with ok" do
|
635
|
-
@obj.
|
653
|
+
expect(@obj).to receive(:update_query).with(:stale => 'ok')
|
636
654
|
@obj.stale('ok')
|
637
655
|
end
|
638
656
|
it "should update query with update_after" do
|
639
|
-
@obj.
|
657
|
+
expect(@obj).to receive(:update_query).with(:stale => 'update_after')
|
640
658
|
@obj.stale('update_after')
|
641
659
|
end
|
642
660
|
it "should fail if anything else is provided" do
|
643
|
-
|
661
|
+
expect { @obj.stale('yes') }.to raise_error(/can only be set with/)
|
644
662
|
end
|
645
663
|
end
|
646
664
|
|
647
665
|
describe "#include_docs" do
|
648
666
|
it "should call include_docs! on new view" do
|
649
|
-
@obj.
|
650
|
-
@obj.
|
667
|
+
expect(@obj).to receive(:update_query).and_return(@obj)
|
668
|
+
expect(@obj).to receive(:include_docs!)
|
651
669
|
@obj.include_docs
|
652
670
|
end
|
653
671
|
end
|
654
672
|
|
655
673
|
describe "#reset!" do
|
656
674
|
it "should empty all cached data" do
|
657
|
-
@obj.
|
675
|
+
expect(@obj).to receive(:result=).with(nil)
|
658
676
|
@obj.instance_exec { @rows = 'foo'; @docs = 'foo' }
|
659
677
|
@obj.reset!
|
660
|
-
@obj.instance_exec { @rows }.
|
661
|
-
@obj.instance_exec { @docs }.
|
678
|
+
expect(@obj.instance_exec { @rows }).to be_nil
|
679
|
+
expect(@obj.instance_exec { @docs }).to be_nil
|
662
680
|
end
|
663
681
|
end
|
664
682
|
|
@@ -666,58 +684,58 @@ describe "Design View" do
|
|
666
684
|
|
667
685
|
describe "#include_docs!" do
|
668
686
|
it "should set query value" do
|
669
|
-
@obj.
|
670
|
-
@obj.
|
687
|
+
expect(@obj).to receive(:result).and_return(false)
|
688
|
+
expect(@obj).not_to receive(:reset!)
|
671
689
|
@obj.send(:include_docs!)
|
672
|
-
@obj.query[:include_docs].
|
690
|
+
expect(@obj.query[:include_docs]).to be_truthy
|
673
691
|
end
|
674
692
|
it "should reset if result and no docs" do
|
675
|
-
@obj.
|
676
|
-
@obj.
|
677
|
-
@obj.
|
693
|
+
expect(@obj).to receive(:result).and_return(true)
|
694
|
+
expect(@obj).to receive(:include_docs?).and_return(false)
|
695
|
+
expect(@obj).to receive(:reset!)
|
678
696
|
@obj.send(:include_docs!)
|
679
|
-
@obj.query[:include_docs].
|
697
|
+
expect(@obj.query[:include_docs]).to be_truthy
|
680
698
|
end
|
681
699
|
it "should raise an error if view is reduced" do
|
682
700
|
@obj.query[:reduce] = true
|
683
|
-
|
701
|
+
expect { @obj.send(:include_docs!) }.to raise_error(/Cannot include documents in view that has been reduced/)
|
684
702
|
end
|
685
703
|
end
|
686
704
|
|
687
705
|
describe "#include_docs?" do
|
688
706
|
it "should return true if set" do
|
689
|
-
@obj.
|
690
|
-
@obj.send(:include_docs?).
|
707
|
+
expect(@obj).to receive(:query).and_return({:include_docs => true})
|
708
|
+
expect(@obj.send(:include_docs?)).to be_truthy
|
691
709
|
end
|
692
710
|
it "should return false if not set" do
|
693
|
-
@obj.
|
694
|
-
@obj.send(:include_docs?).
|
695
|
-
@obj.
|
696
|
-
@obj.send(:include_docs?).
|
711
|
+
expect(@obj).to receive(:query).and_return({})
|
712
|
+
expect(@obj.send(:include_docs?)).to be_falsey
|
713
|
+
expect(@obj).to receive(:query).and_return({:include_docs => false})
|
714
|
+
expect(@obj.send(:include_docs?)).to be_falsey
|
697
715
|
end
|
698
716
|
end
|
699
717
|
|
700
718
|
describe "#update_query" do
|
701
719
|
it "returns a new instance of view" do
|
702
|
-
@obj.send(:update_query).object_id.
|
720
|
+
expect(@obj.send(:update_query).object_id).not_to eql(@obj.object_id)
|
703
721
|
end
|
704
722
|
|
705
723
|
it "returns a new instance of view with extra parameters" do
|
706
724
|
new_obj = @obj.send(:update_query, {:foo => :bar})
|
707
|
-
new_obj.query[:foo].
|
725
|
+
expect(new_obj.query[:foo]).to eql(:bar)
|
708
726
|
end
|
709
727
|
end
|
710
728
|
|
711
729
|
describe "#can_reduce?" do
|
712
730
|
it "should check and prove true" do
|
713
|
-
@obj.
|
714
|
-
@obj.
|
715
|
-
@obj.send(:can_reduce?).
|
731
|
+
expect(@obj).to receive(:name).and_return('test_view')
|
732
|
+
expect(@obj).to receive(:design_doc).and_return({'views' => {'test_view' => {'reduce' => 'foo'}}})
|
733
|
+
expect(@obj.send(:can_reduce?)).to be_truthy
|
716
734
|
end
|
717
735
|
it "should check and prove false" do
|
718
|
-
@obj.
|
719
|
-
@obj.
|
720
|
-
@obj.send(:can_reduce?).
|
736
|
+
expect(@obj).to receive(:name).and_return('test_view')
|
737
|
+
expect(@obj).to receive(:design_doc).and_return({'views' => {'test_view' => {'reduce' => nil}}})
|
738
|
+
expect(@obj.send(:can_reduce?)).to be_falsey
|
721
739
|
end
|
722
740
|
end
|
723
741
|
|
@@ -725,48 +743,48 @@ describe "Design View" do
|
|
725
743
|
before :each do
|
726
744
|
# disable real execution!
|
727
745
|
@design_doc = double("DesignDoc")
|
728
|
-
@design_doc.
|
729
|
-
@design_doc.
|
730
|
-
@obj.
|
746
|
+
allow(@design_doc).to receive(:view_on)
|
747
|
+
allow(@design_doc).to receive(:sync)
|
748
|
+
allow(@obj).to receive(:design_doc).and_return(@design_doc)
|
731
749
|
end
|
732
750
|
|
733
751
|
it "should return previous result if set" do
|
734
752
|
@obj.result = "foo"
|
735
|
-
@obj.send(:execute).
|
753
|
+
expect(@obj.send(:execute)).to eql('foo')
|
736
754
|
end
|
737
755
|
|
738
756
|
it "should raise issue if no database" do
|
739
|
-
@obj.
|
757
|
+
expect(@obj).to receive(:query).and_return({:database => nil})
|
740
758
|
model = double("SomeModel")
|
741
|
-
model.
|
742
|
-
@obj.
|
743
|
-
|
759
|
+
expect(model).to receive(:database).and_return(nil)
|
760
|
+
expect(@obj).to receive(:model).and_return(model)
|
761
|
+
expect { @obj.send(:execute) }.to raise_error(CouchRest::Model::DatabaseNotDefined)
|
744
762
|
end
|
745
763
|
|
746
764
|
it "should delete the reduce option if not going to be used" do
|
747
|
-
@obj.
|
748
|
-
@obj.query.
|
765
|
+
expect(@obj).to receive(:can_reduce?).and_return(false)
|
766
|
+
expect(@obj.query).to receive(:delete).with(:reduce)
|
749
767
|
@obj.send(:execute)
|
750
768
|
end
|
751
769
|
|
752
770
|
it "should call to save the design document" do
|
753
|
-
@obj.
|
754
|
-
@design_doc.
|
771
|
+
expect(@obj).to receive(:can_reduce?).and_return(false)
|
772
|
+
expect(@design_doc).to receive(:sync).with(DB)
|
755
773
|
@obj.send(:execute)
|
756
774
|
end
|
757
775
|
|
758
776
|
it "should populate the results" do
|
759
|
-
@obj.
|
760
|
-
@design_doc.
|
777
|
+
expect(@obj).to receive(:can_reduce?).and_return(true)
|
778
|
+
expect(@design_doc).to receive(:view_on).and_return('foos')
|
761
779
|
@obj.send(:execute)
|
762
|
-
@obj.result.
|
780
|
+
expect(@obj.result).to eql('foos')
|
763
781
|
end
|
764
782
|
|
765
783
|
it "should not remove nil values from query" do
|
766
|
-
@obj.
|
767
|
-
@obj.
|
784
|
+
expect(@obj).to receive(:can_reduce?).and_return(true)
|
785
|
+
allow(@obj).to receive(:use_database).and_return(@mod.database)
|
768
786
|
@obj.query = {:reduce => true, :limit => nil, :skip => nil}
|
769
|
-
@design_doc.
|
787
|
+
expect(@design_doc).to receive(:view_on).with(@mod.database, 'test_view', {:reduce => true, :limit => nil, :skip => nil})
|
770
788
|
@obj.send(:execute)
|
771
789
|
end
|
772
790
|
|
@@ -785,59 +803,59 @@ describe "Design View" do
|
|
785
803
|
|
786
804
|
describe "#page" do
|
787
805
|
it "should call limit and skip" do
|
788
|
-
@obj.
|
789
|
-
@obj.
|
806
|
+
expect(@obj).to receive(:limit).with(25).and_return(@obj)
|
807
|
+
expect(@obj).to receive(:skip).with(25).and_return(@obj)
|
790
808
|
@obj.page(2)
|
791
809
|
end
|
792
810
|
end
|
793
811
|
|
794
812
|
describe "#per" do
|
795
813
|
it "should raise an error if page not called before hand" do
|
796
|
-
|
814
|
+
expect { @obj.per(12) }.to raise_error(/View#page must be called before #per/)
|
797
815
|
end
|
798
816
|
it "should not do anything if number less than or eql 0" do
|
799
817
|
view = @obj.page(1)
|
800
|
-
view.per(0).
|
818
|
+
expect(view.per(0)).to eql(view)
|
801
819
|
end
|
802
820
|
it "should set limit and update skip" do
|
803
821
|
view = @obj.page(2).per(10)
|
804
|
-
view.query[:skip].
|
805
|
-
view.query[:limit].
|
822
|
+
expect(view.query[:skip]).to eql(10)
|
823
|
+
expect(view.query[:limit]).to eql(10)
|
806
824
|
end
|
807
825
|
end
|
808
826
|
|
809
827
|
describe "#total_count" do
|
810
828
|
it "set limit and skip to nill and perform count" do
|
811
|
-
@obj.
|
812
|
-
@obj.
|
813
|
-
@obj.
|
814
|
-
@obj.total_count.
|
815
|
-
@obj.total_count.
|
829
|
+
expect(@obj).to receive(:limit).with(nil).and_return(@obj)
|
830
|
+
expect(@obj).to receive(:skip).with(nil).and_return(@obj)
|
831
|
+
expect(@obj).to receive(:count).and_return(5)
|
832
|
+
expect(@obj.total_count).to eql(5)
|
833
|
+
expect(@obj.total_count).to eql(5) # Second to test caching
|
816
834
|
end
|
817
835
|
end
|
818
836
|
|
819
837
|
describe "#total_pages" do
|
820
838
|
it "should use total_count and limit_value" do
|
821
|
-
@obj.
|
822
|
-
@obj.
|
823
|
-
@obj.total_pages.
|
839
|
+
expect(@obj).to receive(:total_count).and_return(200)
|
840
|
+
expect(@obj).to receive(:limit_value).and_return(25)
|
841
|
+
expect(@obj.total_pages).to eql(8)
|
824
842
|
end
|
825
843
|
end
|
826
844
|
|
827
845
|
# `num_pages` aliases to `total_pages` for compatibility for Kaminari '< 0.14'
|
828
846
|
describe "#num_pages" do
|
829
847
|
it "should use total_count and limit_value" do
|
830
|
-
@obj.
|
831
|
-
@obj.
|
832
|
-
@obj.num_pages.
|
848
|
+
expect(@obj).to receive(:total_count).and_return(200)
|
849
|
+
expect(@obj).to receive(:limit_value).and_return(25)
|
850
|
+
expect(@obj.num_pages).to eql(8)
|
833
851
|
end
|
834
852
|
end
|
835
853
|
|
836
854
|
describe "#current_page" do
|
837
855
|
it "should use offset and limit" do
|
838
|
-
@obj.
|
839
|
-
@obj.
|
840
|
-
@obj.current_page.
|
856
|
+
expect(@obj).to receive(:offset_value).and_return(25)
|
857
|
+
expect(@obj).to receive(:limit_value).and_return(25)
|
858
|
+
expect(@obj.current_page).to eql(2)
|
841
859
|
end
|
842
860
|
end
|
843
861
|
end
|
@@ -852,19 +870,19 @@ describe "Design View" do
|
|
852
870
|
|
853
871
|
let :model do
|
854
872
|
m = double()
|
855
|
-
m.
|
873
|
+
allow(m).to receive(:database).and_return(DB)
|
856
874
|
m
|
857
875
|
end
|
858
876
|
|
859
877
|
describe "intialize" do
|
860
878
|
it "should store reference to model" do
|
861
879
|
obj = @klass.new({}, model)
|
862
|
-
obj.model.
|
880
|
+
expect(obj.model).to eql(model)
|
863
881
|
end
|
864
882
|
it "should copy details from hash" do
|
865
883
|
obj = @klass.new({:foo => :bar, :test => :example}, model)
|
866
|
-
obj[:foo].
|
867
|
-
obj[:test].
|
884
|
+
expect(obj[:foo]).to eql(:bar)
|
885
|
+
expect(obj[:test]).to eql(:example)
|
868
886
|
end
|
869
887
|
end
|
870
888
|
|
@@ -874,7 +892,7 @@ describe "Design View" do
|
|
874
892
|
|
875
893
|
it "should provide id" do
|
876
894
|
obj = @klass.new({'id' => '123456'}, model)
|
877
|
-
obj.id.
|
895
|
+
expect(obj.id).to eql('123456')
|
878
896
|
end
|
879
897
|
|
880
898
|
it "may be instantiated with a database" do
|
@@ -889,24 +907,24 @@ describe "Design View" do
|
|
889
907
|
|
890
908
|
it "should provide key" do
|
891
909
|
obj = @klass.new({'key' => 'thekey'}, model)
|
892
|
-
obj.key.
|
910
|
+
expect(obj.key).to eql('thekey')
|
893
911
|
end
|
894
912
|
|
895
913
|
it "should provide the value" do
|
896
914
|
obj = @klass.new({'value' => 'thevalue'}, model)
|
897
|
-
obj.value.
|
915
|
+
expect(obj.value).to eql('thevalue')
|
898
916
|
end
|
899
917
|
|
900
918
|
it "should provide the raw document" do
|
901
919
|
obj = @klass.new({'doc' => 'thedoc'}, model)
|
902
|
-
obj.raw_doc.
|
920
|
+
expect(obj.raw_doc).to eql('thedoc')
|
903
921
|
end
|
904
922
|
|
905
923
|
it "should instantiate a new document" do
|
906
924
|
hash = {'doc' => {'_id' => '12345', 'name' => 'sam'}}
|
907
925
|
obj = @klass.new(hash, DesignViewModel)
|
908
926
|
doc = double('DesignViewDoc')
|
909
|
-
doc.
|
927
|
+
allow(doc).to receive(:database).and_return(DB)
|
910
928
|
expect(obj.model).to receive(:build_from_database).with(hash['doc']).and_return(doc)
|
911
929
|
expect(obj.doc).to eql(doc)
|
912
930
|
end
|
@@ -915,31 +933,31 @@ describe "Design View" do
|
|
915
933
|
hash = {'id' => '12345', 'value' => 5}
|
916
934
|
obj = @klass.new(hash, DesignViewModel)
|
917
935
|
doc = double('DesignViewModel')
|
918
|
-
doc.
|
919
|
-
obj.model.
|
920
|
-
obj.doc.
|
936
|
+
allow(doc).to receive(:database).and_return(DB)
|
937
|
+
expect(obj.model).to receive(:get).with('12345', DB).and_return(doc)
|
938
|
+
expect(obj.doc).to eql(doc)
|
921
939
|
end
|
922
940
|
|
923
941
|
it "should try to load linked document if available" do
|
924
942
|
hash = {'id' => '12345', 'value' => {'_id' => '54321'}}
|
925
943
|
obj = @klass.new(hash, DesignViewModel)
|
926
944
|
doc = double('DesignViewModel')
|
927
|
-
doc.
|
928
|
-
obj.model.
|
929
|
-
obj.doc.
|
945
|
+
allow(doc).to receive(:database).and_return(DB)
|
946
|
+
expect(obj.model).to receive(:get).with('54321', DB).and_return(doc)
|
947
|
+
expect(obj.doc).to eql(doc)
|
930
948
|
end
|
931
949
|
|
932
950
|
it "should try to return nil for document if none available" do
|
933
951
|
hash = {'value' => 23} # simulate reduce
|
934
952
|
obj = @klass.new(hash, DesignViewModel)
|
935
953
|
doc = double('DesignViewModel')
|
936
|
-
obj.model.
|
937
|
-
obj.doc.
|
954
|
+
expect(obj.model).not_to receive(:get)
|
955
|
+
expect(obj.doc).to be_nil
|
938
956
|
end
|
939
957
|
|
940
958
|
|
941
959
|
end
|
942
|
-
|
960
|
+
|
943
961
|
end
|
944
962
|
|
945
963
|
|
@@ -957,53 +975,53 @@ describe "Design View" do
|
|
957
975
|
|
958
976
|
describe "loading documents" do
|
959
977
|
it "should return first" do
|
960
|
-
DesignViewModel.by_name.first.name.
|
978
|
+
expect(DesignViewModel.by_name.first.name).to eql("Judith")
|
961
979
|
end
|
962
980
|
|
963
981
|
it "should return last" do
|
964
|
-
DesignViewModel.by_name.last.name.
|
982
|
+
expect(DesignViewModel.by_name.last.name).to eql("Vilma")
|
965
983
|
end
|
966
984
|
|
967
985
|
it "should allow multiple results" do
|
968
986
|
view = DesignViewModel.by_name.limit(3)
|
969
|
-
view.total_rows.
|
970
|
-
view.last.name.
|
971
|
-
view.all.length.
|
987
|
+
expect(view.total_rows).to eql(5)
|
988
|
+
expect(view.last.name).to eql("Peter")
|
989
|
+
expect(view.all.length).to eql(3)
|
972
990
|
end
|
973
991
|
|
974
992
|
it "should not return document if nil key provided" do
|
975
|
-
DesignViewModel.by_name.key(nil).first.
|
993
|
+
expect(DesignViewModel.by_name.key(nil).first).to be_nil
|
976
994
|
end
|
977
995
|
end
|
978
996
|
|
979
997
|
describe "index information" do
|
980
998
|
it "should provide total_rows" do
|
981
|
-
DesignViewModel.by_name.total_rows.
|
999
|
+
expect(DesignViewModel.by_name.total_rows).to eql(5)
|
982
1000
|
end
|
983
1001
|
it "should provide total_rows" do
|
984
|
-
DesignViewModel.by_name.total_rows.
|
1002
|
+
expect(DesignViewModel.by_name.total_rows).to eql(5)
|
985
1003
|
end
|
986
1004
|
it "should provide an offset" do
|
987
|
-
DesignViewModel.by_name.offset.
|
1005
|
+
expect(DesignViewModel.by_name.offset).to eql(0)
|
988
1006
|
end
|
989
1007
|
it "should provide a set of keys" do
|
990
|
-
DesignViewModel.by_name.limit(2).keys.
|
1008
|
+
expect(DesignViewModel.by_name.limit(2).keys).to eql(["Judith", "Lorena"])
|
991
1009
|
end
|
992
1010
|
end
|
993
1011
|
|
994
1012
|
describe "viewing" do
|
995
1013
|
it "should load views with no reduce method" do
|
996
1014
|
docs = DesignViewModel.by_just_name.all
|
997
|
-
docs.length.
|
1015
|
+
expect(docs.length).to eql(5)
|
998
1016
|
end
|
999
1017
|
it "should load documents by specific keys" do
|
1000
1018
|
docs = DesignViewModel.by_name.keys(["Judith", "Peter"]).all
|
1001
|
-
docs[0].name.
|
1002
|
-
docs[1].name.
|
1019
|
+
expect(docs[0].name).to eql("Judith")
|
1020
|
+
expect(docs[1].name).to eql("Peter")
|
1003
1021
|
end
|
1004
1022
|
it "should provide count even if limit or skip set" do
|
1005
1023
|
docs = DesignViewModel.by_name.limit(20).skip(2)
|
1006
|
-
docs.count.
|
1024
|
+
expect(docs.count).to eql(5)
|
1007
1025
|
end
|
1008
1026
|
end
|
1009
1027
|
|
@@ -1016,24 +1034,51 @@ describe "Design View" do
|
|
1016
1034
|
end
|
1017
1035
|
|
1018
1036
|
it "should calculate number of pages" do
|
1019
|
-
@view.total_pages.
|
1037
|
+
expect(@view.total_pages).to eql(2)
|
1020
1038
|
end
|
1021
1039
|
it "should return results from first page" do
|
1022
|
-
@view.all.first.name.
|
1023
|
-
@view.all.last.name.
|
1040
|
+
expect(@view.all.first.name).to eql('Judith')
|
1041
|
+
expect(@view.all.last.name).to eql('Peter')
|
1024
1042
|
end
|
1025
1043
|
it "should return results from second page" do
|
1026
|
-
@view.page(2).all.first.name.
|
1027
|
-
@view.page(2).all.last.name.
|
1044
|
+
expect(@view.page(2).all.first.name).to eql('Sam')
|
1045
|
+
expect(@view.page(2).all.last.name).to eql('Vilma')
|
1028
1046
|
end
|
1029
1047
|
|
1030
1048
|
it "should allow overriding per page count" do
|
1031
1049
|
@view = @view.per(10)
|
1032
|
-
@view.total_pages.
|
1033
|
-
@view.all.last.name.
|
1050
|
+
expect(@view.total_pages).to eql(1)
|
1051
|
+
expect(@view.all.last.name).to eql('Vilma')
|
1034
1052
|
end
|
1035
1053
|
end
|
1036
1054
|
|
1055
|
+
describe "concurrent view accesses" do
|
1056
|
+
|
1057
|
+
# NOTE: must use `DesignViewModel2` instead of `DesignViewModel` to mimic
|
1058
|
+
# a "cold" start of a multi-threaded application (as the checksum is
|
1059
|
+
# stored at the class level)
|
1060
|
+
class DesignViewModel2 < CouchRest::Model::Base
|
1061
|
+
use_database DB
|
1062
|
+
property :name
|
1063
|
+
|
1064
|
+
design do
|
1065
|
+
view :by_name
|
1066
|
+
end
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
it "should not conflict" do
|
1070
|
+
expect {
|
1071
|
+
threads = 2.times.map {
|
1072
|
+
Thread.new {
|
1073
|
+
DesignViewModel2.by_name.page(1).to_a
|
1074
|
+
}
|
1075
|
+
}
|
1076
|
+
threads.each(&:join)
|
1077
|
+
}.to_not raise_error
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
end
|
1081
|
+
|
1037
1082
|
end
|
1038
1083
|
|
1039
1084
|
|