mongoid_orderable 5.0.0 → 6.0.2

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.
Files changed (71) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +83 -22
  3. data/LICENSE.txt +20 -0
  4. data/README.md +256 -149
  5. data/Rakefile +24 -6
  6. data/lib/config/locales/en.yml +12 -9
  7. data/lib/mongoid/orderable.rb +29 -22
  8. data/lib/mongoid/orderable/configs/field_config.rb +79 -0
  9. data/lib/mongoid/orderable/configs/global_config.rb +26 -0
  10. data/lib/mongoid/orderable/errors/invalid_target_position.rb +19 -18
  11. data/lib/mongoid/orderable/errors/transaction_failed.rb +20 -0
  12. data/lib/mongoid/orderable/generators/base.rb +21 -0
  13. data/lib/mongoid/orderable/generators/helpers.rb +29 -0
  14. data/lib/mongoid/orderable/generators/listable.rb +41 -0
  15. data/lib/mongoid/orderable/generators/lock_collection.rb +37 -0
  16. data/lib/mongoid/orderable/generators/movable.rb +62 -0
  17. data/lib/mongoid/orderable/generators/position.rb +26 -0
  18. data/lib/mongoid/orderable/generators/scope.rb +26 -0
  19. data/lib/mongoid/orderable/handlers/base.rb +167 -0
  20. data/lib/mongoid/orderable/handlers/document.rb +24 -0
  21. data/lib/mongoid/orderable/handlers/document_embedded.rb +14 -0
  22. data/lib/mongoid/orderable/handlers/document_transactional.rb +35 -0
  23. data/lib/mongoid/orderable/handlers/transaction.rb +71 -0
  24. data/lib/mongoid/orderable/installer.rb +63 -0
  25. data/lib/mongoid/orderable/mixins/callbacks.rb +43 -0
  26. data/lib/mongoid/orderable/mixins/helpers.rb +39 -0
  27. data/lib/mongoid/orderable/mixins/listable.rb +49 -0
  28. data/lib/mongoid/orderable/mixins/movable.rb +60 -0
  29. data/lib/mongoid/orderable/version.rb +7 -0
  30. data/lib/mongoid_orderable.rb +33 -54
  31. data/spec/integration/concurrency_spec.rb +232 -0
  32. data/spec/integration/customized_spec.rb +31 -0
  33. data/spec/integration/embedded_spec.rb +41 -0
  34. data/spec/integration/foreign_key_spec.rb +33 -0
  35. data/spec/integration/inherited_spec.rb +54 -0
  36. data/spec/integration/multiple_fields_spec.rb +554 -0
  37. data/spec/integration/multiple_scoped_spec.rb +63 -0
  38. data/spec/integration/no_indexed_spec.rb +23 -0
  39. data/spec/integration/scoped_spec.rb +151 -0
  40. data/spec/integration/simple_spec.rb +184 -0
  41. data/spec/integration/string_scoped_spec.rb +28 -0
  42. data/spec/integration/zero_based_spec.rb +161 -0
  43. data/spec/spec_helper.rb +42 -30
  44. data/spec/support/models.rb +122 -0
  45. metadata +75 -41
  46. data/.gitignore +0 -4
  47. data/.rspec +0 -2
  48. data/.rvmrc +0 -1
  49. data/.travis.yml +0 -14
  50. data/Gemfile +0 -18
  51. data/lib/mongoid/orderable/callbacks.rb +0 -75
  52. data/lib/mongoid/orderable/configuration.rb +0 -60
  53. data/lib/mongoid/orderable/errors.rb +0 -2
  54. data/lib/mongoid/orderable/errors/mongoid_orderable_error.rb +0 -14
  55. data/lib/mongoid/orderable/generator.rb +0 -34
  56. data/lib/mongoid/orderable/generator/helpers.rb +0 -29
  57. data/lib/mongoid/orderable/generator/listable.rb +0 -41
  58. data/lib/mongoid/orderable/generator/movable.rb +0 -62
  59. data/lib/mongoid/orderable/generator/position.rb +0 -26
  60. data/lib/mongoid/orderable/generator/scope.rb +0 -17
  61. data/lib/mongoid/orderable/helpers.rb +0 -50
  62. data/lib/mongoid/orderable/listable.rb +0 -49
  63. data/lib/mongoid/orderable/movable.rb +0 -58
  64. data/lib/mongoid/orderable/orderable_class.rb +0 -51
  65. data/lib/mongoid_orderable/mongoid/contexts/enumerable.rb +0 -15
  66. data/lib/mongoid_orderable/mongoid/contexts/mongo.rb +0 -18
  67. data/lib/mongoid_orderable/mongoid/contextual/memory.rb +0 -15
  68. data/lib/mongoid_orderable/mongoid/criteria.rb +0 -4
  69. data/lib/mongoid_orderable/version.rb +0 -3
  70. data/mongoid_orderable.gemspec +0 -26
  71. data/spec/mongoid/orderable_spec.rb +0 -1413
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a966ef4b59309d05845a832163936ce54e339a1e
4
- data.tar.gz: 16b32ccd0fdb0a2ae9a61424d8842de9eba00d4e
2
+ SHA256:
3
+ metadata.gz: b3a80c8eb058adeffe1ead4c0fa20ce10660ea49a2df1405d46048419f2af965
4
+ data.tar.gz: d68f6f64f52f132295e588dfcd59ad27d22a68237e5b29ab7682a37e3c940ca5
5
5
  SHA512:
