mongoid-scroll 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 57a1e903af68213f7d6552ca5dc91515ef599fcd
4
- data.tar.gz: f957cb76b0556ba653b2a56d030850c07ed995c6
3
+ metadata.gz: 3c6aed40600433d3619cdc8839f6a2ad2da3b9c7
4
+ data.tar.gz: fbe2257d54b98c8aff1d8163f2a4dc15071c7d92
5
5
  SHA512:
6
- metadata.gz: e4df4fa326bfb87fa7cb41e577e4cf22010415e2cedaa74f52a7b789f72143bcc2f5c6074f3823f95705c3090fef4a75d7b365d3274a8ff640105d429918b08f
7
- data.tar.gz: cacbb8b7577052c47fac14aa4401117dfb6c05a788e900d252fac0c565d49c24b6512deb87c02f69ab3803ce4348820bdfe78e6f99309516be5d45cc9bf66229
6
+ metadata.gz: 4936c9a792ec9950a4bbd5c02c8fcc89cedc44cd1900737d6e20106ad3810f1d27b7aa9bbb230f58177a2dd10ac251bfbaec4674a5e31855c5f5bf450fd7dfbf
7
+ data.tar.gz: 5f087846be5d4870975de8841872320a6e0ce441b568e4db28526a2bb715264b92b7089aa70df9adb615d3f735b8079847472e55e9c8cd75cd0eca4b33cd01ca
@@ -4,5 +4,3 @@ AllCops:
4
4
  Exclude:
5
5
  - vendor/**/*
6
6
  - gemfiles/vendor/**/*
7
-
8
-
@@ -1,31 +1,43 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2016-09-27 11:32:40 -0700 using RuboCop version 0.43.0.
3
+ # on 2018-03-13 23:29:51 +0100 using RuboCop version 0.49.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
+ # Offense count: 6
10
+ # Configuration parameters: Include.
11
+ # Include: **/Gemfile, **/gems.rb
12
+ Bundler/DuplicatedGem:
13
+ Exclude:
14
+ - 'Gemfile'
15
+
9
16
  # Offense count: 6
10
17
  Metrics/AbcSize:
11
18
  Max: 67
12
19
 
13
- # Offense count: 6
20
+ # Offense count: 14
21
+ # Configuration parameters: CountComments, ExcludedMethods.
22
+ Metrics/BlockLength:
23
+ Max: 216
24
+
25
+ # Offense count: 5
14
26
  Metrics/CyclomaticComplexity:
15
27
  Max: 11
16
28
 
17
- # Offense count: 114
18
- # Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
29
+ # Offense count: 121
30
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
19
31
  # URISchemes: http, https
20
32
  Metrics/LineLength:
21
- Max: 170
33
+ Max: 172
22
34
 
23
35
  # Offense count: 6
24
36
  # Configuration parameters: CountComments.
25
37
  Metrics/MethodLength:
26
38
  Max: 25
27
39
 
28
- # Offense count: 4
40
+ # Offense count: 3
29
41
  Metrics/PerceivedComplexity:
30
42
  Max: 11
31
43
 
@@ -36,7 +48,7 @@ Style/Documentation:
36
48
  - 'test/**/*'
37
49
  - 'examples/mongoid_scroll_feed.rb'
38
50
  - 'lib/mongo/scrollable.rb'
39
- - 'lib/mongoid/criterion/scrollable.rb'
51
+ - 'lib/mongoid/criteria/scrollable.rb'
40
52
  - 'lib/mongoid/scroll/cursor.rb'
41
53
  - 'lib/mongoid/scroll/errors/base.rb'
42
54
  - 'lib/mongoid/scroll/errors/invalid_cursor_error.rb'
@@ -46,27 +58,21 @@ Style/Documentation:
46
58
  - 'lib/moped/scrollable.rb'
47
59
 
48
60
  # Offense count: 1
49
- # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts.
61
+ # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
62
+ # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
50
63
  Style/FileName:
51
64
  Exclude:
52
65
  - 'lib/mongoid-scroll.rb'
53
66
 
54
- # Offense count: 2
67
+ # Offense count: 1
55
68
  # Configuration parameters: MinBodyLength.
56
69
  Style/GuardClause:
57
70
  Exclude:
58
- - 'lib/mongoid/criterion/scrollable.rb'
59
71
  - 'lib/moped/scrollable.rb'
60
72
 
61
- # Offense count: 7
73
+ # Offense count: 1
62
74
  # Cop supports --auto-correct.
63
75
  # Configuration parameters: SupportedStyles.
64
76
  # SupportedStyles: compact, exploded
65
77
  Style/RaiseArgs:
66
78
  EnforcedStyle: compact
67
-
68
- # Offense count: 1
69
- # Configuration parameters: SupportedStyles.
70
- # SupportedStyles: snake_case, normalcase, non_integer
71
- Style/VariableNumber:
72
- EnforcedStyle: normalcase
@@ -26,3 +26,10 @@ matrix:
26
26
  - bundle exec danger
27
27
 
28
28
  bundler_args: --without development
