couch_potato 1.7.0 → 1.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +50 -0
- data/.gitignore +3 -0
- data/CHANGES.md +180 -130
- data/Gemfile +4 -0
- data/README.md +61 -85
- data/Rakefile +11 -10
- data/couch_potato-rspec.gemspec +2 -1
- data/couch_potato.gemspec +9 -7
- data/gemfiles/active_support_5_0 +6 -0
- data/gemfiles/active_support_5_1 +7 -0
- data/gemfiles/active_support_5_2 +6 -0
- data/gemfiles/active_support_6_0 +6 -0
- data/gemfiles/active_support_6_1 +6 -0
- data/gemfiles/active_support_7_0 +6 -0
- data/lib/couch_potato/database.rb +170 -71
- data/lib/couch_potato/persistence/dirty_attributes.rb +3 -21
- data/lib/couch_potato/persistence/magic_timestamps.rb +3 -3
- data/lib/couch_potato/persistence/properties.rb +15 -10
- data/lib/couch_potato/persistence/simple_property.rb +0 -4
- data/lib/couch_potato/persistence/type_caster.rb +11 -6
- data/lib/couch_potato/persistence.rb +0 -1
- data/lib/couch_potato/railtie.rb +6 -11
- data/lib/couch_potato/validation.rb +8 -0
- data/lib/couch_potato/version.rb +2 -2
- data/lib/couch_potato/view/base_view_spec.rb +8 -32
- data/lib/couch_potato/view/custom_views.rb +4 -3
- data/lib/couch_potato/view/flex_view_spec.rb +121 -0
- data/lib/couch_potato/view/view_parameters.rb +34 -0
- data/lib/couch_potato.rb +37 -16
- data/spec/callbacks_spec.rb +45 -19
- data/spec/conflict_handling_spec.rb +1 -2
- data/spec/property_spec.rb +12 -3
- data/spec/railtie_spec.rb +10 -0
- data/spec/spec_helper.rb +4 -3
- data/spec/unit/active_model_compliance_spec.rb +7 -3
- data/spec/unit/attributes_spec.rb +54 -1
- data/spec/unit/caching_spec.rb +105 -0
- data/spec/unit/couch_potato_spec.rb +70 -5
- data/spec/unit/create_spec.rb +5 -4
- data/spec/unit/database_spec.rb +239 -135
- data/spec/unit/dirty_attributes_spec.rb +5 -26
- data/spec/unit/flex_view_spec_spec.rb +17 -0
- data/spec/unit/model_view_spec_spec.rb +1 -1
- data/spec/unit/rspec_stub_db_spec.rb +31 -0
- data/spec/unit/validation_spec.rb +42 -2
- data/spec/unit/view_query_spec.rb +12 -7
- data/spec/views_spec.rb +214 -103
- data/vendor/pouchdb-collate/LICENSE +202 -0
- data/vendor/pouchdb-collate/pouchdb-collate.js +430 -0
- metadata +47 -36
- data/.ruby-version +0 -1
- data/.travis.yml +0 -21
- data/gemfiles/active_support_4_0 +0 -11
- data/gemfiles/active_support_4_1 +0 -11
- data/gemfiles/active_support_4_2 +0 -11
- data/lib/couch_potato/persistence/deep_dirty_attributes.rb +0 -180
- data/spec/unit/deep_dirty_attributes_spec.rb +0 -434
data/spec/views_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
class Build
|
@@ -5,20 +7,35 @@ class Build
|
|
5
7
|
|
6
8
|
property :state
|
7
9
|
property :time
|
8
|
-
property :type, :
|
9
|
-
|
10
|
-
view :timeline, :
|
11
|
-
view :count, :
|
12
|
-
view :minimal_timeline, :
|
13
|
-
view :key_array_timeline, :
|
14
|
-
view :custom_timeline, :
|
15
|
-
view :custom_timeline_returns_docs, :
|
16
|
-
view :custom_with_reduce, :
|
17
|
-
view :custom_count_with_reduce, :
|
18
|
-
view :raw, :
|
19
|
-
view :filtered_raw, :
|
20
|
-
view :with_view_options, :
|
21
|
-
view :all, :
|
10
|
+
property :type, type: String, default: 'Build'
|
11
|
+
|
12
|
+
view :timeline, key: :time
|
13
|
+
view :count, key: :time, reduce: true
|
14
|
+
view :minimal_timeline, key: :time, properties: [:state], type: :properties
|
15
|
+
view :key_array_timeline, key: %i[time state]
|
16
|
+
view :custom_timeline, map: "function(doc) { emit(doc._id, {state: 'custom_' + doc.state}); }", type: :custom
|
17
|
+
view :custom_timeline_returns_docs, map: 'function(doc) { emit(doc._id, null); }', include_docs: true, type: :custom
|
18
|
+
view :custom_with_reduce, map: 'function(doc) {if(doc.foreign_key) {emit(doc.foreign_key, 1);} else {emit(doc._id, 1)}}', reduce: 'function(key, values) {return({"count": sum(values)});}', group: true, type: :custom
|
19
|
+
view :custom_count_with_reduce, map: 'function(doc) {if(doc.foreign_key) {emit(doc.foreign_key, 1);} else {emit(doc._id, 1)}}', reduce: 'function(key, values) {return(sum(values));}', group: true, type: :custom
|
20
|
+
view :raw, type: :raw, map: 'function(doc) {emit(doc._id, doc.state)}'
|
21
|
+
view :filtered_raw, type: :raw, map: 'function(doc) {emit(doc._id, doc.state)}', results_filter: ->(res) { res['rows'].map { |row| row['value'] } }
|
22
|
+
view :with_view_options, group: true, key: :time
|
23
|
+
view :all, map: "function(doc) { if (doc && doc.type == 'Build') emit(doc._id, 1); }", include_docs: true, type: :custom
|
24
|
+
|
25
|
+
module TimesToInt
|
26
|
+
def times_to_int
|
27
|
+
docs.map { |doc| doc.time.to_i }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
view :flex_with_key, type: :flex, key: :time, extend_results: TimesToInt
|
31
|
+
view :flex_with_custom,
|
32
|
+
type: :flex,
|
33
|
+
map: <<~JS,
|
34
|
+
function(doc) {
|
35
|
+
emit(doc.time, 1);
|
36
|
+
}
|
37
|
+
JS
|
38
|
+
reduce: '_sum'
|
22
39
|
end
|
23
40
|
|
24
41
|
class CustomBuild < Build
|
@@ -30,8 +47,8 @@ class ErlangBuild
|
|
30
47
|
property :name
|
31
48
|
property :code
|
32
49
|
|
33
|
-
view :by_name, :
|
34
|
-
view :by_name_and_code, :
|
50
|
+
view :by_name, key: :name, language: :erlang
|
51
|
+
view :by_name_and_code, key: %i[name code], language: :erlang
|
35
52
|
end
|
36
53
|
|
37
54
|
describe 'views' do
|
@@ -42,7 +59,7 @@ describe 'views' do
|
|
42
59
|
|
43
60
|
context 'in erlang' do
|
44
61
|
it 'builds views with single keys' do
|
45
|
-
build = ErlangBuild.new(:
|
62
|
+
build = ErlangBuild.new(name: 'erlang')
|
46
63
|
@db.save_document build
|
47
64
|
|
48
65
|
results = @db.view(ErlangBuild.by_name('erlang'))
|
@@ -50,98 +67,98 @@ describe 'views' do
|
|
50
67
|
end
|
51
68
|
|
52
69
|
it 'does not crash couchdb when a document does not have the key' do
|
53
|
-
build = {'ruby_class' => 'ErlangBuild'}
|
70
|
+
build = { 'ruby_class' => 'ErlangBuild' }
|
54
71
|
@db.couchrest_database.save_doc build
|
55
72
|
|
56
|
-
results = @db.view(ErlangBuild.by_name(:
|
73
|
+
results = @db.view(ErlangBuild.by_name(key: nil))
|
57
74
|
expect(results.size).to eq(1)
|
58
75
|
end
|
59
76
|
|
60
77
|
it 'builds views with composite keys' do
|
61
|
-
build = ErlangBuild.new(:
|
78
|
+
build = ErlangBuild.new(name: 'erlang', code: '123')
|
62
79
|
@db.save_document build
|
63
80
|
|
64
|
-
results = @db.view(ErlangBuild.by_name_and_code([
|
81
|
+
results = @db.view(ErlangBuild.by_name_and_code(%w[erlang 123]))
|
65
82
|
expect(results).to eq([build])
|
66
83
|
end
|
67
84
|
|
68
85
|
it 'can reduce over erlang views' do
|
69
|
-
build = ErlangBuild.new(:
|
86
|
+
build = ErlangBuild.new(name: 'erlang')
|
70
87
|
@db.save_document build
|
71
88
|
|
72
|
-
results = @db.view(ErlangBuild.by_name(:
|
89
|
+
results = @db.view(ErlangBuild.by_name(reduce: true))
|
73
90
|
expect(results).to eq(1)
|
74
91
|
end
|
75
92
|
end
|
76
93
|
|
77
|
-
it
|
78
|
-
@db.save_document Build.new(:
|
94
|
+
it 'should return instances of the class' do
|
95
|
+
@db.save_document Build.new(state: 'success', time: '2008-01-01')
|
79
96
|
results = @db.view(Build.timeline)
|
80
97
|
expect(results.map(&:class)).to eq([Build])
|
81
98
|
end
|
82
99
|
|
83
|
-
it
|
84
|
-
build = Build.new(:
|
100
|
+
it 'should return the ids if there document was not included' do
|
101
|
+
build = Build.new(state: 'success', time: '2008-01-01')
|
85
102
|
@db.save_document build
|
86
|
-
results = @db.view(Build.timeline(:
|
103
|
+
results = @db.view(Build.timeline(include_docs: false))
|
87
104
|
expect(results).to eq([build.id])
|
88
105
|
end
|
89
106
|
|
90
|
-
it
|
107
|
+
it 'should pass the view options to the view query' do
|
91
108
|
query = double 'query'
|
92
109
|
allow(CouchPotato::View::ViewQuery).to receive(:new).and_return(query)
|
93
|
-
expect(query).to receive(:query_view!).with(hash_including(:
|
94
|
-
@db.view Build.timeline(:
|
110
|
+
expect(query).to receive(:query_view!).with(hash_including(key: 1)).and_return('rows' => [])
|
111
|
+
@db.view Build.timeline(key: 1)
|
95
112
|
end
|
96
113
|
|
97
114
|
it "should not return documents that don't have a matching JSON.create_id" do
|
98
|
-
CouchPotato.couchrest_database.save_doc({:
|
115
|
+
CouchPotato.couchrest_database.save_doc({ time: 'x' })
|
99
116
|
expect(@db.view(Build.timeline)).to eq([])
|
100
117
|
end
|
101
118
|
|
102
|
-
it
|
103
|
-
@db.save_document! Build.new(:
|
104
|
-
expect(@db.view(Build.count(:
|
119
|
+
it 'should count documents' do
|
120
|
+
@db.save_document! Build.new(state: 'success', time: '2008-01-01')
|
121
|
+
expect(@db.view(Build.count(reduce: true))).to eq(1)
|
105
122
|
end
|
106
123
|
|
107
|
-
it
|
108
|
-
expect(@db.view(Build.count(:
|
124
|
+
it 'should count zero documents' do
|
125
|
+
expect(@db.view(Build.count(reduce: true))).to eq(0)
|
109
126
|
end
|
110
127
|
|
111
|
-
describe
|
112
|
-
it
|
113
|
-
build = Build.new(:
|
128
|
+
describe 'with multiple keys' do
|
129
|
+
it 'should return the documents with matching keys' do
|
130
|
+
build = Build.new(state: 'success', time: '2008-01-01')
|
114
131
|
@db.save! build
|
115
|
-
expect(@db.view(Build.timeline(:
|
132
|
+
expect(@db.view(Build.timeline(keys: ['2008-01-01']))).to eq([build])
|
116
133
|
end
|
117
134
|
|
118
|
-
it
|
119
|
-
build = Build.new(:
|
135
|
+
it 'should not return documents with non-matching keys' do
|
136
|
+
build = Build.new(state: 'success', time: '2008-01-01')
|
120
137
|
@db.save! build
|
121
|
-
expect(@db.view(Build.timeline(:
|
138
|
+
expect(@db.view(Build.timeline(keys: ['2008-01-02']))).to be_empty
|
122
139
|
end
|
123
140
|
end
|
124
141
|
|
125
|
-
describe
|
126
|
-
it
|
142
|
+
describe 'properties defined' do
|
143
|
+
it 'assigns the configured properties' do
|
127
144
|
CouchPotato.couchrest_database.save_doc(:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build')
|
128
145
|
expect(@db.view(Build.minimal_timeline).first.state).to eql('success')
|
129
146
|
end
|
130
147
|
|
131
|
-
it
|
148
|
+
it 'does not assign the properties not configured' do
|
132
149
|
CouchPotato.couchrest_database.save_doc(:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build')
|
133
150
|
expect(@db.view(Build.minimal_timeline).first.time).to be_nil
|
134
151
|
end
|
135
152
|
|
136
|
-
it
|
153
|
+
it 'assigns the id even if it is not configured' do
|
137
154
|
id = CouchPotato.couchrest_database.save_doc(:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build')['id']
|
138
155
|
expect(@db.view(Build.minimal_timeline).first._id).to eql(id)
|
139
156
|
end
|
140
157
|
end
|
141
158
|
|
142
|
-
describe
|
143
|
-
it
|
144
|
-
id = CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build'})['id']
|
159
|
+
describe 'no properties defined' do
|
160
|
+
it 'should assign all properties to the objects by default' do
|
161
|
+
id = CouchPotato.couchrest_database.save_doc({ :state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build' })['id']
|
145
162
|
result = @db.view(Build.timeline).first
|
146
163
|
expect(result.state).to eq('success')
|
147
164
|
expect(result.time).to eq('2008-01-01')
|
@@ -149,116 +166,210 @@ describe 'views' do
|
|
149
166
|
end
|
150
167
|
end
|
151
168
|
|
152
|
-
describe
|
153
|
-
it
|
154
|
-
CouchPotato.couchrest_database.save_doc({:
|
169
|
+
describe 'map function given' do
|
170
|
+
it 'should still return instances of the class' do
|
171
|
+
CouchPotato.couchrest_database.save_doc({ state: 'success', time: '2008-01-01' })
|
155
172
|
expect(@db.view(Build.custom_timeline).map(&:class)).to eq([Build])
|
156
173
|
end
|
157
174
|
|
158
|
-
it
|
159
|
-
CouchPotato.couchrest_database.save_doc({:
|
175
|
+
it 'should assign the properties from the value' do
|
176
|
+
CouchPotato.couchrest_database.save_doc({ state: 'success', time: '2008-01-01' })
|
160
177
|
expect(@db.view(Build.custom_timeline).map(&:state)).to eq(['custom_success'])
|
161
178
|
end
|
162
179
|
|
163
|
-
it
|
164
|
-
doc = CouchPotato.couchrest_database.save_doc({:
|
180
|
+
it 'should assign the id' do
|
181
|
+
doc = CouchPotato.couchrest_database.save_doc({ state: 'success', time: '2008-01-01' })
|
165
182
|
expect(@db.view(Build.custom_timeline).map(&:_id)).to eq([doc['id']])
|
166
183
|
end
|
167
184
|
|
168
|
-
it
|
169
|
-
CouchPotato.couchrest_database.save_doc({:
|
185
|
+
it 'should leave the other properties blank' do
|
186
|
+
CouchPotato.couchrest_database.save_doc({ state: 'success', time: '2008-01-01' })
|
170
187
|
expect(@db.view(Build.custom_timeline).map(&:time)).to eq([nil])
|
171
188
|
end
|
172
189
|
|
173
|
-
describe
|
174
|
-
it
|
175
|
-
CouchPotato.couchrest_database.save_doc({:
|
190
|
+
describe 'that returns null documents' do
|
191
|
+
it 'should return instances of the class' do
|
192
|
+
CouchPotato.couchrest_database.save_doc({ state: 'success', time: '2008-01-01' })
|
176
193
|
expect(@db.view(Build.custom_timeline_returns_docs).map(&:class)).to eq([Build])
|
177
194
|
end
|
178
195
|
|
179
|
-
it
|
180
|
-
CouchPotato.couchrest_database.save_doc({:
|
196
|
+
it 'should assign the properties from the value' do
|
197
|
+
CouchPotato.couchrest_database.save_doc({ state: 'success', time: '2008-01-01' })
|
181
198
|
expect(@db.view(Build.custom_timeline_returns_docs).map(&:state)).to eq(['success'])
|
182
199
|
end
|
183
200
|
|
184
|
-
it
|
185
|
-
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym =>
|
201
|
+
it 'should still return instance of class if document included JSON.create_id' do
|
202
|
+
CouchPotato.couchrest_database.save_doc({ :state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build' })
|
186
203
|
view_data = @db.view(Build.custom_timeline_returns_docs)
|
187
204
|
expect(view_data.map(&:class)).to eq([Build])
|
188
205
|
expect(view_data.map(&:state)).to eq(['success'])
|
189
206
|
end
|
190
207
|
end
|
191
208
|
|
192
|
-
describe
|
193
|
-
it
|
209
|
+
describe 'additional reduce function given' do
|
210
|
+
it 'should still assign the id' do
|
194
211
|
doc = CouchPotato.couchrest_database.save_doc({})
|
195
|
-
CouchPotato.couchrest_database.save_doc({:
|
212
|
+
CouchPotato.couchrest_database.save_doc({ foreign_key: doc['id'] })
|
196
213
|
expect(@db.view(Build.custom_with_reduce).map(&:_id)).to eq([doc['id']])
|
197
214
|
end
|
198
215
|
|
199
|
-
describe
|
200
|
-
it
|
216
|
+
describe 'when the additional reduce function is a typical count' do
|
217
|
+
it 'should parse the reduce count' do
|
201
218
|
doc = CouchPotato.couchrest_database.save_doc({})
|
202
|
-
CouchPotato.couchrest_database.save_doc({:
|
203
|
-
expect(@db.view(Build.custom_count_with_reduce(:
|
219
|
+
CouchPotato.couchrest_database.save_doc({ foreign_key: doc['id'] })
|
220
|
+
expect(@db.view(Build.custom_count_with_reduce(reduce: true))).to eq(2)
|
204
221
|
end
|
205
222
|
end
|
206
223
|
end
|
207
224
|
end
|
208
225
|
|
209
|
-
describe
|
210
|
-
it
|
211
|
-
expect(CouchPotato::View::ViewQuery).to receive(:new) do |
|
226
|
+
describe 'with array as key' do
|
227
|
+
it 'should create a map function with the composite key' do
|
228
|
+
expect(CouchPotato::View::ViewQuery).to receive(:new) do |_db, _design_name, view, _list|
|
212
229
|
expect(view['key_array_timeline'][:map]).to match(/emit\(\[doc\['time'\], doc\['state'\]\]/)
|
213
230
|
|
214
|
-
double('view query',
|
231
|
+
double('view query', query_view!: { 'rows' => [] })
|
215
232
|
end
|
216
233
|
@db.view Build.key_array_timeline
|
217
234
|
end
|
218
235
|
end
|
219
236
|
|
220
|
-
describe
|
221
|
-
it
|
222
|
-
@db.save_document Build.new(:
|
237
|
+
describe 'raw view' do
|
238
|
+
it 'should return the raw data' do
|
239
|
+
@db.save_document Build.new(state: 'success', time: '2008-01-01')
|
223
240
|
expect(@db.view(Build.raw)['rows'][0]['value']).to eq('success')
|
224
241
|
end
|
225
242
|
|
226
|
-
it
|
227
|
-
@db.save_document Build.new(:
|
243
|
+
it 'should return filtred raw data' do
|
244
|
+
@db.save_document Build.new(state: 'success', time: '2008-01-01')
|
228
245
|
expect(@db.view(Build.filtered_raw)).to eq(['success'])
|
229
246
|
end
|
230
247
|
|
231
|
-
it
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
248
|
+
it 'should pass view options declared in the view declaration to the query' do
|
249
|
+
view_query = double 'view_query'
|
250
|
+
allow(CouchPotato::View::ViewQuery).to receive(:new).and_return(view_query)
|
251
|
+
expect(view_query).to receive(:query_view!).with(hash_including(group: true)).and_return({ 'rows' => [] })
|
252
|
+
@db.view(Build.with_view_options)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
describe 'flex view' do
|
257
|
+
it 'supports a given key' do
|
258
|
+
@db.save_document Build.new(id: 'b1', state: 'success', time: '2008-01-01')
|
259
|
+
@db.save_document Build.new(state: 'success', time: '2008-01-02')
|
260
|
+
|
261
|
+
rows = @db.view(Build.flex_with_key('2008-01-01')).raw['rows']
|
262
|
+
|
263
|
+
expect(rows.map { |row| row['id'] }).to eq(['b1'])
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'supports a given map function' do
|
267
|
+
@db.save_document Build.new(id: 'b1', time: '2008-01-01')
|
268
|
+
@db.save_document Build.new(time: '2008-01-02')
|
269
|
+
|
270
|
+
rows = @db.view(Build.flex_with_custom('2008-01-01')).raw['rows']
|
271
|
+
|
272
|
+
expect(rows.map { |row| row['id'] }).to eq(['b1'])
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'supports a given reduce function' do
|
276
|
+
@db.save_document Build.new(time: '2008-01-01')
|
277
|
+
@db.save_document Build.new(time: '2008-01-02')
|
278
|
+
|
279
|
+
raw = @db.view(Build.flex_with_custom(reduce: true)).raw
|
280
|
+
|
281
|
+
expect(raw['rows'][0]['value']).to eq(2)
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'returns ids' do
|
285
|
+
@db.save_document Build.new(id: 'b1')
|
286
|
+
@db.save_document Build.new(id: 'b2')
|
287
|
+
|
288
|
+
ids = @db.view(Build.flex_with_key).ids
|
289
|
+
|
290
|
+
expect(ids).to eq(%w[b1 b2])
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'returns keys' do
|
294
|
+
@db.save_document Build.new(time: '1')
|
295
|
+
@db.save_document Build.new(time: '2')
|
296
|
+
|
297
|
+
ids = @db.view(Build.flex_with_key).keys
|
298
|
+
|
299
|
+
expect(ids).to eq(%w[1 2])
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'returns values' do
|
303
|
+
@db.save_document Build.new(time: '1')
|
304
|
+
@db.save_document Build.new(time: '2')
|
305
|
+
|
306
|
+
ids = @db.view(Build.flex_with_key).values
|
307
|
+
|
308
|
+
expect(ids).to eq([1, 1])
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'returns docs' do
|
312
|
+
@db.save_document Build.new(time: '1')
|
313
|
+
|
314
|
+
docs = @db.view(Build.flex_with_key(include_docs: true)).docs
|
315
|
+
|
316
|
+
expect(docs.map(&:time)).to eq(['1'])
|
317
|
+
expect(docs.first.database).to eq(@db)
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'returns the value of reduce' do
|
321
|
+
@db.save_document Build.new(time: '1')
|
322
|
+
@db.save_document Build.new(time: '1')
|
323
|
+
|
324
|
+
value = @db.view(Build.flex_with_key(reduce: true)).reduce_value
|
325
|
+
|
326
|
+
expect(value).to eq(2)
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'returns the raw results' do
|
330
|
+
@db.save_document Build.new(id: 'b1', time: '1')
|
331
|
+
|
332
|
+
raw = @db.view(Build.flex_with_key).raw
|
333
|
+
|
334
|
+
expect(raw).to eq(
|
335
|
+
'total_rows' => 1, 'offset' => 0,
|
336
|
+
'rows' => [{ 'id' => 'b1', 'key' => '1', 'value' => 1 }]
|
337
|
+
)
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'returns the results via a custom method' do
|
341
|
+
@db.save_document Build.new(id: 'b1', time: '100')
|
342
|
+
@db.save_document Build.new(id: 'b2', time: '200')
|
343
|
+
|
344
|
+
custom = @db.view(Build.flex_with_key(include_docs: true)).times_to_int
|
345
|
+
|
346
|
+
expect(custom).to eq([100, 200])
|
236
347
|
end
|
237
348
|
end
|
238
349
|
|
239
|
-
describe
|
240
|
-
it
|
241
|
-
@db.save_document CustomBuild.new(:
|
350
|
+
describe 'inherited views' do
|
351
|
+
it 'should support parent views for objects of the subclass' do
|
352
|
+
@db.save_document CustomBuild.new(state: 'success', time: '2008-01-01')
|
242
353
|
expect(@db.view(CustomBuild.timeline).size).to eq(1)
|
243
354
|
expect(@db.view(CustomBuild.timeline).first).to be_kind_of(CustomBuild)
|
244
355
|
end
|
245
356
|
|
246
|
-
it
|
247
|
-
@db.save_document Build.new(:
|
248
|
-
@db.save_document CustomBuild.new(:
|
357
|
+
it 'should return instances of subclasses as well if a special view exists' do
|
358
|
+
@db.save_document Build.new(state: 'success', time: '2008-01-01')
|
359
|
+
@db.save_document CustomBuild.new(state: 'success', time: '2008-01-01', server: 'Jenkins')
|
249
360
|
results = @db.view(Build.all)
|
250
361
|
expect(results.map(&:class)).to eq([CustomBuild, Build])
|
251
362
|
end
|
252
363
|
end
|
253
364
|
|
254
|
-
describe
|
365
|
+
describe 'list functions' do
|
255
366
|
class Coworker
|
256
367
|
include CouchPotato::Persistence
|
257
368
|
|
258
369
|
property :name
|
259
370
|
|
260
|
-
view :all_with_list, :
|
261
|
-
view :all, :
|
371
|
+
view :all_with_list, key: :name, list: :append_doe
|
372
|
+
view :all, key: :name
|
262
373
|
|
263
374
|
list :append_doe, <<-JS
|
264
375
|
function(head, req) {
|
@@ -273,14 +384,14 @@ describe 'views' do
|
|
273
384
|
JS
|
274
385
|
end
|
275
386
|
|
276
|
-
it
|
277
|
-
@db.save! Coworker.new(:
|
387
|
+
it 'should use the list function declared at class level' do
|
388
|
+
@db.save! Coworker.new(name: 'joe')
|
278
389
|
expect(@db.view(Coworker.all_with_list).first.name).to eq('joe doe')
|
279
390
|
end
|
280
391
|
|
281
|
-
it
|
282
|
-
@db.save! Coworker.new(:
|
283
|
-
expect(@db.view(Coworker.all(:
|
392
|
+
it 'should use the list function passed at runtime' do
|
393
|
+
@db.save! Coworker.new(name: 'joe')
|
394
|
+
expect(@db.view(Coworker.all(list: :append_doe)).first.name).to eq('joe doe')
|
284
395
|
end
|
285
396
|
end
|
286
397
|
|
@@ -291,7 +402,7 @@ describe 'views' do
|
|
291
402
|
@db.view(Build.timeline)
|
292
403
|
@db.destroy build
|
293
404
|
|
294
|
-
expect(@db.view(Build.timeline(:
|
405
|
+
expect(@db.view(Build.timeline(stale: 'ok'))).to be_empty
|
295
406
|
end
|
296
407
|
end
|
297
408
|
end
|