6
- metadata.gz: ee3e6de12801d857bb9345dc6035c698c56ee119f9b2e78fc15584caf6108351904487b888fa2091636bc750be62e6076b06bf74f38f44b2bd2fa68bc36611ac
7
- data.tar.gz: 5fc8fe3f744fff60b38ac3d0136dcc5c84c069042beda3a7c623c9d6da743e67219e29da920bd983d4a5f506f081cbac9614e14630647dbc58593fa3dfb877d9
6
+ metadata.gz: 6c2d9da294dda836b17047aaf3ebc6329b3c382fb793c83fe57dd63a07512d2e1da65af3559b12e75ce3924b1edfaaefad8317f4acaa488cb94ad2392d84b474
7
+ data.tar.gz: 58e8c15554183674cef20639c2cb888cb6e793471ecf7f55ea76360f2ca7de351d218f417e34db220d2daa32c6ab5dc11da23bce7acec0f77a1f99718e713705
@@ -1,22 +1,83 @@
1
- # master
2
-
3
- # 5.0.0
4
-
5
- * Mongoid 5 support (@dblock)
6
- * Ruby 1.8 support dropped
7
-
8
- # 4.1.1
9
-
10
- * Fix: index should respect scope (@joeyAghion)
11
-
12
- # 4.1.0
13
-
14
- * Resolving scope foreign key form passed relation name (@dsci)
15
- * Fix: relation metadata quering (@pjkelly)
16
- * `previous_items` and `next_items` methods (@mrjlynch)
17
-
18
- # 4.0.0
19
-
20
- * Semantic versioning
21
- * Added Mongoid 4 support (@dblock)
22
- * Fixes by @johnnyshields and @zhengjia
1
+ ### 6.0.3 (Next)
2
+
3
+ * Your contribution here.
4
+
5
+ ### 6.0.2 (2021/01/26)
6
+
7
+ * [#70](https://github.com/mongoid/mongoid_orderable/pull/70): Fix: Transactions should not use around callbacks - [@johnnyshields](https://github.com/johnnyshields).
8
+ * [#70](https://github.com/mongoid/mongoid_orderable/pull/70): Refactor: Partially reduce code complexity of handler classes - [@johnnyshields](https://github.com/johnnyshields).
9
+ * [#70](https://github.com/mongoid/mongoid_orderable/pull/70): Tests: Run all tests both with and without transactions - [@johnnyshields](https://github.com/johnnyshields).
10
+
11
+ ### 6.0.1 (2021/01/26)
12
+
13
+ * [#69](https://github.com/mongoid/mongoid_orderable/pull/69): Fix: Transactions should force read from primary - [@johnnyshields](https://github.com/johnnyshields).
14
+
15
+ ### 6.0.0 (2021/01/23)
16
+
17
+ * [#65](https://github.com/mongoid/mongoid_orderable/pull/65): Feature: Add transaction support with lock table - [@johnnyshields](https://github.com/johnnyshields).
18
+ * [#65](https://github.com/mongoid/mongoid_orderable/pull/65): Feature: Avoid calling position function if neither position nor scope is changing - [@johnnyshields](https://github.com/johnnyshields).
19
+ * [#62](https://github.com/mongoid/mongoid_orderable/pull/62): Feature: Allow scope parameter to be an Array - [@johnnyshields](https://github.com/johnnyshields).
20
+ * [#62](https://github.com/mongoid/mongoid_orderable/pull/62): Feature: Add global configurability - [@johnnyshields](https://github.com/johnnyshields).
21
+ * [#65](https://github.com/mongoid/mongoid_orderable/pull/65): Fix: Do not run embedded destroy callbacks when the root object has been destroyed - [@johnnyshields](https://github.com/johnnyshields).
22
+ * [#62](https://github.com/mongoid/mongoid_orderable/pull/62): Refactor: rename "column" to "field" - [@johnnyshields](https://github.com/johnnyshields).
23
+ * [#60](https://github.com/mongoid/mongoid_orderable/pull/60): Refactor: Drop support for Mongoid 6.x and lower - [@johnnyshields](https://github.com/johnnyshields).
24
+ * [#60](https://github.com/mongoid/mongoid_orderable/pull/60): Refactor: Remove Mongoid Compatibility (no longer needed) - [@johnnyshields](https://github.com/johnnyshields).
25
+
26
+ ### 5.2.0 (2018/05/01)
27
+
28
+ * [#57](https://github.com/mongoid/mongoid_orderable/pull/57): Compatibility with Mongoid 7 - [@tomasc](https://github.com/tomasc).
29
+ * [#52](https://github.com/mongoid/mongoid_orderable/pull/52): Test against Mongoid 6 - [@dblock](https://github.com/dblock).
30
+
31
+ ### 5.1.0 (2017/06/04)
32
+
33
+ * [#50](https://github.com/mongoid/mongoid_orderable/pull/50): Added Danger, PR linter - [@dblock](https://github.com/dblock).
34
+ * [#51](https://github.com/mongoid/mongoid_orderable/pull/51): Added RuboCop - [@dblock](https://github.com/dblock).
35
+ * [#49](https://github.com/mongoid/mongoid_orderable/pull/49): Fix orderable on embedded documents inside an inherited model - [@rafaelgaspar](https://github.com/rafaelgaspar).
36
+
37
+ ### 5.0.0 (2015/10/21)
38
+
39
+ * [#41](https://github.com/mongoid/mongoid_orderable/pull/41): Mongoid 5 support - [@dblock](https://github.com/dblock).
40
+ * [#41](https://github.com/mongoid/mongoid_orderable/pull/41): Dropped support for ruby 1.8 - [@dblock](https://github.com/dblock).
41
+
42
+ ### 4.1.1 (2014/12/19)
43
+
44
+ * [#34](https://github.com/mongoid/mongoid_orderable/pull/34): Fix: index should respect scope - [@joeyAghion](https://github.com/joeyAghion).
45
+
46
+ ### 4.1.0 (2014/3/19)
47
+
48
+ * [#30](https://github.com/mongoid/mongoid_orderable/pull/30): Fix: reset a single field when `orderable_scope` changed instead of removing it from list - [@Bharat311](https://github.com/Bharat311).
49
+ * [#29](https://github.com/mongoid/mongoid_orderable/pull/29): Fix: incorrect position when orderable base is set - [@Bharat311](https://github.com/Bharat311).
50
+ * [#28](https://github.com/mongoid/mongoid_orderable/pull/28): Inherited `orderable_configurations` - [@johnny-miyake](https://github.com/johnny-miyake).
51
+ * [#27](https://github.com/mongoid/mongoid_orderable/pull/27): Allowed numeric string to specify a target position - [@johnny-miyake](https://github.com/johnny-miyake).
52
+ * [#26](https://github.com/mongoid/mongoid_orderable/pull/26): Added support for multiple orderable fields - [@Bharat311](https://github.com/Bharat311).
53
+ * [#22](https://github.com/mongoid/mongoid_orderable/pull/22): Added lazy support for scopes with different foreign key names - [@dsci](https://github.com/dsci).
54
+ * [#21](https://github.com/mongoid/mongoid_orderable/pull/21): Accounting for change in Mongoid's metadata API - [@pjkelly](https://github.com/pjkelly).
55
+ * [#20](https://github.com/mongoid/mongoid_orderable/pull/20): Added next and previous item methods - [@mrjlynch](https://github.com/mrjlynch).
56
+ * [#19](https://github.com/mongoid/mongoid_orderable/pull/19): Added lower and higher item methods - [@mrjlynch](https://github.com/mrjlynch).
57
+
58
+ ### 4.0.0 (2013/10/22)
59
+
60
+ * [#18](https://github.com/mongoid/mongoid_orderable/pull/18): Added Mongoid 4 support - [@dblock](https://github.com/dblock).
61
+ * [#16](https://github.com/mongoid/mongoid_orderable/pull/16): Fix for Mongoid identity map combined with scoped orderable - [@johnnyshields](https://github.com/johnnyshields).
62
+ * [#15](https://github.com/mongoid/mongoid_orderable/pull/15): Support pass-thru of Mongoid field alias (`:as` parameter) - [@johnnyshields](https://github.com/johnnyshields).
63
+ * [#13](https://github.com/mongoid/mongoid_orderable/pull/13): Support inheritance - [@zhengjia](https://github.com/zhengjia).
64
+
65
+ ### 1.2.0 (2013/1/10)
66
+
67
+ * [#12](https://github.com/mongoid/mongoid_orderable/pull/12): Added support for "base" in config options, in order to do a zero-based position - [@johnnyshields](https://github.com/johnnyshields).
68
+
69
+ ### 1.1.0 (2012/5/23)
70
+
71
+ * Added Mongoid 3 support - [@pyromaniac](https://github.com/pyromaniac).
72
+
73
+ ### 1.0.0 (2012/2/14)
74
+
75
+ * [#5](https://github.com/mongoid/mongoid_orderable/pull/5): Allow for use with default scopes - [@mattiassvedhem](https://github.com/mattiassvedhem).
76
+
77
+ ### 0.9.1 (2012/2/3)
78
+
79
+ ### 0.9.0 (2011/11/23)
80
+
81
+ ### 0.0.1 (2011/11/1)
82
+
83
+ * Initial public release - [@pyromaniac](https://github.com/pyromaniac).
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011-2017 Arkadiy Zabazhanov & Contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,149 +1,256 @@
1
- [![Gem Version](https://badge.fury.io/rb/mongoid_orderable.svg)](https://badge.fury.io/rb/mongoid_orderable)
2
- [![Build Status](https://travis-ci.org/pyromaniac/mongoid_orderable.svg?branch=master)](https://travis-ci.org/pyromaniac/mongoid_orderable)
3
-
4
- # What?
5
-
6
- Mongoid::Orderable is a ordered list implementation for your Mongoid 2, 3, 4 and 5 models.
7
-
8
- # Why?
9
-
10
- * It uses native mongo batch increment feature
11
- * It supports mutators api
12
- * It correctly assigns the position while moving document between scopes
13
- * It supports mongoid 2, 3 and 4
14
- * It supports specifying multiple orderable columns
15
-
16
- # How?
17
-
18
- ```ruby
19
- gem 'mongoid_orderable'
20
- ```
21
-
22
- Gem has the same api as others. Just include Mongoid::Orderable into your model and call `orderable` method.
23
- Embedded objects are automatically scoped by their parent.
24
-
25
- ```ruby
26
- class Item
27
- include Mongoid::Document
28
- include Mongoid::Orderable
29
-
30
- # belongs_to :group
31
- # belongs_to :drawer, class_name: "Office::Drawer",
32
- # foreign_key: "legacy_drawer_key_id"
33
-
34
- # orderable
35
- # orderable scope: :group, column: :pos
36
- # orderable scope: :drawer, column: :pos # resolves scope foreign key from relation
37
- # orderable scope: 'drawer', column: :pos # but if you pass a string - it will use it as is, as the column name for scope
38
- # orderable scope: lambda { |document| where(group_id: document.group_id) }
39
- # orderable index: false # this one if you want specify indexes manually
40
- # orderable base: 0 # count position from zero as the top-most value (1 is the default value)
41
- end
42
- ```
43
-
44
- # Usage
45
-
46
- ```ruby
47
- item.move_to 2 # just change position
48
- item.move_to! 2 # and save
49
- item.move_to = 2 # assignable method
50
-
51
- # symbol position
52
- item.move_to :top
53
- item.move_to :bottom
54
- item.move_to :higher
55
- item.move_to :lower
56
-
57
- # generated methods
58
- item.move_to_top
59
- item.move_to_bottom
60
- item.move_higher
61
- item.move_lower
62
-
63
- item.next_items # return a collection of items higher on the list
64
- item.previous_items # return a collection of items lower on the list
65
-
66
- item.next_item # returns the next item in the list
67
- item.previous_item # returns the previous item in the list
68
- ```
69
-
70
- # Multiple Columns
71
-
72
- You can also define multiple orderable columns for any class including the Mongoid::Orderable module.
73
-
74
- ```ruby
75
- class Book
76
- include Mongoid::Document
77
- include Mongoid::Orderable
78
-
79
- orderable base: 0
80
- orderable column: sno, as: :serial_no
81
- end
82
- ```
83
-
84
- The above defines two different orderable_columns on Book - *position* and *serial_no*.
85
- The following helpers are generated in this case:
86
-
87
- ```ruby
88
- item.move_#{column_name}_to
89
- item.move_#{column_name}_to=
90
- item.move_#{column_name}_to!
91
-
92
- item.move_#{column_name}_to_top
93
- item.move_#{column_name}_to_bottom
94
- item.move_#{column_name}_higher
95
- item.move_#{column_name}_lower
96
-
97
- item.next_#{column_name}_items
98
- item.previous_#{column_name}_items
99
-
100
- item.next_#{column_name}_item
101
- item.previous_#{column_name}_item
102
- ```
103
-
104
- *where column_name is either **position** or **serial_no**.*
105
-
106
- When a model defines multiple orderable columns, the original helpers are also available and work on the first orderable column.
107
-
108
- ```ruby
109
- @book1 = Book.create!
110
- @book2 = Book.create!
111
- @book2 => #<Book _id: 53a16a2ba1bde4f746000001, serial_no: 1, position: 1>
112
- @book2.move_to! :top # this will change the :position of the book to 0 (not serial_no)
113
- @book2 => #<Book _id: 53a16a2ba1bde4f746000001, serial_no: 1, position: 0>
114
- ```
115
-
116
- To specify any other orderable column as default pass the **default: true** option with orderable.
117
-
118
- ```ruby
119
- orderable column: sno, as: :serial_no, default: true
120
- ```
121
-
122
- # Embedded documents
123
- ```ruby
124
- class Question
125
- include Mongoid::Document
126
- include Mongoid::Orderable
127
-
128
- embedded_in :survey
129
-
130
- orderable
131
- end
132
- ```
133
- If you bulk import embedded documents without specifying their position, no field `position` will be written.
134
- ```ruby
135
- class Survey
136
- include Mongoid::Document
137
-
138
- embeds_many :questions, cascade_callbacks: true
139
- end
140
- ```
141
- To ensure the position is written correctly, you will need to provide the cascade callbacks option to the relation.
142
-
143
- # Contributing
144
-
145
- Fork && Patch && Spec && Push && Pull request.
146
-
147
- # License
148
-
149
- Mongoid::Orderable is released under the MIT license.
1
+ [![Gem Version](https://badge.fury.io/rb/mongoid_orderable.svg)](https://badge.fury.io/rb/mongoid_orderable)
2
+ [![Build Status](https://travis-ci.org/mongoid/mongoid_orderable.svg?branch=master)](https://travis-ci.org/mongoid/mongoid_orderable)
3
+
4
+ # Mongoid Orderable
5
+
6
+ Mongoid::Orderable is a ordered list implementation for your Mongoid 7+ projects.
7
+
8
+ ### Core Features
9
+
10
+ * Sets a position index field on your documents which allows you to sort them in order.
11
+ * Uses MongoDB's `$inc` operator to batch-update position.
12
+ * Supports scope for position index, including changing scopes.
13
+ * Supports multiple position indexes on the same document.
14
+ * (Optional) Uses [MongoDB transactions](https://docs.mongodb.com/manual/core/transactions/) to ensure order integrity during concurrent updates.
15
+
16
+ ### Version Support
17
+
18
+ As of version 6.0.0, Mongoid::Orderable supports the following dependency versions:
19
+
20
+ * Ruby 2.6+
21
+ * Mongoid 7.0+
22
+ * Rails 5.2+
23
+
24
+ For older versions, please use Mongoid::Orderable 5.x and earlier.
25
+
26
+ Transaction support requires MongoDB 4.2+ (4.4+ recommended.)
27
+
28
+ ## Usage
29
+
30
+ ### Getting Started
31
+
32
+ ```ruby
33
+ gem 'mongoid_orderable'
34
+ ```
35
+
36
+ Include `Mongoid::Orderable` into your model and call `orderable` method.
37
+ Embedded objects are automatically scoped to their parent.
38
+
39
+ ```ruby
40
+ class MyModel
41
+ include Mongoid::Document
42
+ include Mongoid::Orderable
43
+
44
+ belongs_to :group
45
+ belongs_to :drawer, class_name: "Office::Drawer",
46
+ foreign_key: "legacy_drawer_key_id"
47
+
48
+ orderable
49
+
50
+ # if you set :scope as a symbol, it will resolve the foreign key from relation
51
+ orderable scope: :drawer, field: :pos
52
+
53
+ # if you set :scope as a string, it will use it as the field name for scope
54
+ orderable scope: 'drawer', field: :pos
55
+
56
+ # scope can also be a proc
57
+ orderable scope: ->(doc) { where(group_id: doc.group_id) }
58
+
59
+ # this one if you want specify indexes manually
60
+ orderable index: false
61
+
62
+ # count position from zero as the top-most value (1 is the default value)
63
+ orderable base: 0
64
+ end
65
+ ```
66
+
67
+ You can also set default config values in an initializer, which will be
68
+ applied when calling the `orderable` macro in a model.
69
+
70
+ ```ruby
71
+ # configs/initializers/mongoid_orderable.rb
72
+ Mongoid::Orderable.configure do |config|
73
+ config.field = :pos
74
+ config.base = 0
75
+ config.index = false
76
+ end
77
+ ```
78
+
79
+ ### Moving Position
80
+
81
+ ```ruby
82
+ item.move_to 2 # just change position
83
+ item.move_to! 2 # and save
84
+ item.move_to = 2 # assignable method
85
+
86
+ # symbol position
87
+ item.move_to :top
88
+ item.move_to :bottom
89
+ item.move_to :higher
90
+ item.move_to :lower
91
+
92
+ # generated methods
93
+ item.move_to_top
94
+ item.move_to_bottom
95
+ item.move_higher
96
+ item.move_lower
97
+
98
+ item.next_items # return a collection of items higher on the list
99
+ item.previous_items # return a collection of items lower on the list
100
+
101
+ item.next_item # returns the next item in the list
102
+ item.previous_item # returns the previous item in the list
103
+ ```
104
+
105
+ ### Multiple Fields
106
+
107
+ You can also define multiple orderable fields for any class including the Mongoid::Orderable module.
108
+
109
+ ```ruby
110
+ class Book
111
+ include Mongoid::Document
112
+ include Mongoid::Orderable
113
+
114
+ orderable base: 0
115
+ orderable field: sno, as: :serial_no
116
+ end
117
+ ```
118
+
119
+ The above defines two different orderable_fields on Book - *position* and *serial_no*.
120
+ The following helpers are generated in this case:
121
+
122
+ ```ruby
123
+ book.move_#{field}_to
124
+ book.move_#{field}_to=
125
+ book.move_#{field}_to!
126
+
127
+ book.move_#{field}_to_top
128
+ book.move_#{field}_to_bottom
129
+ book.move_#{field}_higher
130
+ book.move_#{field}_lower
131
+
132
+ book.next_#{field}_items
133
+ book.previous_#{field}_items
134
+
135
+ book.next_#{field}_item
136
+ book.previous_#{field}_item
137
+ ```
138
+
139
+ where `#{field}` is either `position` or `serial_no`.
140
+
141
+ When a model defines multiple orderable fields, the original helpers are also available and work on the first orderable field.
142
+
143
+ ```ruby
144
+ @book1 = Book.create!
145
+ @book2 = Book.create!
146
+ @book2 # => <Book _id: 53a16a2ba1bde4f746000001, serial_no: 1, position: 1>
147
+ @book2.move_to! :top # this will change the :position of the book to 0 (not serial_no)
148
+ @book2 # => <Book _id: 53a16a2ba1bde4f746000001, serial_no: 1, position: 0>
149
+ ```
150
+
151
+ To specify any other orderable field as default pass the **default: true** option with orderable.
152
+
153
+ ```ruby
154
+ orderable field: sno, as: :serial_no, default: true
155
+ ```
156
+
157
+ ### Embedded Documents
158
+
159
+ ```ruby
160
+ class Question
161
+ include Mongoid::Document
162
+ include Mongoid::Orderable
163
+
164
+ embedded_in :survey
165
+
166
+ orderable
167
+ end
168
+ ```
169
+
170
+ If you bulk import embedded documents without specifying their position,
171
+ no field `position` will be written.
172
+
173
+ ```ruby
174
+ class Survey
175
+ include Mongoid::Document
176
+
177
+ embeds_many :questions, cascade_callbacks: true
178
+ end
179
+ ```
180
+
181
+ To ensure the position is written correctly, you will need to set
182
+ `cascade_callbacks: true` on the relation.
183
+
184
+ ## Transaction Support
185
+
186
+ By default, Mongoid Orderable does not guarantee ordering consistency
187
+ when doing multiple concurrent updates on documents. This means that
188
+ instead of having positions `1, 2, 3, 4, 5`, after running your system
189
+ in production at scale your position data will become corrupted, e.g.
190
+ `1, 1, 4, 4, 6`. To remedy this, this Mongoid Orderable can use
191
+ [MongoDB transactions](https://docs.mongodb.com/manual/core/transactions/)
192
+
193
+ ### Prerequisites
194
+
195
+ * MongoDB version 4.2+ (4.4+ recommended.)
196
+ * Requires [MongoDB Replica Set](https://docs.mongodb.com/manual/tutorial/deploy-replica-set/) topology
197
+
198
+ ### Configuration
199
+
200
+ You may enable transactions on both the global and model configs:
201
+
202
+ ```ruby
203
+ Mongoid::Orderable.configure do |config|
204
+ config.use_transactions = true # default: false
205
+ config.transaction_max_retries = 10 # default: 10
206
+ end
207
+
208
+ class MyModel
209
+ orderable :position, use_transactions: false
210
+ end
211
+ ```
212
+
213
+ When two transactions are attempted at the same time, database-level
214
+ `WriteConflict` failures may result and retries will be attempted.
215
+ After `transaction_max_retries` has been exceeded, a
216
+ `Mongoid::Orderable::Errors::TransactionFailed` error will be raised.
217
+
218
+ ### Locks
219
+
220
+ When using transactions, Mongoid Orderable creates a collection
221
+ `mongoid_orderable_locks` which is used to store temporary lock objects.
222
+ This collection accumulate documents overtime; it is safe to delete it periodically.
223
+
224
+ You can change the lock collection name globally or per model:
225
+
226
+ ```ruby
227
+ Mongoid::Orderable.configure do |config|
228
+ config.lock_collection = "my_locks" # default: "mongoid_orderable_locks"
229
+ end
230
+
231
+ class MyModel
232
+ orderable :position, lock_collection: "my_model_locks"
233
+ end
234
+ ```
235
+
236
+ ### MongoDB 4.2 Support
237
+
238
+ In MongoDB 4.2, collections cannot be created within transactions.
239
+ Therefore, you will need to manually run the following command once
240
+ to initialize the lock collection:
241
+
242
+ ```ruby
243
+ Mongoid::Orderable::Models::Lock.create!
244
+ ```
245
+
246
+ This step is not necessary when using MongoDB 4.4+.
247
+
248
+ ### Contributing
249
+
250
+ Please fork the project on Github and raise a pull request including passing specs.
251
+
252
+ ### Copyright & License
253
+
254
+ Copyright (c) 2011 Arkadiy Zabazhanov, Johnny Shields, and contributors.
255
+
256
+ MIT license, see [LICENSE](LICENSE.txt) for details.