29
+
30
+ addons:
31
+ apt:
32
+ sources:
33
+ - mongodb-3.4-precise
34
+ packages:
35
+ - mongodb-org-server
@@ -1,50 +1,46 @@
1
- 0.3.5 (2016/09/27)
2
- ------------------
1
+ ### 0.3.6 (2018/05/01)
2
+
3
+ * [#18](https://github.com/mongoid/mongoid-scroll/pull/18): Fix mongoid scroll without block returning wrong criteria - [@asgerb](https://github.com/asgerb).
4
+ * [#15](https://github.com/mongoid/mongoid-scroll/pull/15): Use MongoDB 3.4 in testing and fix tests w/ WiredTiger storage engine - [@dblock](https://github.com/dblock).
5
+ * [#14](https://github.com/mongoid/mongoid-scroll/pull/14): Allow scrolling by foreign key - [@joeyAghion](https://github.com/joeyAghion).
6
+
7
+ ### 0.3.5 (2016/09/27)
3
8
 
4
9
  * [#11](https://github.com/mongoid/mongoid-scroll/pull/11): Compatibility with Mongoid 6 - [@dblock](https://github.com/dblock).
5
10
  * [#12](https://github.com/mongoid/mongoid-scroll/pull/12): Added Danger, PR linter - [@dblock](https://github.com/dblock).
6
11
 
7
- 0.3.4 (2015/10/22)
8
- ------------------
12
+ ### 0.3.4 (2015/10/22)
9
13
 
10
14
  * Added support for [mongo-ruby-driver](https://github.com/mongodb/mongo-ruby-driver), `Mongo::Collection::View` - [@dblock](https://github.com/dblock).
11
15
 
12
- 0.3.3 (2015/09/17)
13
- ------------------
16
+ ### 0.3.3 (2015/09/17)
14
17
 
15
18
  * Compatibility with Mongoid 5 - [@dblock](https://github.com/dblock).
16
19
 
17
- 0.3.2 (2015/8/8)
18
- ----------------
20
+ ### 0.3.2 (2015/8/8)
19
21
 
20
22
  * [#7](https://github.com/mongoid/mongoid-scroll/pull/7): Fix: pre-merge cursor criteria fields - [@sweir27](https://github.com/sweir27).
21
23
 
22
- 0.3.1 (2015/7/27)
23
- -----------------
24
+ ### 0.3.1 (2015/7/27)
24
25
 
25
26
  * Compatibility with Mongoid 5.x beta - [@dblock](https://github.com/dblock).
26
27
  * [#4](https://github.com/mongoid/mongoid-scroll/pull/4): Fix: support chaining `$or` criteria - [@sweir27](https://github.com/sweir27).
27
28
  * [#5](https://github.com/mongoid/mongoid-scroll/pull/5): Fix: embeddable objects now returned in pagination - [@sweir27](https://github.com/sweir27).
28
29
 
29
- 0.3.0 (2014/1/7)
30
- ----------------
30
+ ### 0.3.0 (2014/1/7)
31
31
 
32
32
  * Compatibility with Mongoid 4.x - [@dblock](https://github.com/dblock).
33
33
  * Implemeneted Rubocop, Ruby linter - [@dblock](https://github.com/dblock).
34
34
 
35
- 0.2.1 (2013/3/21)
36
- -----------------
35
+ ### 0.2.1 (2013/3/21)
37
36
 
38
37
  * Fix: scroll over a collection that has duplicate values while data is being modified in a way that causes a change in the natural sort order - [@dblock](https://github.com/dblock).
39
38
 
40
- 0.2.0 (2013/3/14)
41
- -----------------
39
+ ### 0.2.0 (2013/3/14)
42
40
 
43
41
  * Extended `Moped::Query` with `scroll` - [@dblock](https://github.com/dblock).
44
42
  * `Mongoid::Scroll::Cursor.from_record` can now be called with either a Mongoid field or `field_type` and `field_name` in the `options` hash - [@dblock](https://github.com/dblock).
45
43
 
46
- 0.1.0 (2013/2/14)
47
- -----------------
44
+ ### 0.1.0 (2013/2/14)
48
45
 
49
46
  * Initial public release, extends `Mongoid::Criteria` with `scroll` - [@dblock](https://github.com/dblock).
50
-
data/Gemfile CHANGED
@@ -5,6 +5,8 @@ gemspec
5
5
  case version = ENV['MONGOID_VERSION'] || '~> 6.0'
6
6
  when 'HEAD'
7
7
  gem 'mongoid', github: 'mongodb/mongoid'
8
+ when /7/
9
+ gem 'mongoid', github: 'mongodb/mongoid', branch: '7.0-dev'
8
10
  when /6/
9
11
  gem 'mongoid', '~> 6.0'
10
12
  when /5/
@@ -18,11 +20,12 @@ else
18
20
  end
19
21
 
20
22
  group :development, :test do
21
- gem 'rake'
22
23
  gem 'bundler'
23
- gem 'rspec', '~> 3.0'
24
- gem 'rspec-its'
24
+ gem 'database_cleaner'
25
25
  gem 'faker'
26
- gem 'rubocop', '0.43.0'
27
26
  gem 'mongoid-danger', '~> 0.1.0', require: false
27
+ gem 'rake'
28
+ gem 'rspec', '~> 3.0'
29
+ gem 'rspec-its'
30
+ gem 'rubocop', '0.49.1'
28
31
  end
@@ -1,7 +1,7 @@
1
1
  Releasing Mongoid::Scroll
2
2
  =========================
3
3
 
4
- There're no particular rules about when to release mongoid-scroll. Release bug fixes frequenty, features not so frequently and breaking API changes rarely.
4
+ There're no particular rules about when to release mongoid-scroll. Release bug fixes frequently, features not so frequently and breaking API changes rarely.
5
5
 
6
6
  ### Release
7
7
 
@@ -22,11 +22,10 @@ Increment the version, modify [lib/mongoid/scroll/version.rb](lib/mongoid/scroll
22
22
  Change "Next Release" in [CHANGELOG.md](CHANGELOG.md) to the new version.
23
23
 
24
24
  ```
25
- 0.4.0 (2014-01-27)
26
- ==================
25
+ ### 0.4.0 (2018/12/24)
27
26
  ```
28
27
 
29
- Remove the line with "Your contribution here.", since there will be no more contributions to this release.
28
+ Remove the line with "* Your contribution here.", since there will be no more contributions to this release.
30
29
 
31
30
  Commit your changes.
32
31
 
@@ -52,15 +51,14 @@ Pushed mongoid-scroll 0.4.0 to rubygems.org.
52
51
  Add the next release to [CHANGELOG.md](CHANGELOG.md).
53
52
 
54
53
  ```
55
- Next Release
56
- ============
54
+ ### Next Release
57
55
 
58
56
  * Your contribution here.
59
57
  ```
60
58
 
61
59
  Increment the minor version, modify [lib/mongoid-scroll/version.rb](lib/mongoid-scroll/version.rb).
62
60
 
63
- Comit your changes.
61
+ Commit your changes.
64
62
 
65
63
  ```
66
64
  git add CHANGELOG.md lib/mongoid-scroll/version.rb
data/Rakefile CHANGED
@@ -24,4 +24,4 @@ task :spec
24
24
  require 'rubocop/rake_task'
25
25
  RuboCop::RakeTask.new(:rubocop)
26
26
 
27
- task default: [:rubocop, :spec]
27
+ task default: %i[rubocop spec]
@@ -9,4 +9,4 @@ require 'mongoid/scroll/errors'
9
9
  require 'mongoid/scroll/cursor'
10
10
  require 'moped/scrollable' if Object.const_defined?(:Moped)
11
11
  require 'mongo/scrollable' if Object.const_defined?(:Mongo)
12
- require 'mongoid/criterion/scrollable'
12
+ require 'mongoid/criteria/scrollable'
@@ -0,0 +1,81 @@
1
+ module Mongoid
2
+ class Criteria
3
+ module Scrollable
4
+ def scroll(cursor = nil, &_block)
5
+ raise_multiple_sort_fields_error if multiple_sort_fields?
6
+ criteria = dup
7
+ criteria.merge!(default_sort) if no_sort_option?
8
+ cursor_options = build_cursor_options(criteria)
9
+ cursor = cursor.is_a?(Mongoid::Scroll::Cursor) ? cursor : new_cursor(cursor, cursor_options)
10
+ cursor_criteria = build_cursor_criteria(criteria, cursor)
11
+ if block_given?
12
+ cursor_criteria.order_by(_id: scroll_direction(criteria)).each do |record|
13
+ yield record, cursor_from_record(record, cursor_options)
14
+ end
15
+ else
16
+ cursor_criteria
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def raise_multiple_sort_fields_error
23
+ raise Mongoid::Scroll::Errors::MultipleSortFieldsError.new(sort: criteria.options.sort)
24
+ end
25
+
26
+ def multiple_sort_fields?
27
+ options.sort && options.sort.keys.size != 1
28
+ end
29
+
30
+ def no_sort_option?
31
+ options.sort.blank? || options.sort.empty?
32
+ end
33
+
34
+ def default_sort
35
+ asc(:_id)
36
+ end
37
+
38
+ def scroll_field(criteria)
39
+ criteria.options.sort.keys.first
40
+ end
41
+
42
+ def scroll_direction(criteria)
43
+ criteria.options.sort.values.first.to_i
44
+ end
45
+
46
+ def build_cursor_options(criteria)
47
+ {
48
+ field_type: scroll_field_type(criteria),
49
+ field_name: scroll_field(criteria),
50
+ direction: scroll_direction(criteria)
51
+ }
52
+ end
53
+
54
+ def new_cursor(cursor, cursor_options)
55
+ Mongoid::Scroll::Cursor.new(cursor, cursor_options)
56
+ end
57
+
58
+ def build_cursor_criteria(criteria, cursor)
59
+ cursor_criteria = criteria.dup
60
+ cursor_criteria.selector = { '$and' => [criteria.selector, cursor.criteria] }
61
+ cursor_criteria
62
+ end
63
+
64
+ def cursor_from_record(record, cursor_options)
65
+ Mongoid::Scroll::Cursor.from_record(record, cursor_options)
66
+ end
67
+
68
+ def scroll_field_type(criteria)
69
+ scroll_field = scroll_field(criteria)
70
+ field = criteria.klass.fields[scroll_field.to_s]
71
+ field.foreign_key? && field.object_id_field? ? bson_type : field.type
72
+ end
73
+
74
+ def bson_type
75
+ Mongoid::Compatibility::Version.mongoid3? ? Moped::BSON::ObjectId : BSON::ObjectId
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ Mongoid::Criteria.send(:include, Mongoid::Criteria::Scrollable)
@@ -14,7 +14,7 @@ module Mongoid
14
14
  compare_direction = direction == 1 ? '$gt' : '$lt'
15
15
  cursor_criteria = { field_name => { compare_direction => mongo_value } } if mongo_value
16
16
  tiebreak_criteria = { field_name => mongo_value, :_id => { compare_direction => tiebreak_id } } if mongo_value && tiebreak_id
17
- cursor_selector = if Mongoid::Compatibility::Version.mongoid6?
17
+ cursor_selector = if Mongoid::Compatibility::Version.mongoid6? || Mongoid::Compatibility::Version.mongoid7?
18
18
  Mongoid::Criteria::Queryable::Selector.new
19
19
  else
20
20
  Origin::Selector.new
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Scroll
3
- VERSION = '0.3.5'.freeze
3
+ VERSION = '0.3.6'.freeze
4
4
  end
5
5
  end
@@ -1,124 +1,126 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Mongo::Collection::View do
4
- context 'scrollable' do
5
- subject do
6
- Mongoid.default_client['feed_items'].find
7
- end
8
- it ':scroll' do
9
- expect(subject).to respond_to(:scroll)
10
- end
11
- end
12
- context 'with multiple sort fields' do
13
- subject do
14
- Mongoid.default_client['feed_items'].find.sort(name: 1, value: -1)
15
- end
16
- it 'raises Mongoid::Scroll::Errors::MultipleSortFieldsError' do
17
- expect { subject.scroll }.to raise_error Mongoid::Scroll::Errors::MultipleSortFieldsError,
18
- /You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
19
- end
20
- end
21
- context 'with no sort' do
22
- subject do
23
- Mongoid.default_client['feed_items'].find
3
+ if Object.const_defined?(:Mongo)
4
+ describe Mongo::Collection::View do
5
+ context 'scrollable' do
6
+ subject do
7
+ Mongoid.default_client['feed_items'].find
8
+ end
9
+ it ':scroll' do
10
+ expect(subject).to respond_to(:scroll)
11
+ end
24
12
  end
25
- it 'adds a default sort by _id' do
26
- expect(subject.scroll.sort).to eq('_id' => 1)
13
+ context 'with multiple sort fields' do
14
+ subject do
15
+ Mongoid.default_client['feed_items'].find.sort(name: 1, value: -1)
16
+ end
17
+ it 'raises Mongoid::Scroll::Errors::MultipleSortFieldsError' do
18
+ expect { subject.scroll }.to raise_error Mongoid::Scroll::Errors::MultipleSortFieldsError,
19
+ /You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
20
+ end
27
21
  end
28
- end
29
- context 'with data' do
30
- before :each do
31
- 10.times do |i|
32
- Mongoid.default_client['feed_items'].insert_one(
33
- a_string: i.to_s,
34
- a_integer: i,
35
- a_datetime: DateTime.mongoize(DateTime.new(2013, i + 1, 21, 1, 42, 3, 'UTC')),
36
- a_date: Date.mongoize(Date.new(2013, i + 1, 21)),
37
- a_time: Time.mongoize(Time.at(Time.now.to_i + i))
38
- )
22
+ context 'with no sort' do
23
+ subject do
24
+ Mongoid.default_client['feed_items'].find
25
+ end
26
+ it 'adds a default sort by _id' do
27
+ expect(subject.scroll.sort).to eq('_id' => 1)
39
28
  end
40
29
  end
41
- context 'default' do
42
- it 'scrolls all' do
43
- records = []
44
- Mongoid.default_client['feed_items'].find.scroll do |record, _next_cursor|
45
- records << record
30
+ context 'with data' do
31
+ before :each do
32
+ 10.times do |i|
33
+ Mongoid.default_client['feed_items'].insert_one(
34
+ a_string: i.to_s,
35
+ a_integer: i,
36
+ a_datetime: DateTime.mongoize(DateTime.new(2013, i + 1, 21, 1, 42, 3, 'UTC')),
37
+ a_date: Date.mongoize(Date.new(2013, i + 1, 21)),
38
+ a_time: Time.mongoize(Time.at(Time.now.to_i + i))
39
+ )
46
40
  end
47
- expect(records.size).to eq 10
48
- expect(records).to eq Mongoid.default_client['feed_items'].find.to_a
49
41
  end
50
- end
51
- { a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
52
- context field_type do
53
- it 'scrolls all with a block' do
42
+ context 'default' do
43
+ it 'scrolls all' do
54
44
  records = []
55
- Mongoid.default_client['feed_items'].find.sort(field_name => 1).scroll(nil, field_type: field_type) do |record, _next_cursor|
45
+ Mongoid.default_client['feed_items'].find.scroll do |record, _next_cursor|
56
46
  records << record
57
47
  end
58
48
  expect(records.size).to eq 10
59
49
  expect(records).to eq Mongoid.default_client['feed_items'].find.to_a
60
50
  end
61
- it 'scrolls all with a break' do
51
+ end
52
+ { a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
53
+ context field_type do
54
+ it 'scrolls all with a block' do
55
+ records = []
56
+ Mongoid.default_client['feed_items'].find.sort(field_name => 1).scroll(nil, field_type: field_type) do |record, _next_cursor|
57
+ records << record
58
+ end
59
+ expect(records.size).to eq 10
60
+ expect(records).to eq Mongoid.default_client['feed_items'].find.to_a
61
+ end
62
+ it 'scrolls all with a break' do
63
+ records = []
64
+ cursor = nil
65
+ Mongoid.default_client['feed_items'].find.sort(field_name => 1).limit(5).scroll(nil, field_type: field_type) do |record, next_cursor|
66
+ records << record
67
+ cursor = next_cursor
68
+ end
69
+ expect(records.size).to eq 5
70
+ Mongoid.default_client['feed_items'].find.sort(field_name => 1).scroll(cursor, field_type: field_type) do |record, next_cursor|
71
+ records << record
72
+ cursor = next_cursor
73
+ end
74
+ expect(records.size).to eq 10
75
+ expect(records).to eq Mongoid.default_client['feed_items'].find.to_a
76
+ end
77
+ it 'scrolls in descending order' do
78
+ records = []
79
+ Mongoid.default_client['feed_items'].find.sort(field_name => -1).limit(3).scroll(nil, field_type: field_type, field_name: field_name) do |record, _next_cursor|
80
+ records << record
81
+ end
82
+ expect(records.size).to eq 3
83
+ expect(records).to eq Mongoid.default_client['feed_items'].find.sort(field_name => -1).limit(3).to_a
84
+ end
85
+ it 'map' do
86
+ record = Mongoid.default_client['feed_items'].find.limit(3).scroll(nil, field_type: field_type, field_name: field_name).map { |r| r }.last
87
+ cursor = Mongoid::Scroll::Cursor.from_record(record, field_type: field_type, field_name: field_name)
88
+ expect(cursor).to_not be nil
89
+ expect(cursor.to_s.split(':')).to eq [
90
+ Mongoid::Scroll::Cursor.transform_field_value(field_type, field_name, record[field_name.to_s]).to_s,
91
+ record['_id'].to_s
92
+ ]
93
+ end
94
+ end
95
+ end
96
+ end
97
+ context 'with overlapping data', if: MongoDB.mmapv1? do
98
+ before :each do
99
+ 3.times { Feed::Item.create! a_integer: 5 }
100
+ Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
101
+ end
102
+ it 'natural order is different from order by id' do
103
+ # natural order isn't necessarily going to be the same as _id order
104
+ # if a document is updated and grows in size, it may need to be relocated and
105
+ # thus cause the natural order to change
106
+ expect(Feed::Item.order_by('$natural' => 1).to_a).to_not eq Feed::Item.order_by(_id: 1).to_a
107
+ end
108
+ [{ a_integer: 1 }, { a_integer: -1 }].each do |sort_order|
109
+ it "scrolls by #{sort_order}" do
62
110
  records = []
63
111
  cursor = nil
64
- Mongoid.default_client['feed_items'].find.sort(field_name => 1).limit(5).scroll(nil, field_type: field_type) do |record, next_cursor|
112
+ Mongoid.default_client['feed_items'].find.sort(sort_order).limit(2).scroll do |record, next_cursor|
65
113
  records << record
66
114
  cursor = next_cursor
67
115
  end
68
- expect(records.size).to eq 5
69
- Mongoid.default_client['feed_items'].find.sort(field_name => 1).scroll(cursor, field_type: field_type) do |record, next_cursor|
70
- records << record
71
- cursor = next_cursor
72
- end
73
- expect(records.size).to eq 10
74
- expect(records).to eq Mongoid.default_client['feed_items'].find.to_a
75
- end
76
- it 'scrolls in descending order' do
77
- records = []
78
- Mongoid.default_client['feed_items'].find.sort(field_name => -1).limit(3).scroll(nil, field_type: field_type, field_name: field_name) do |record, _next_cursor|
116
+ expect(records.size).to eq 2
117
+ Mongoid.default_client['feed_items'].find.sort(sort_order).scroll(cursor) do |record, _next_cursor|
79
118
  records << record
80
119
  end
81
120
  expect(records.size).to eq 3
82
- expect(records).to eq Mongoid.default_client['feed_items'].find.sort(field_name => -1).limit(3).to_a
83
- end
84
- it 'map' do
85
- record = Mongoid.default_client['feed_items'].find.limit(3).scroll(nil, field_type: field_type, field_name: field_name).map { |r| r }.last
86
- cursor = Mongoid::Scroll::Cursor.from_record(record, field_type: field_type, field_name: field_name)
87
- expect(cursor).to_not be nil
88
- expect(cursor.to_s.split(':')).to eq [
89
- Mongoid::Scroll::Cursor.transform_field_value(field_type, field_name, record[field_name.to_s]).to_s,
90
- record['_id'].to_s
91
- ]
92
- end
93
- end
94
- end
95
- end
96
- context 'with overlapping data' do
97
- before :each do
98
- 3.times { Feed::Item.create! a_integer: 5 }
99
- Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
100
- end
101
- it 'natural order is different from order by id' do
102
- # natural order isn't necessarily going to be the same as _id order
103
- # if a document is updated and grows in size, it may need to be relocated and
104
- # thus cause the natural order to change
105
- expect(Feed::Item.order_by('$natural' => 1).to_a).to_not eq Feed::Item.order_by(_id: 1).to_a
106
- end
107
- [{ a_integer: 1 }, { a_integer: -1 }].each do |sort_order|
108
- it "scrolls by #{sort_order}" do
109
- records = []
110
- cursor = nil
111
- Mongoid.default_client['feed_items'].find.sort(sort_order).limit(2).scroll do |record, next_cursor|
112
- records << record
113
- cursor = next_cursor
114
- end
115
- expect(records.size).to eq 2
116
- Mongoid.default_client['feed_items'].find.sort(sort_order).scroll(cursor) do |record, _next_cursor|
117
- records << record
121
+ expect(records).to eq Mongoid.default_client['feed_items'].find.sort(sort_order.merge(_id: sort_order[:a_integer])).to_a
118
122
  end
119
- expect(records.size).to eq 3
120
- expect(records).to eq Mongoid.default_client['feed_items'].find.sort(sort_order.merge(_id: sort_order[:a_integer])).to_a
121
123
  end
122
124
  end
123
125
  end
124
- end if Object.const_defined?(:Mongo)
126
+ end
@@ -13,6 +13,7 @@ describe Mongoid::Criteria do
13
13
  /You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
14
14
  end
15
15
  end
16
+
16
17
  context 'with no sort' do
17
18
  subject do
18
19
  Feed::Item.all
@@ -42,7 +43,30 @@ describe Mongoid::Criteria do
42
43
  expect(records.size).to eq 10
43
44
  expect(records).to eq Feed::Item.all.to_a
44
45
  end
46
+ it 'does not change original criteria' do
47
+ criteria = Feed::Item.where(:a_time.gt => Time.new(2013, 7, 22, 1, 2, 3))
48
+ original_criteria = criteria.dup
49
+ criteria.limit(2).scroll
50
+ expect(criteria).to eq original_criteria
51
+ cursor = nil
52
+ criteria.limit(2).scroll(cursor) do |_record, next_cursor|
53
+ cursor = next_cursor
54
+ end
55
+ criteria.scroll(cursor) do |_record, next_cursor|
56
+ cursor = next_cursor
57
+ end
58
+ expect(criteria).to eq original_criteria
59
+ end
45
60
  end
61
+
62
+ context 'with a foreign key' do
63
+ it 'sorts by object id' do
64
+ records = []
65
+ Feed::Item.asc('publisher_id').scroll { |r, _| records << r }
66
+ expect(records).not_to be_empty
67
+ end
68
+ end
69
+
46
70
  { a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
47
71
  context field_type do
48
72
  it 'scrolls all with a block' do
@@ -68,6 +92,17 @@ describe Mongoid::Criteria do
68
92
  expect(records.size).to eq 10
69
93
  expect(records).to eq Feed::Item.all.to_a
70
94
  end
95
+ it 'scrolls from a cursor' do
96
+ last_record = nil
97
+ cursor = nil
98
+ Feed::Item.asc(field_name).limit(5).scroll do |record, next_cursor|
99
+ last_record = record
100
+ cursor = next_cursor
101
+ end
102
+ sixth_item = Feed::Item.asc(field_name).to_a[5]
103
+ from_item = Feed::Item.asc(field_name).scroll(cursor).to_a.first
104
+ expect(from_item).to eq sixth_item
105
+ end
71
106
  it 'scrolls in descending order' do
72
107
  records = []
73
108
  Feed::Item.desc(field_name).limit(3).scroll do |record, _next_cursor|
@@ -160,7 +195,7 @@ describe Mongoid::Criteria do
160
195
  expect(records.map(&:name)).to eq ['embedded']
161
196
  end
162
197
  end
163
- context 'with overlapping data' do
198
+ context 'with overlapping data', if: MongoDB.mmapv1? do
164
199
  before :each do
165
200
  3.times { Feed::Item.create! a_integer: 5 }
166
201
  Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
@@ -124,7 +124,7 @@ describe Mongoid::Scroll::Cursor do
124
124
  end
125
125
  end
126
126
  context 'an array field cursor' do
127
- let(:feed_item) { Feed::Item.create!(a_array: %w(x y)) }
127
+ let(:feed_item) { Feed::Item.create!(a_array: %w[x y]) }
128
128
  it 'is not supported' do
129
129
  expect do
130
130
  Mongoid::Scroll::Cursor.from_record feed_item, field_name: 'a_array', field_type: Array
@@ -1,124 +1,126 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Moped::Query do
4
- context 'scrollable' do
5
- subject do
6
- Mongoid.default_session['feed_items'].find
7
- end
8
- it ':scroll' do
9
- expect(subject).to respond_to(:scroll)
10
- end
11
- end
12
- context 'with multiple sort fields' do
13
- subject do
14
- Mongoid.default_session['feed_items'].find.sort(name: 1, value: -1)
15
- end
16
- it 'raises Mongoid::Scroll::Errors::MultipleSortFieldsError' do
17
- expect { subject.scroll }.to raise_error Mongoid::Scroll::Errors::MultipleSortFieldsError,
18
- /You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
19
- end
20
- end
21
- context 'with no sort' do
22
- subject do
23
- Mongoid.default_session['feed_items'].find
3
+ if Object.const_defined?(:Moped)
4
+ describe Moped::Query do
5
+ context 'scrollable' do
6
+ subject do
7
+ Mongoid.default_session['feed_items'].find
8
+ end
9
+ it ':scroll' do
10
+ expect(subject).to respond_to(:scroll)
11
+ end
24
12
  end
25
- it 'adds a default sort by _id' do
26
- expect(subject.scroll.operation.selector['$orderby']).to eq(_id: 1)
13
+ context 'with multiple sort fields' do
14
+ subject do
15
+ Mongoid.default_session['feed_items'].find.sort(name: 1, value: -1)
16
+ end
17
+ it 'raises Mongoid::Scroll::Errors::MultipleSortFieldsError' do
18
+ expect { subject.scroll }.to raise_error Mongoid::Scroll::Errors::MultipleSortFieldsError,
19
+ /You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
20
+ end
27
21
  end
28
- end
29
- context 'with data' do
30
- before :each do
31
- 10.times do |i|
32
- Mongoid.default_session['feed_items'].insert(
33
- a_string: i.to_s,
34
- a_integer: i,
35
- a_datetime: DateTime.mongoize(DateTime.new(2013, i + 1, 21, 1, 42, 3, 'UTC')),
36
- a_date: Date.mongoize(Date.new(2013, i + 1, 21)),
37
- a_time: Time.mongoize(Time.at(Time.now.to_i + i))
38
- )
22
+ context 'with no sort' do
23
+ subject do
24
+ Mongoid.default_session['feed_items'].find
25
+ end
26
+ it 'adds a default sort by _id' do
27
+ expect(subject.scroll.operation.selector['$orderby']).to eq(_id: 1)
39
28
  end
40
29
  end
41
- context 'default' do
42
- it 'scrolls all' do
43
- records = []
44
- Mongoid.default_session['feed_items'].find.scroll do |record, _next_cursor|
45
- records << record
30
+ context 'with data' do
31
+ before :each do
32
+ 10.times do |i|
33
+ Mongoid.default_session['feed_items'].insert(
34
+ a_string: i.to_s,
35
+ a_integer: i,
36
+ a_datetime: DateTime.mongoize(DateTime.new(2013, i + 1, 21, 1, 42, 3, 'UTC')),
37
+ a_date: Date.mongoize(Date.new(2013, i + 1, 21)),
38
+ a_time: Time.mongoize(Time.at(Time.now.to_i + i))
39
+ )
46
40
  end
47
- expect(records.size).to eq 10
48
- expect(records).to eq Mongoid.default_session['feed_items'].find.to_a
49
41
  end
50
- end
51
- { a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
52
- context field_type do
53
- it 'scrolls all with a block' do
42
+ context 'default' do
43
+ it 'scrolls all' do
54
44
  records = []
55
- Mongoid.default_session['feed_items'].find.sort(field_name => 1).scroll(nil, field_type: field_type) do |record, _next_cursor|
45
+ Mongoid.default_session['feed_items'].find.scroll do |record, _next_cursor|
56
46
  records << record
57
47
  end
58
48
  expect(records.size).to eq 10
59
49
  expect(records).to eq Mongoid.default_session['feed_items'].find.to_a
60
50
  end
61
- it 'scrolls all with a break' do
51
+ end
52
+ { a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
53
+ context field_type do
54
+ it 'scrolls all with a block' do
55
+ records = []
56
+ Mongoid.default_session['feed_items'].find.sort(field_name => 1).scroll(nil, field_type: field_type) do |record, _next_cursor|
57
+ records << record
58
+ end
59
+ expect(records.size).to eq 10
60
+ expect(records).to eq Mongoid.default_session['feed_items'].find.to_a
61
+ end
62
+ it 'scrolls all with a break' do
63
+ records = []
64
+ cursor = nil
65
+ Mongoid.default_session['feed_items'].find.sort(field_name => 1).limit(5).scroll(nil, field_type: field_type) do |record, next_cursor|
66
+ records << record
67
+ cursor = next_cursor
68
+ end
69
+ expect(records.size).to eq 5
70
+ Mongoid.default_session['feed_items'].find.sort(field_name => 1).scroll(cursor, field_type: field_type) do |record, next_cursor|
71
+ records << record
72
+ cursor = next_cursor
73
+ end
74
+ expect(records.size).to eq 10
75
+ expect(records).to eq Mongoid.default_session['feed_items'].find.to_a
76
+ end
77
+ it 'scrolls in descending order' do
78
+ records = []
79
+ Mongoid.default_session['feed_items'].find.sort(field_name => -1).limit(3).scroll(nil, field_type: field_type, field_name: field_name) do |record, _next_cursor|
80
+ records << record
81
+ end
82
+ expect(records.size).to eq 3
83
+ expect(records).to eq Mongoid.default_session['feed_items'].find.sort(field_name => -1).limit(3).to_a
84
+ end
85
+ it 'map' do
86
+ record = Mongoid.default_session['feed_items'].find.limit(3).scroll(nil, field_type: field_type, field_name: field_name).map { |r| r }.last
87
+ cursor = Mongoid::Scroll::Cursor.from_record(record, field_type: field_type, field_name: field_name)
88
+ expect(cursor).to_not be nil
89
+ expect(cursor.to_s.split(':')).to eq [
90
+ Mongoid::Scroll::Cursor.transform_field_value(field_type, field_name, record[field_name.to_s]).to_s,
91
+ record['_id'].to_s
92
+ ]
93
+ end
94
+ end
95
+ end
96
+ end
97
+ context 'with overlapping data', if: MongoDB.mmapv1? do
98
+ before :each do
99
+ 3.times { Feed::Item.create! a_integer: 5 }
100
+ Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
101
+ end
102
+ it 'natural order is different from order by id' do
103
+ # natural order isn't necessarily going to be the same as _id order
104
+ # if a document is updated and grows in size, it may need to be relocated and
105
+ # thus cause the natural order to change
106
+ expect(Feed::Item.order_by('$natural' => 1).to_a).to_not eq Feed::Item.order_by(_id: 1).to_a
107
+ end
108
+ [{ a_integer: 1 }, { a_integer: -1 }].each do |sort_order|
109
+ it "scrolls by #{sort_order}" do
62
110
  records = []
63
111
  cursor = nil
64
- Mongoid.default_session['feed_items'].find.sort(field_name => 1).limit(5).scroll(nil, field_type: field_type) do |record, next_cursor|
112
+ Mongoid.default_session['feed_items'].find.sort(sort_order).limit(2).scroll do |record, next_cursor|
65
113
  records << record
66
114
  cursor = next_cursor
67
115
  end
68
- expect(records.size).to eq 5
69
- Mongoid.default_session['feed_items'].find.sort(field_name => 1).scroll(cursor, field_type: field_type) do |record, next_cursor|
70
- records << record
71
- cursor = next_cursor
72
- end
73
- expect(records.size).to eq 10
74
- expect(records).to eq Mongoid.default_session['feed_items'].find.to_a
75
- end
76
- it 'scrolls in descending order' do
77
- records = []
78
- Mongoid.default_session['feed_items'].find.sort(field_name => -1).limit(3).scroll(nil, field_type: field_type, field_name: field_name) do |record, _next_cursor|
116
+ expect(records.size).to eq 2
117
+ Mongoid.default_session['feed_items'].find.sort(sort_order).scroll(cursor) do |record, _next_cursor|
79
118
  records << record
80
119
  end
81
120
  expect(records.size).to eq 3
82
- expect(records).to eq Mongoid.default_session['feed_items'].find.sort(field_name => -1).limit(3).to_a
83
- end
84
- it 'map' do
85
- record = Mongoid.default_session['feed_items'].find.limit(3).scroll(nil, field_type: field_type, field_name: field_name).map { |r| r }.last
86
- cursor = Mongoid::Scroll::Cursor.from_record(record, field_type: field_type, field_name: field_name)
87
- expect(cursor).to_not be nil
88
- expect(cursor.to_s.split(':')).to eq [
89
- Mongoid::Scroll::Cursor.transform_field_value(field_type, field_name, record[field_name.to_s]).to_s,
90
- record['_id'].to_s
91
- ]
92
- end
93
- end
94
- end
95
- end
96
- context 'with overlapping data' do
97
- before :each do
98
- 3.times { Feed::Item.create! a_integer: 5 }
99
- Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
100
- end
101
- it 'natural order is different from order by id' do
102
- # natural order isn't necessarily going to be the same as _id order
103
- # if a document is updated and grows in size, it may need to be relocated and
104
- # thus cause the natural order to change
105
- expect(Feed::Item.order_by('$natural' => 1).to_a).to_not eq Feed::Item.order_by(_id: 1).to_a
106
- end
107
- [{ a_integer: 1 }, { a_integer: -1 }].each do |sort_order|
108
- it "scrolls by #{sort_order}" do
109
- records = []
110
- cursor = nil
111
- Mongoid.default_session['feed_items'].find.sort(sort_order).limit(2).scroll do |record, next_cursor|
112
- records << record
113
- cursor = next_cursor
114
- end
115
- expect(records.size).to eq 2
116
- Mongoid.default_session['feed_items'].find.sort(sort_order).scroll(cursor) do |record, _next_cursor|
117
- records << record
121
+ expect(records).to eq Mongoid.default_session['feed_items'].find.sort(sort_order.merge(_id: sort_order[:a_integer])).to_a
118
122
  end
119
- expect(records.size).to eq 3
120
- expect(records).to eq Mongoid.default_session['feed_items'].find.sort(sort_order.merge(_id: sort_order[:a_integer])).to_a
121
123
  end
122
124
  end
123
125
  end
124
- end if Object.const_defined?(:Moped)
126
+ end
@@ -4,6 +4,7 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
  require 'rubygems'
5
5
  require 'rspec'
6
6
  require 'rspec/its'
7
+ require 'database_cleaner'
7
8
  require 'mongoid-scroll'
8
9
 
9
10
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each do |f|
@@ -17,9 +18,9 @@ end
17
18
  RSpec.configure do |config|
18
19
  config.before :all do
19
20
  Mongoid.logger.level = Logger::INFO
20
- Mongo::Logger.logger.level = Logger::INFO if Mongoid::Compatibility::Version.mongoid5?
21
+ Mongo::Logger.logger.level = Logger::INFO if Mongoid::Compatibility::Version.mongoid5? || Mongoid::Compatibility::Version.mongoid6?
21
22
  end
22
23
  config.before :each do
23
- Mongoid.purge!
24
+ DatabaseCleaner.clean
24
25
  end
25
26
  end
@@ -10,6 +10,10 @@ module Feed
10
10
  field :a_time, type: Time
11
11
  field :a_array, type: Array
12
12
 
13
- embeds_many :embedded_items
13
+ embeds_many :embedded_items, class_name: 'Feed::EmbeddedItem'
14
+
15
+ publisher_options = { class_name: 'Feed::Publisher' }
16
+ publisher_options[:optional] = true if Mongoid::Compatibility::Version.mongoid6? || Mongoid::Compatibility::Version.mongoid7?
17
+ belongs_to :publisher, publisher_options
14
18
  end
15
19
  end
@@ -0,0 +1,9 @@
1
+ module Feed
2
+ class Publisher
3
+ include Mongoid::Document
4
+
5
+ field :name, type: String
6
+
7
+ has_many :items
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module MongoDB
2
+ def self.mmapv1?
3
+ if Mongoid.respond_to?(:default_session)
4
+ Mongoid.default_session.command(serverStatus: 1)['storageEngine']['name'] == 'mmapv1'
5
+ else
6
+ Mongoid.default_client.command(serverStatus: 1).first['storageEngine']['name'] == 'mmapv1'
7
+ end
8
+ end
9
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-scroll
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Doubrovkine
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-09-27 00:00:00.000000000 Z
12
+ date: 2018-05-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongoid
@@ -77,7 +77,7 @@ files:
77
77
  - lib/config/locales/en.yml
78
78
  - lib/mongo/scrollable.rb
79
79
  - lib/mongoid-scroll.rb
80
- - lib/mongoid/criterion/scrollable.rb
80
+ - lib/mongoid/criteria/scrollable.rb
81
81
  - lib/mongoid/scroll/cursor.rb
82
82
  - lib/mongoid/scroll/errors.rb
83
83
  - lib/mongoid/scroll/errors/base.rb
@@ -97,6 +97,8 @@ files:
97
97
  - spec/spec_helper.rb
98
98
  - spec/support/feed/embedded_item.rb
99
99
  - spec/support/feed/item.rb
100
+ - spec/support/feed/publisher.rb
101
+ - spec/support/mongodb.rb
100
102
  homepage: http://github.com/mongoid/mongoid-scroll
101
103
  licenses:
102
104
  - MIT
@@ -117,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
119
  version: 1.3.6
118
120
  requirements: []
119
121
  rubyforge_project:
120
- rubygems_version: 2.5.1
122
+ rubygems_version: 2.6.12
121
123
  signing_key:
122
124
  specification_version: 4
123
125
  summary: Mongoid extensions to enable infinite scroll.
@@ -1,35 +0,0 @@
1
- module Mongoid
2
- module Criterion
3
- module Scrollable
4
- def scroll(cursor = nil, &_block)
5
- criteria = self
6
- # we don't support scrolling over a criteria with multiple fields
7
- if criteria.options[:sort] && criteria.options[:sort].keys.size != 1
8
- raise Mongoid::Scroll::Errors::MultipleSortFieldsError.new(sort: criteria.options[:sort])
9
- elsif !criteria.options.key?(:sort) || criteria.options[:sort].empty?
10
- # introduce a default sort order if there's none
11
- criteria = criteria.asc(:_id)
12
- end
13
- # scroll field and direction
14
- scroll_field = criteria.options[:sort].keys.first
15
- scroll_direction = criteria.options[:sort].values.first.to_i
16
- # scroll cursor from the parameter, with value and tiebreak_id
17
- field = criteria.klass.fields[scroll_field.to_s]
18
- cursor_options = { field_type: field.type, field_name: scroll_field, direction: scroll_direction }
19
- cursor = cursor.is_a?(Mongoid::Scroll::Cursor) ? cursor : Mongoid::Scroll::Cursor.new(cursor, cursor_options)
20
- # scroll
21
- if block_given?
22
- cursor_criteria = criteria.dup
23
- cursor_criteria.selector = { '$and' => [criteria.selector, cursor.criteria] }
24
- cursor_criteria.order_by(_id: scroll_direction).each do |record|
25
- yield record, Mongoid::Scroll::Cursor.from_record(record, cursor_options)
26
- end
27
- else
28
- criteria
29
- end
30
- end
31
- end
32
- end
33
- end
34
-
35
- Mongoid::Criteria.send(:include, Mongoid::Criterion::Scrollable)