mongoid-scroll 1.0.1 → 2.0.0

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.
@@ -7,19 +7,23 @@ describe Mongoid::Criteria do
7
7
  subject do
8
8
  Feed::Item.desc(:name).asc(:value)
9
9
  end
10
+
10
11
  it ':scroll' do
11
12
  expect(subject).to respond_to(:scroll)
12
13
  end
14
+
13
15
  it 'raises Mongoid::Scroll::Errors::MultipleSortFieldsError' do
14
16
  expect do
15
17
  subject.scroll(cursor_type)
16
18
  end.to raise_error Mongoid::Scroll::Errors::MultipleSortFieldsError, /You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
17
19
  end
18
20
  end
21
+
19
22
  context 'with different sort fields between the cursor and the criteria' do
20
23
  subject do
21
24
  Feed::Item.desc(:name)
22
25
  end
26
+
23
27
  it 'raises Mongoid::Scroll::Errors::MismatchedSortFieldsError' do
24
28
  record = Feed::Item.create!
25
29
  cursor = cursor_type.from_record(record, field: record.fields['a_string'])
@@ -27,16 +31,19 @@ describe Mongoid::Criteria do
27
31
  expect { subject.scroll(cursor) }.to raise_error Mongoid::Scroll::Errors::MismatchedSortFieldsError, error_string
28
32
  end
29
33
  end
34
+
30
35
  context 'with no sort' do
31
36
  subject do
32
37
  Feed::Item.all
33
38
  end
39
+
34
40
  it 'adds a default sort by _id' do
35
41
  expect(subject.scroll(cursor_type).options[:sort]).to eq('_id' => 1)
36
42
  end
37
43
  end
44
+
38
45
  context 'with data' do
39
- before :each do
46
+ before do
40
47
  10.times do |i|
41
48
  Feed::Item.create!(
42
49
  name: i.to_s,
@@ -48,30 +55,33 @@ describe Mongoid::Criteria do
48
55
  )
49
56
  end
50
57
  end
58
+
51
59
  context 'default' do
52
60
  it 'scrolls all' do
53
61
  records = []
54
- Feed::Item.all.scroll(cursor_type) do |record, _next_cursor|
62
+ Feed::Item.all.scroll(cursor_type) do |record, _iterator|
55
63
  records << record
56
64
  end
57
65
  expect(records.size).to eq 10
58
66
  expect(records).to eq Feed::Item.all.to_a
59
67
  end
68
+
60
69
  it 'does not change original criteria' do
61
70
  criteria = Feed::Item.where(:a_time.gt => Time.new(2013, 7, 22, 1, 2, 3))
62
71
  original_criteria = criteria.dup
63
72
  criteria.limit(2).scroll(cursor_type)
64
73
  expect(criteria).to eq original_criteria
65
74
  cursor = nil
66
- criteria.limit(2).scroll(cursor) do |_record, next_cursor|
67
- cursor = next_cursor
75
+ criteria.limit(2).scroll(cursor) do |_record, iterator|
76
+ cursor = iterator.next_cursor
68
77
  end
69
- criteria.scroll(cursor) do |_record, next_cursor|
70
- cursor = next_cursor
78
+ criteria.scroll(cursor) do |_record, iterator|
79
+ cursor = iterator.next_cursor
71
80
  end
72
81
  expect(criteria).to eq original_criteria
73
82
  end
74
83
  end
84
+
75
85
  context 'with a foreign key' do
76
86
  it 'sorts by object id' do
77
87
  records = []
@@ -79,92 +89,144 @@ describe Mongoid::Criteria do
79
89
  expect(records).not_to be_empty
80
90
  end
81
91
  end
92
+
82
93
  { a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
83
94
  context field_type do
84
95
  it 'scrolls all with a block' do
85
96
  records = []
86
- Feed::Item.asc(field_name).scroll(cursor_type) do |record, _next_cursor|
97
+ Feed::Item.asc(field_name).scroll(cursor_type) do |record, _iterator|
87
98
  records << record
88
99
  end
89
100
  expect(records.size).to eq 10
90
101
  expect(records).to eq Feed::Item.all.to_a
91
102
  end
103
+
92
104
  it 'scrolls all with a break' do
93
105
  records = []
94
106
  cursor = nil
95
- Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, next_cursor|
107
+ Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, iterator|
96
108
  records << record
97
- cursor = next_cursor
109
+ cursor = iterator.next_cursor
98
110
  end
99
111
  expect(records.size).to eq 5
100
- Feed::Item.asc(field_name).scroll(cursor) do |record, next_cursor|
112
+ Feed::Item.asc(field_name).scroll(cursor) do |record, iterator|
101
113
  records << record
102
- cursor = next_cursor
114
+ cursor = iterator.next_cursor
103
115
  end
104
116
  expect(records.size).to eq 10
105
117
  expect(records).to eq Feed::Item.all.to_a
106
118
  end
119
+
107
120
  it 'scrolls from a cursor' do
108
121
  last_record = nil
109
122
  cursor = nil
110
- Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, next_cursor|
123
+ Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, iterator|
111
124
  last_record = record
112
- cursor = next_cursor
125
+ cursor = iterator.next_cursor
113
126
  end
114
127
  sixth_item = Feed::Item.asc(field_name).to_a[5]
115
128
  from_item = Feed::Item.asc(field_name).scroll(cursor).to_a.first
116
129
  expect(from_item).to eq sixth_item
117
130
  end
131
+
118
132
  it 'includes the current record when Mongoid::Scroll::Cursor#include_current is true' do
119
133
  last_record = nil
120
134
  cursor = nil
121
- Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, next_cursor|
135
+ Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, iterator|
122
136
  last_record = record
123
- cursor = next_cursor
137
+ cursor = iterator.next_cursor
124
138
  end
125
139
  fifth_item = last_record
126
140
  cursor.include_current = true
127
141
  from_item = Feed::Item.asc(field_name).scroll(cursor).to_a.first
128
142
  expect(from_item).to eq fifth_item
129
143
  end
144
+
130
145
  it 'scrolls in descending order' do
131
146
  records = []
132
- Feed::Item.desc(field_name).limit(3).scroll(cursor_type) do |record, _next_cursor|
147
+ Feed::Item.desc(field_name).limit(3).scroll(cursor_type) do |record, _iterator|
133
148
  records << record
134
149
  end
135
150
  expect(records.size).to eq 3
136
151
  expect(records).to eq Feed::Item.desc(field_name).limit(3).to_a
137
152
  end
153
+
138
154
  it 'map' do
139
155
  record = Feed::Item.desc(field_name).limit(3).scroll(cursor_type).map { |r| r }.last
140
- expect(record).to_not be nil
156
+ expect(record).not_to be_nil
141
157
  cursor = cursor_type.from_record(record, field_type: field_type, field_name: field_name)
142
- expect(cursor).to_not be nil
158
+ expect(cursor).not_to be_nil
143
159
  expect(cursor.tiebreak_id).to eq record.id
144
160
  expect(cursor.value).to eq record.send(field_name)
145
161
  end
162
+
146
163
  it 'can be reused' do
147
164
  ids = Feed::Item.asc(field_name).limit(2).map(&:id)
148
- Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, cursor|
149
- cursor.include_current = true
150
- expect(Feed::Item.asc(field_name).limit(2).scroll(cursor).pluck(:id)).to eq ids
165
+ Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, iterator|
166
+ iterator.next_cursor.include_current = true
167
+ expect(Feed::Item.asc(field_name).limit(2).scroll(iterator.next_cursor).pluck(:id)).to eq ids
151
168
  break
152
169
  end
153
170
  end
171
+
154
172
  it 'can be re-created and reused' do
155
173
  ids = Feed::Item.asc(field_name).limit(2).map(&:id)
156
- Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, cursor|
157
- new_cursor = cursor_type.new(cursor.to_s, field_type: field_type, field_name: field_name)
174
+ Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, iterator|
175
+ new_cursor = cursor_type.new(iterator.next_cursor.to_s, field_type: field_type, field_name: field_name)
158
176
  new_cursor.include_current = true
159
177
  expect(Feed::Item.asc(field_name).limit(2).scroll(new_cursor).pluck(:id)).to eq ids
160
178
  break
161
179
  end
162
180
  end
181
+
182
+ it 'can scroll back with the previous cursor' do
183
+ first_iterator = nil
184
+ second_iterator = nil
185
+ third_iterator = nil
186
+
187
+ Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, iterator|
188
+ first_iterator = iterator
189
+ end
190
+
191
+ Feed::Item.asc(field_name).limit(2).scroll(first_iterator.next_cursor) do |_, iterator|
192
+ second_iterator = iterator
193
+ end
194
+
195
+ Feed::Item.asc(field_name).limit(2).scroll(second_iterator.next_cursor) do |_, iterator|
196
+ third_iterator = iterator
197
+ end
198
+
199
+ records = Feed::Item.asc(field_name)
200
+ expect(Feed::Item.asc(field_name).limit(2).scroll(second_iterator.previous_cursor)).to eq(records.limit(2))
201
+ expect(Feed::Item.asc(field_name).limit(2).scroll(third_iterator.previous_cursor)).to eq(records.skip(2).limit(2))
202
+ end
203
+
204
+ it 'can loop over the same records with the current cursor' do
205
+ current_cursor = nil
206
+ cursor = cursor_type.from_record Feed::Item.skip(4).first, field_name: field_name, field_type: field_type, include_current: true
207
+
208
+ Feed::Item.asc(field_name).limit(2).scroll(cursor) do |_, iterator|
209
+ current_cursor = iterator.current_cursor
210
+ end
211
+
212
+ expect(Feed::Item.asc(field_name).limit(2).scroll(current_cursor).to_a).to eq(Feed::Item.asc(field_name).skip(4).limit(2).to_a)
213
+ end
214
+
215
+ it 'can loop over the first records with the first page cursor' do
216
+ first_cursor = nil
217
+
218
+ Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, it|
219
+ first_cursor = it.first_cursor
220
+ end
221
+
222
+ expect(Feed::Item.asc(field_name).limit(2).scroll(first_cursor).to_a).to eq(Feed::Item.asc(field_name).limit(2).to_a)
223
+ end
163
224
  end
164
225
  end
165
226
  end
227
+
166
228
  context 'with logic in initial criteria' do
167
- before :each do
229
+ before do
168
230
  3.times do |i|
169
231
  Feed::Item.create!(
170
232
  name: "Feed Item #{i}",
@@ -184,63 +246,69 @@ describe Mongoid::Criteria do
184
246
  a_time: Time.new(2014, 2, 2, 1, 2, 3)
185
247
  )
186
248
  end
249
+
187
250
  it 'respects original criteria with OR logic' do
188
251
  criteria = Feed::Item.where(
189
252
  '$or' => [{ :a_time.gt => Time.new(2015, 7, 22, 1, 2, 3) }, { :a_time.lte => Time.new(2015, 7, 22, 1, 2, 3), :a_date.gte => Date.new(2015, 7, 30) }]
190
253
  ).asc(:a_time)
191
254
  records = []
192
255
  cursor = nil
193
- criteria.limit(2).scroll(cursor_type) do |record, next_cursor|
256
+ criteria.limit(2).scroll(cursor_type) do |record, iterator|
194
257
  records << record
195
- cursor = next_cursor
258
+ cursor = iterator.next_cursor
196
259
  end
197
260
  expect(records.size).to eq 2
198
261
  expect(records.map(&:name)).to eq ['Feed Item 0', 'Feed Item 1']
199
262
  records = []
200
- criteria.limit(2).scroll(cursor) do |record, next_cursor|
263
+ criteria.limit(2).scroll(cursor) do |record, iterator|
201
264
  records << record
202
- cursor = next_cursor
265
+ cursor = iterator.next_cursor
203
266
  end
204
267
  expect(records.size).to eq 1
205
268
  expect(records.map(&:name)).to eq ['Feed Item 2']
206
269
  end
207
270
  end
271
+
208
272
  context 'with embeddable objects' do
209
273
  before do
210
274
  @item = Feed::Item.create! a_integer: 1, name: 'item'
211
275
  @embedded_item = Feed::EmbeddedItem.create! name: 'embedded', item: @item
212
276
  end
277
+
213
278
  it 'respects embedded queries' do
214
279
  records = []
215
280
  criteria = @item.embedded_items.limit(2)
216
- criteria.scroll(cursor_type) do |record, _next_cursor|
281
+ criteria.scroll(cursor_type) do |record, _iterator|
217
282
  records << record
218
283
  end
219
284
  expect(records.size).to eq 1
220
285
  expect(records.map(&:name)).to eq ['embedded']
221
286
  end
222
287
  end
288
+
223
289
  context 'with overlapping data', if: MongoDB.mmapv1? do
224
- before :each do
290
+ before do
225
291
  3.times { Feed::Item.create! a_integer: 5 }
226
292
  Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
227
293
  end
294
+
228
295
  it 'natural order is different from order by id' do
229
296
  # natural order isn't necessarily going to be the same as _id order
230
297
  # if a document is updated and grows in size, it may need to be relocated and
231
298
  # thus cause the natural order to change
232
- expect(Feed::Item.order_by('$natural' => 1).to_a).to_not eq(Feed::Item.order_by(_id: 1).to_a)
299
+ expect(Feed::Item.order_by('$natural' => 1).to_a).not_to eq(Feed::Item.order_by(_id: 1).to_a)
233
300
  end
301
+
234
302
  [{ a_integer: 1 }, { a_integer: -1 }].each do |sort_order|
235
303
  it "scrolls by #{sort_order}" do
236
304
  records = []
237
305
  cursor = nil
238
- Feed::Item.order_by(sort_order).limit(2).scroll(cursor_type) do |record, next_cursor|
306
+ Feed::Item.order_by(sort_order).limit(2).scroll(cursor_type) do |record, iterator|
239
307
  records << record
240
- cursor = next_cursor
308
+ cursor = iterator.next_cursor
241
309
  end
242
310
  expect(records.size).to eq 2
243
- Feed::Item.order_by(sort_order).scroll(cursor) do |record, _next_cursor|
311
+ Feed::Item.order_by(sort_order).scroll(cursor) do |record, _iterator|
244
312
  records << record
245
313
  end
246
314
  expect(records.size).to eq 3
@@ -248,10 +316,12 @@ describe Mongoid::Criteria do
248
316
  end
249
317
  end
250
318
  end
319
+
251
320
  context 'with several records having the same value' do
252
- before :each do
321
+ before do
253
322
  3.times { Feed::Item.create! a_integer: 5 }
254
323
  end
324
+
255
325
  it 'returns records from the current one when Mongoid::Scroll::Cursor#include_current is true' do
256
326
  _first_item, second_item, third_item = Feed::Item.asc(:a_integer).to_a
257
327
  cursor = Mongoid::Scroll::Cursor.from_record(second_item, field: Feed::Item.fields['a_integer'])
@@ -260,6 +330,7 @@ describe Mongoid::Criteria do
260
330
  expect(items).to eq([second_item, third_item])
261
331
  end
262
332
  end
333
+
263
334
  context 'with DateTime with a milisecond precision' do
264
335
  let!(:item_1) { Feed::Item.create!(a_datetime: DateTime.new(2013, 1, 21, 1, 42, 3.1, 'UTC')) }
265
336
  let!(:item_2) { Feed::Item.create!(a_datetime: DateTime.new(2013, 1, 21, 1, 42, 3.2, 'UTC')) }
@@ -268,9 +339,9 @@ describe Mongoid::Criteria do
268
339
  it 'doesn\'t lose the precision when rebuilding the cursor' do
269
340
  records = []
270
341
  cursor = nil
271
- Feed::Item.order_by(a_datetime: 1).limit(2).scroll(cursor_type) do |record, next_cursor|
342
+ Feed::Item.order_by(a_datetime: 1).limit(2).scroll(cursor_type) do |record, iterator|
272
343
  records << record
273
- cursor = next_cursor
344
+ cursor = iterator.next_cursor
274
345
  end
275
346
  expect(records).to eq [item_1, item_2]
276
347
  cursor = cursor_type.new(cursor.to_s, field: Feed::Item.fields['a_datetime'])
@@ -5,125 +5,158 @@ describe Mongoid::Scroll::Cursor do
5
5
  subject do
6
6
  Mongoid::Scroll::Cursor.new nil, field_name: 'a_string', field_type: String
7
7
  end
8
- its(:tiebreak_id) { should be_nil }
9
- its(:value) { should be_nil }
10
- its(:criteria) { should eq({}) }
8
+
9
+ its(:tiebreak_id) { is_expected.to be_nil }
10
+ its(:value) { is_expected.to be_nil }
11
+ its(:criteria) { is_expected.to eq({}) }
11
12
  end
13
+
12
14
  context 'an invalid cursor' do
13
15
  it 'raises InvalidCursorError' do
14
16
  expect { Mongoid::Scroll::Cursor.new 'invalid', field_name: 'a_string', field_type: String }.to raise_error Mongoid::Scroll::Errors::InvalidCursorError,
15
17
  /The cursor supplied is invalid: invalid./
16
18
  end
17
19
  end
20
+
18
21
  context 'an id field cursor' do
19
- let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
20
22
  subject do
21
23
  Mongoid::Scroll::Cursor.new "#{feed_item.id}:#{feed_item.id}", field_name: '_id', field_type: BSON::ObjectId, direction: 1
22
24
  end
23
- its(:value) { should eq feed_item.id }
24
- its(:tiebreak_id) { should eq feed_item.id }
25
+
26
+ let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
27
+
28
+ its(:value) { is_expected.to eq feed_item.id }
29
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
30
+
25
31
  its(:criteria) do
26
- should eq('$or' => [
27
- { '_id' => { '$gt' => BSON::ObjectId(feed_item.id.to_s) } }
28
- ])
32
+ is_expected.to eq('$or' => [
33
+ { '_id' => { '$gt' => BSON::ObjectId(feed_item.id.to_s) } }
34
+ ])
29
35
  end
30
36
  end
37
+
31
38
  context 'a string field cursor' do
32
- let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
33
39
  subject do
34
40
  Mongoid::Scroll::Cursor.new "#{feed_item.a_string}:#{feed_item.id}", field_name: 'a_string', field_type: String
35
41
  end
36
- its(:value) { should eq feed_item.a_string }
37
- its(:tiebreak_id) { should eq feed_item.id }
42
+
43
+ let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
44
+
45
+ its(:value) { is_expected.to eq feed_item.a_string }
46
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
47
+
38
48
  its(:criteria) do
39
- should eq('$or' => [
40
- { 'a_string' => { '$gt' => feed_item.a_string } },
41
- { 'a_string' => feed_item.a_string, '_id' => { '$gt' => feed_item.id } }
42
- ])
49
+ is_expected.to eq('$or' => [
50
+ { 'a_string' => { '$gt' => feed_item.a_string } },
51
+ { 'a_string' => feed_item.a_string, '_id' => { '$gt' => feed_item.id } }
52
+ ])
43
53
  end
44
54
  end
55
+
45
56
  context 'an integer field cursor' do
46
- let(:feed_item) { Feed::Item.create!(a_integer: 10) }
47
57
  subject do
48
58
  Mongoid::Scroll::Cursor.new "#{feed_item.a_integer}:#{feed_item.id}", field_name: 'a_integer', field_type: Integer
49
59
  end
50
- its(:value) { should eq feed_item.a_integer }
51
- its(:tiebreak_id) { should eq feed_item.id }
60
+
61
+ let(:feed_item) { Feed::Item.create!(a_integer: 10) }
62
+
63
+ its(:value) { is_expected.to eq feed_item.a_integer }
64
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
65
+
52
66
  its(:criteria) do
53
- should eq('$or' => [
54
- { 'a_integer' => { '$gt' => feed_item.a_integer } },
55
- { 'a_integer' => feed_item.a_integer, '_id' => { '$gt' => feed_item.id } }
56
- ])
67
+ is_expected.to eq('$or' => [
68
+ { 'a_integer' => { '$gt' => feed_item.a_integer } },
69
+ { 'a_integer' => feed_item.a_integer, '_id' => { '$gt' => feed_item.id } }
70
+ ])
57
71
  end
58
72
  end
73
+
59
74
  context 'a date/time field cursor' do
60
- let(:feed_item) { Feed::Item.create!(a_datetime: DateTime.new(2013, 12, 21, 1, 42, 3, 'UTC')) }
61
75
  subject do
62
76
  Mongoid::Scroll::Cursor.new "#{feed_item.a_datetime.utc.to_f.round(3)}:#{feed_item.id}", field_name: 'a_datetime', field_type: DateTime
63
77
  end
64
- its(:value) { should eq feed_item.a_datetime }
65
- its(:tiebreak_id) { should eq feed_item.id }
66
- its(:to_s) { should eq "#{feed_item.a_datetime.utc.to_f.round(3)}:#{feed_item.id}" }
78
+
79
+ let(:feed_item) { Feed::Item.create!(a_datetime: DateTime.new(2013, 12, 21, 1, 42, 3, 'UTC')) }
80
+
81
+ its(:value) { is_expected.to eq feed_item.a_datetime }
82
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
83
+ its(:to_s) { is_expected.to eq "#{feed_item.a_datetime.utc.to_f.round(3)}:#{feed_item.id}" }
84
+
67
85
  its(:criteria) do
68
- should eq('$or' => [
69
- { 'a_datetime' => { '$gt' => feed_item.a_datetime } },
70
- { 'a_datetime' => feed_item.a_datetime, '_id' => { '$gt' => feed_item.id } }
71
- ])
86
+ is_expected.to eq('$or' => [
87
+ { 'a_datetime' => { '$gt' => feed_item.a_datetime } },
88
+ { 'a_datetime' => feed_item.a_datetime, '_id' => { '$gt' => feed_item.id } }
89
+ ])
72
90
  end
73
91
  end
92
+
74
93
  context 'a date field cursor' do
75
- let(:feed_item) { Feed::Item.create!(a_date: Date.new(2013, 12, 21)) }
76
94
  subject do
77
95
  Mongoid::Scroll::Cursor.new "#{feed_item.a_date.to_datetime.to_i}:#{feed_item.id}", field_name: 'a_date', field_type: Date
78
96
  end
79
- its(:value) { should eq feed_item.a_date }
80
- its(:tiebreak_id) { should eq feed_item.id }
81
- its(:to_s) { should eq "#{feed_item.a_date.to_datetime.to_i}:#{feed_item.id}" }
97
+
98
+ let(:feed_item) { Feed::Item.create!(a_date: Date.new(2013, 12, 21)) }
99
+
100
+ its(:value) { is_expected.to eq feed_item.a_date }
101
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
102
+ its(:to_s) { is_expected.to eq "#{feed_item.a_date.to_datetime.to_i}:#{feed_item.id}" }
103
+
82
104
  its(:criteria) do
83
- should eq('$or' => [
84
- { 'a_date' => { '$gt' => feed_item.a_date.to_datetime } },
85
- { 'a_date' => feed_item.a_date.to_datetime, '_id' => { '$gt' => feed_item.id } }
86
- ])
105
+ is_expected.to eq('$or' => [
106
+ { 'a_date' => { '$gt' => feed_item.a_date.to_datetime } },
107
+ { 'a_date' => feed_item.a_date.to_datetime, '_id' => { '$gt' => feed_item.id } }
108
+ ])
87
109
  end
88
110
  end
111
+
89
112
  context 'a time field cursor' do
90
- let(:feed_item) { Feed::Item.create!(a_time: Time.new(2013, 12, 21, 1, 2, 3)) }
91
113
  subject do
92
114
  Mongoid::Scroll::Cursor.new "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}", field_name: 'a_time', field_type: Time
93
115
  end
94
- its(:value) { should eq feed_item.a_time }
95
- its(:tiebreak_id) { should eq feed_item.id }
96
- its(:to_s) { should eq "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}" }
116
+
117
+ let(:feed_item) { Feed::Item.create!(a_time: Time.new(2013, 12, 21, 1, 2, 3)) }
118
+
119
+ its(:value) { is_expected.to eq feed_item.a_time }
120
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
121
+ its(:to_s) { is_expected.to eq "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}" }
122
+
97
123
  its(:criteria) do
98
- should eq('$or' => [
99
- { 'a_time' => { '$gt' => feed_item.a_time } },
100
- { 'a_time' => feed_item.a_time, '_id' => { '$gt' => feed_item.id } }
101
- ])
124
+ is_expected.to eq('$or' => [
125
+ { 'a_time' => { '$gt' => feed_item.a_time } },
126
+ { 'a_time' => feed_item.a_time, '_id' => { '$gt' => feed_item.id } }
127
+ ])
102
128
  end
103
129
  end
130
+
104
131
  context 'a time field cursor with a field option' do
105
- let(:feed_item) { Feed::Item.create!(a_time: Time.new(2013, 12, 21, 1, 2, 3)) }
106
132
  subject do
107
133
  Mongoid::Scroll::Cursor.new "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}", field: Feed::Item.fields['a_time']
108
134
  end
109
- its(:value) { should eq feed_item.a_time }
110
- its(:tiebreak_id) { should eq feed_item.id }
111
- its(:to_s) { should eq "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}" }
135
+
136
+ let(:feed_item) { Feed::Item.create!(a_time: Time.new(2013, 12, 21, 1, 2, 3)) }
137
+
138
+ its(:value) { is_expected.to eq feed_item.a_time }
139
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
140
+ its(:to_s) { is_expected.to eq "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}" }
141
+
112
142
  its(:criteria) do
113
- should eq('$or' => [
114
- { 'a_time' => { '$gt' => feed_item.a_time } },
115
- { 'a_time' => feed_item.a_time, '_id' => { '$gt' => feed_item.id } }
116
- ])
143
+ is_expected.to eq('$or' => [
144
+ { 'a_time' => { '$gt' => feed_item.a_time } },
145
+ { 'a_time' => feed_item.a_time, '_id' => { '$gt' => feed_item.id } }
146
+ ])
117
147
  end
118
148
  end
149
+
119
150
  context 'an array field cursor' do
120
151
  let(:feed_item) { Feed::Item.create!(a_array: %w[x y]) }
152
+
121
153
  it 'is not supported' do
122
154
  expect do
123
155
  Mongoid::Scroll::Cursor.from_record feed_item, field_name: 'a_array', field_type: Array
124
156
  end.to raise_error Mongoid::Scroll::Errors::UnsupportedFieldTypeError, /The type of the field 'a_array' is not supported: Array./
125
157
  end
126
158
  end
159
+
127
160
  context 'an invalid field cursor' do
128
161
  it 'raises ArgumentError' do
129
162
  expect do
@@ -131,23 +164,38 @@ describe Mongoid::Scroll::Cursor do
131
164
  end.to raise_error ArgumentError
132
165
  end
133
166
  end
134
- context 'a cursor with include_current set to true' do
167
+
168
+ context 'an invalid type cursor' do
135
169
  let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
170
+
171
+ it 'raises Mongoid::Scroll::Errors::UnsupportedTypeError' do
172
+ expect do
173
+ Mongoid::Scroll::Cursor.new "#{feed_item.a_string}:#{feed_item.id}", field_name: 'a_string', field_type: String, include_current: true, type: :invalid
174
+ end.to raise_error Mongoid::Scroll::Errors::UnsupportedTypeError, /The type supplied in the cursor is not supported: invalid./
175
+ end
176
+ end
177
+
178
+ context 'a cursor with include_current set to true' do
136
179
  subject do
137
180
  Mongoid::Scroll::Cursor.new "#{feed_item.a_string}:#{feed_item.id}", field_name: 'a_string', field_type: String, include_current: true
138
181
  end
139
- its(:value) { should eq 'astring' }
140
- its(:tiebreak_id) { should eq feed_item.id }
182
+
183
+ let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
184
+
185
+ its(:value) { is_expected.to eq 'astring' }
186
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
187
+
141
188
  its(:criteria) do
142
- should eq('$or' => [
143
- { 'a_string' => { '$gt' => 'astring' } },
144
- { '_id' => { '$gte' => BSON::ObjectId(feed_item.id.to_s) }, 'a_string' => 'astring' }
145
- ])
189
+ is_expected.to eq('$or' => [
190
+ { 'a_string' => { '$gt' => 'astring' } },
191
+ { '_id' => { '$gte' => BSON::ObjectId(feed_item.id.to_s) }, 'a_string' => 'astring' }
192
+ ])
146
193
  end
147
194
  end
195
+
148
196
  context 'criteria' do
149
197
  context 'with data' do
150
- before :each do
198
+ before do
151
199
  3.times do |i|
152
200
  Feed::Item.create!(
153
201
  name: "Feed Item #{i}",
@@ -159,6 +207,7 @@ describe Mongoid::Scroll::Cursor do
159
207
  a_time: Time.new(2014, 2, 2, 1, 2, 3)
160
208
  )
161
209
  end
210
+
162
211
  it 'merges cursor criteria when no sort field is given' do
163
212
  criteria = Feed::Item.where(:a_time.gt => Time.new(2013, 7, 22, 1, 2, 3))
164
213
  feed_item = Feed::Item.where(name: 'Feed Item 1').first
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mongoid::Scroll::VERSION do
4
- it { should_not be_nil }
4
+ it { is_expected.not_to be_nil }
5
5
  end
data/spec/spec_helper.rb CHANGED
@@ -1,12 +1,19 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
 
4
+ require 'coveralls'
5
+ Coveralls.wear! do
6
+ add_filter 'spec'
7
+ end
8
+
4
9
  require 'rubygems'
5
10
  require 'rspec'
6
11
  require 'rspec/its'
7
12
  require 'database_cleaner'
8
13
  require 'mongoid-scroll'
9
14
 
15
+ Time.zone ||= 'EST'
16
+
10
17
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each do |f|
11
18
  require f
12
19
  end
@@ -18,9 +25,9 @@ end
18
25
  RSpec.configure do |config|
19
26
  config.before :all do
20
27
  Mongoid.logger.level = Logger::INFO
21
- Mongo::Logger.logger.level = Logger::INFO if Mongoid::Compatibility::Version.mongoid5_or_newer?
28
+ Mongo::Logger.logger.level = Logger::INFO
22
29
  end
23
- config.before :each do
30
+ config.before do
24
31
  DatabaseCleaner.clean
25
32
  end
26
33
  end