mongoid_orderable 5.2.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +73 -58
  3. data/LICENSE.txt +20 -20
  4. data/README.md +256 -150
  5. data/Rakefile +24 -21
  6. data/lib/config/locales/en.yml +12 -9
  7. data/lib/mongoid/orderable.rb +29 -20
  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/engine.rb +204 -0
  11. data/lib/mongoid/orderable/errors/invalid_target_position.rb +19 -15
  12. data/lib/mongoid/orderable/errors/transaction_failed.rb +20 -0
  13. data/lib/mongoid/orderable/generators/base.rb +21 -0
  14. data/lib/mongoid/orderable/generators/helpers.rb +29 -0
  15. data/lib/mongoid/orderable/generators/listable.rb +41 -0
  16. data/lib/mongoid/orderable/generators/lock_collection.rb +37 -0
  17. data/lib/mongoid/orderable/generators/movable.rb +62 -0
  18. data/lib/mongoid/orderable/generators/position.rb +26 -0
  19. data/lib/mongoid/orderable/generators/scope.rb +26 -0
  20. data/lib/mongoid/orderable/installer.rb +63 -0
  21. data/lib/mongoid/orderable/mixins/callbacks.rb +29 -0
  22. data/lib/mongoid/orderable/mixins/helpers.rb +39 -0
  23. data/lib/mongoid/orderable/mixins/listable.rb +49 -0
  24. data/lib/mongoid/orderable/mixins/movable.rb +60 -0
  25. data/lib/mongoid/orderable/version.rb +7 -0
  26. data/lib/mongoid_orderable.rb +29 -56
  27. data/spec/mongoid/orderable_spec.rb +1486 -1380
  28. data/spec/spec_helper.rb +21 -21
  29. metadata +44 -41
  30. data/.gitignore +0 -4
  31. data/.rspec +0 -2
  32. data/.rubocop.yml +0 -6
  33. data/.rubocop_todo.yml +0 -88
  34. data/.rvmrc +0 -1
  35. data/.travis.yml +0 -48
  36. data/CONTRIBUTING.md +0 -118
  37. data/Dangerfile +0 -1
  38. data/Gemfile +0 -26
  39. data/RELEASING.md +0 -68
  40. data/lib/mongoid/orderable/callbacks.rb +0 -79
  41. data/lib/mongoid/orderable/configuration.rb +0 -58
  42. data/lib/mongoid/orderable/errors.rb +0 -2
  43. data/lib/mongoid/orderable/errors/mongoid_orderable_error.rb +0 -6
  44. data/lib/mongoid/orderable/generator.rb +0 -33
  45. data/lib/mongoid/orderable/generator/helpers.rb +0 -27
  46. data/lib/mongoid/orderable/generator/listable.rb +0 -39
  47. data/lib/mongoid/orderable/generator/movable.rb +0 -60
  48. data/lib/mongoid/orderable/generator/position.rb +0 -24
  49. data/lib/mongoid/orderable/generator/scope.rb +0 -17
  50. data/lib/mongoid/orderable/helpers.rb +0 -49
  51. data/lib/mongoid/orderable/listable.rb +0 -47
  52. data/lib/mongoid/orderable/movable.rb +0 -56
  53. data/lib/mongoid/orderable/orderable_class.rb +0 -47
  54. data/lib/mongoid_orderable/mongoid/contextual/memory.rb +0 -15
  55. data/lib/mongoid_orderable/version.rb +0 -3
  56. data/mongoid_orderable.gemspec +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: eb9edcb0b7e48f8910b7a098a650b2908e1ba5cf
4
- data.tar.gz: c4ffa043177aa71c23f565d9e9d0765f94b4409c
2
+ SHA256:
3
+ metadata.gz: 278b3da8970c3b04304f169db82ca4999f31cf6b1b2212dd632864e805238162
4
+ data.tar.gz: b0c174f214b091e08e88660f622554f362dfa08722117f914d1358017d3b86e5
5
5
  SHA512:
6
- metadata.gz: 195681bcfce24cde2af7ebfb9b9ed74a36688ce24ec8acf59bc8f1b94c3ea81d3e252f1a20f67e4c554818c03739da3b84639026f5a80cb259575d7a2686f331
7
- data.tar.gz: 51d3bb674839997759c72ef9aa88335900ff6e6f5859fd8809c5e81a14f733c18df29191485ff81257fbe5b16c693985fd60b75f0c4a3166f4e48c219067f258
6
+ metadata.gz: 73f36dbb8f62f5f252deaaed6f488ea423d92d52be039aa6d95b7b2e0457cf41d50a63d934d26b1b2d92ad9d44530ec5053ca639c81b1ee523a244fe6dfbf9fd
7
+ data.tar.gz: b5ce0f3b0de0e6a0653784f1a507b5e32a92e9f59e277fa27e020010cf6f3cf0d5f49cc685c58e8ffe8a0ba0493d7d9cf41f0ddc3f13fc79a155b16e2f409f5b
@@ -1,58 +1,73 @@
1
- ### 5.2.0 (2018/05/01)
2
-
3
- * [#57](https://github.com/mongoid/mongoid_orderable/pull/57): Compatibility with Mongoid 7 - [@tomasc](https://github.com/tomasc).
4
- * [#52](https://github.com/mongoid/mongoid_orderable/pull/52): Test against Mongoid 6 - [@dblock](https://github.com/dblock).
5
-
6
- ### 5.1.0 (2017/06/04)
7
-
8
- * [#50](https://github.com/mongoid/mongoid_orderable/pull/50): Added Danger, PR linter - [@dblock](https://github.com/dblock).
9
- * [#51](https://github.com/mongoid/mongoid_orderable/pull/51): Added RuboCop - [@dblock](https://github.com/dblock).
10
- * [#49](https://github.com/mongoid/mongoid_orderable/pull/49): Fix orderable on embedded documents inside an inherited model - [@rafaelgaspar](https://github.com/rafaelgaspar).
11
-
12
- ### 5.0.0 (2015/10/21)
13
-
14
- * [#41](https://github.com/mongoid/mongoid_orderable/pull/41): Mongoid 5 support - [@dblock](https://github.com/dblock).
15
- * [#41](https://github.com/mongoid/mongoid_orderable/pull/41): Dropped support for ruby 1.8 - [@dblock](https://github.com/dblock).
16
-
17
- ### 4.1.1 (2014/12/19)
18
-
19
- * [#34](https://github.com/mongoid/mongoid_orderable/pull/34): Fix: index should respect scope - [@joeyAghion](https://github.com/joeyAghion).
20
-
21
- ### 4.1.0 (2014/3/19)
22
-
23
- * [#30](https://github.com/mongoid/mongoid_orderable/pull/30): Fix: reset a single column when `orderable_scope` changed instead of removing it from list - [@Bharat311](https://github.com/Bharat311).
24
- * [#29](https://github.com/mongoid/mongoid_orderable/pull/29): Fix: incorrect position when orderable base is set - [@Bharat311](https://github.com/Bharat311).
25
- * [#28](https://github.com/mongoid/mongoid_orderable/pull/28): Inherited `orderable_configurations` - [@johnny-miyake](https://github.com/johnny-miyake).
26
- * [#27](https://github.com/mongoid/mongoid_orderable/pull/27): Allowed numeric string to specify a target position - [@johnny-miyake](https://github.com/johnny-miyake).
27
- * [#26](https://github.com/mongoid/mongoid_orderable/pull/26): Added support for multiple orderable columns - [@Bharat311](https://github.com/Bharat311).
28
- * [#22](https://github.com/mongoid/mongoid_orderable/pull/22): Added lazy support for scopes with different foreign key names - [@dsci](https://github.com/dsci).
29
- * [#21](https://github.com/mongoid/mongoid_orderable/pull/21): Accounting for change in Mongoid's metadata API - [@pjkelly](https://github.com/pjkelly).
30
- * [#20](https://github.com/mongoid/mongoid_orderable/pull/20): Added next and previous item methods - [@mrjlynch](https://github.com/mrjlynch).
31
- * [#19](https://github.com/mongoid/mongoid_orderable/pull/19): Added lower and higher item methods - [@mrjlynch](https://github.com/mrjlynch).
32
-
33
- ### 4.0.0 (2013/10/22)
34
-
35
- * [#18](https://github.com/mongoid/mongoid_orderable/pull/18): Added Mongoid 4 support - [@dblock](https://github.com/dblock).
36
- * [#16](https://github.com/mongoid/mongoid_orderable/pull/16): Fix for Mongoid identity map combined with scoped orderable - [@johnnyshields](https://github.com/johnnyshields).
37
- * [#15](https://github.com/mongoid/mongoid_orderable/pull/15): Support pass-thru of Mongoid field alias (`:as` parameter) - [@johnnyshields](https://github.com/johnnyshields).
38
- * [#13](https://github.com/mongoid/mongoid_orderable/pull/13): Support inheritance - [@zhengjia](https://github.com/zhengjia).
39
-
40
- ### 1.2.0 (2013/1/10)
41
-
42
- * [#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).
43
-
44
- ### 1.1.0 (2012/5/23)
45
-
46
- * Added Mongoid 3 support - [@pyromaniac](https://github.com/pyromaniac).
47
-
48
- ### 1.0.0 (2012/2/14)
49
-
50
- * [#5](https://github.com/mongoid/mongoid_orderable/pull/5): Allow for use with default scopes - [@mattiassvedhem](https://github.com/mattiassvedhem).
51
-
52
- ### 0.9.1 (2012/2/3)
53
-
54
- ### 0.9.0 (2011/11/23)
55
-
56
- ### 0.0.1 (2011/11/1)
57
-
58
- * Initial public release - [@pyromaniac](https://github.com/pyromaniac).
1
+ ### 6.0.1 (Next)
2
+
3
+ * Your contribution here.
4
+
5
+ ### 6.0.0 (2021/01/23)
6
+
7
+ * [#65](https://github.com/mongoid/mongoid_orderable/pull/65): Feature: Add transaction support with lock table - [@johnnyshields](https://github.com/johnnyshields).
8
+ * [#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).
9
+ * [#62](https://github.com/mongoid/mongoid_orderable/pull/62): Feature: Allow scope parameter to be an Array - [@johnnyshields](https://github.com/johnnyshields).
10
+ * [#62](https://github.com/mongoid/mongoid_orderable/pull/62): Feature: Add global configurability - [@johnnyshields](https://github.com/johnnyshields).
11
+ * [#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).
12
+ * [#62](https://github.com/mongoid/mongoid_orderable/pull/62): Refactor: rename "column" to "field" - [@johnnyshields](https://github.com/johnnyshields).
13
+ * [#60](https://github.com/mongoid/mongoid_orderable/pull/60): Refactor: Drop support for Mongoid 6.x and lower - [@johnnyshields](https://github.com/johnnyshields).
14
+ * [#60](https://github.com/mongoid/mongoid_orderable/pull/60): Refactor: Remove Mongoid Compatibility (no longer needed) - [@johnnyshields](https://github.com/johnnyshields).
15
+
16
+ ### 5.2.0 (2018/05/01)
17
+
18
+ * [#57](https://github.com/mongoid/mongoid_orderable/pull/57): Compatibility with Mongoid 7 - [@tomasc](https://github.com/tomasc).
19
+ * [#52](https://github.com/mongoid/mongoid_orderable/pull/52): Test against Mongoid 6 - [@dblock](https://github.com/dblock).
20
+
21
+ ### 5.1.0 (2017/06/04)
22
+
23
+ * [#50](https://github.com/mongoid/mongoid_orderable/pull/50): Added Danger, PR linter - [@dblock](https://github.com/dblock).
24
+ * [#51](https://github.com/mongoid/mongoid_orderable/pull/51): Added RuboCop - [@dblock](https://github.com/dblock).
25
+ * [#49](https://github.com/mongoid/mongoid_orderable/pull/49): Fix orderable on embedded documents inside an inherited model - [@rafaelgaspar](https://github.com/rafaelgaspar).
26
+
27
+ ### 5.0.0 (2015/10/21)
28
+
29
+ * [#41](https://github.com/mongoid/mongoid_orderable/pull/41): Mongoid 5 support - [@dblock](https://github.com/dblock).
30
+ * [#41](https://github.com/mongoid/mongoid_orderable/pull/41): Dropped support for ruby 1.8 - [@dblock](https://github.com/dblock).
31
+
32
+ ### 4.1.1 (2014/12/19)
33
+
34
+ * [#34](https://github.com/mongoid/mongoid_orderable/pull/34): Fix: index should respect scope - [@joeyAghion](https://github.com/joeyAghion).
35
+
36
+ ### 4.1.0 (2014/3/19)
37
+
38
+ * [#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).
39
+ * [#29](https://github.com/mongoid/mongoid_orderable/pull/29): Fix: incorrect position when orderable base is set - [@Bharat311](https://github.com/Bharat311).
40
+ * [#28](https://github.com/mongoid/mongoid_orderable/pull/28): Inherited `orderable_configurations` - [@johnny-miyake](https://github.com/johnny-miyake).
41
+ * [#27](https://github.com/mongoid/mongoid_orderable/pull/27): Allowed numeric string to specify a target position - [@johnny-miyake](https://github.com/johnny-miyake).
42
+ * [#26](https://github.com/mongoid/mongoid_orderable/pull/26): Added support for multiple orderable fields - [@Bharat311](https://github.com/Bharat311).
43
+ * [#22](https://github.com/mongoid/mongoid_orderable/pull/22): Added lazy support for scopes with different foreign key names - [@dsci](https://github.com/dsci).
44
+ * [#21](https://github.com/mongoid/mongoid_orderable/pull/21): Accounting for change in Mongoid's metadata API - [@pjkelly](https://github.com/pjkelly).
45
+ * [#20](https://github.com/mongoid/mongoid_orderable/pull/20): Added next and previous item methods - [@mrjlynch](https://github.com/mrjlynch).
46
+ * [#19](https://github.com/mongoid/mongoid_orderable/pull/19): Added lower and higher item methods - [@mrjlynch](https://github.com/mrjlynch).
47
+
48
+ ### 4.0.0 (2013/10/22)
49
+
50
+ * [#18](https://github.com/mongoid/mongoid_orderable/pull/18): Added Mongoid 4 support - [@dblock](https://github.com/dblock).
51
+ * [#16](https://github.com/mongoid/mongoid_orderable/pull/16): Fix for Mongoid identity map combined with scoped orderable - [@johnnyshields](https://github.com/johnnyshields).
52
+ * [#15](https://github.com/mongoid/mongoid_orderable/pull/15): Support pass-thru of Mongoid field alias (`:as` parameter) - [@johnnyshields](https://github.com/johnnyshields).
53
+ * [#13](https://github.com/mongoid/mongoid_orderable/pull/13): Support inheritance - [@zhengjia](https://github.com/zhengjia).
54
+
55
+ ### 1.2.0 (2013/1/10)
56
+
57
+ * [#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).
58
+
59
+ ### 1.1.0 (2012/5/23)
60
+
61
+ * Added Mongoid 3 support - [@pyromaniac](https://github.com/pyromaniac).
62
+
63
+ ### 1.0.0 (2012/2/14)
64
+
65
+ * [#5](https://github.com/mongoid/mongoid_orderable/pull/5): Allow for use with default scopes - [@mattiassvedhem](https://github.com/mattiassvedhem).
66
+
67
+ ### 0.9.1 (2012/2/3)
68
+
69
+ ### 0.9.0 (2011/11/23)
70
+
71
+ ### 0.0.1 (2011/11/1)
72
+
73
+ * Initial public release - [@pyromaniac](https://github.com/pyromaniac).
@@ -1,20 +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.
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,150 +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/mongoid/mongoid_orderable.svg?branch=master)](https://travis-ci.org/mongoid/mongoid_orderable)
3
-
4
- # What?
5
-
6
- Mongoid::Orderable is a ordered list implementation for your Mongoid 3, 4, 5, 6 and 7 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 specifying multiple orderable columns
14
-
15
- # How?
16
-
17
- ```ruby
18
- gem 'mongoid_orderable'
19
- ```
20
-
21
- Gem has the same api as others. Just include Mongoid::Orderable into your model and call `orderable` method.
22
- Embedded objects are automatically scoped by their parent.
23
-
24
- ```ruby
25
- class Item
26
- include Mongoid::Document
27
- include Mongoid::Orderable
28
-
29
- # belongs_to :group
30
- # belongs_to :drawer, class_name: "Office::Drawer",
31
- # foreign_key: "legacy_drawer_key_id"
32
-
33
- # orderable
34
- # orderable scope: :group, column: :pos
35
- # orderable scope: :drawer, column: :pos # resolves scope foreign key from relation
36
- # orderable scope: 'drawer', column: :pos # but if you pass a string - it will use it as is, as the column name for scope
37
- # orderable scope: lambda { |document| where(group_id: document.group_id) }
38
- # orderable index: false # this one if you want specify indexes manually
39
- # orderable base: 0 # count position from zero as the top-most value (1 is the default value)
40
- end
41
- ```
42
-
43
- # Usage
44
-
45
- ```ruby
46
- item.move_to 2 # just change position
47
- item.move_to! 2 # and save
48
- item.move_to = 2 # assignable method
49
-
50
- # symbol position
51
- item.move_to :top
52
- item.move_to :bottom
53
- item.move_to :higher
54
- item.move_to :lower
55
-
56
- # generated methods
57
- item.move_to_top
58
- item.move_to_bottom
59
- item.move_higher
60
- item.move_lower
61
-
62
- item.next_items # return a collection of items higher on the list
63
- item.previous_items # return a collection of items lower on the list
64
-
65
- item.next_item # returns the next item in the list
66
- item.previous_item # returns the previous item in the list
67
- ```
68
-
69
- # Multiple Columns
70
-
71
- You can also define multiple orderable columns for any class including the Mongoid::Orderable module.
72
-
73
- ```ruby
74
- class Book
75
- include Mongoid::Document
76
- include Mongoid::Orderable
77
-
78
- orderable base: 0
79
- orderable column: sno, as: :serial_no
80
- end
81
- ```
82
-
83
- The above defines two different orderable_columns on Book - *position* and *serial_no*.
84
- The following helpers are generated in this case:
85
-
86
- ```ruby
87
- item.move_#{column_name}_to
88
- item.move_#{column_name}_to=
89
- item.move_#{column_name}_to!
90
-
91
- item.move_#{column_name}_to_top
92
- item.move_#{column_name}_to_bottom
93
- item.move_#{column_name}_higher
94
- item.move_#{column_name}_lower
95
-
96
- item.next_#{column_name}_items
97
- item.previous_#{column_name}_items
98
-
99
- item.next_#{column_name}_item
100
- item.previous_#{column_name}_item
101
- ```
102
-
103
- *where column_name is either **position** or **serial_no**.*
104
-
105
- When a model defines multiple orderable columns, the original helpers are also available and work on the first orderable column.
106
-
107
- ```ruby
108
- @book1 = Book.create!
109
- @book2 = Book.create!
110
- @book2 => #<Book _id: 53a16a2ba1bde4f746000001, serial_no: 1, position: 1>
111
- @book2.move_to! :top # this will change the :position of the book to 0 (not serial_no)
112
- @book2 => #<Book _id: 53a16a2ba1bde4f746000001, serial_no: 1, position: 0>
113
- ```
114
-
115
- To specify any other orderable column as default pass the **default: true** option with orderable.
116
-
117
- ```ruby
118
- orderable column: sno, as: :serial_no, default: true
119
- ```
120
-
121
- # Embedded documents
122
- ```ruby
123
- class Question
124
- include Mongoid::Document
125
- include Mongoid::Orderable
126
-
127
- embedded_in :survey
128
-
129
- orderable
130
- end
131
- ```
132
- If you bulk import embedded documents without specifying their position, no field `position` will be written.
133
- ```ruby
134
- class Survey
135
- include Mongoid::Document
136
-
137
- embeds_many :questions, cascade_callbacks: true
138
- end
139
- ```
140
- To ensure the position is written correctly, you will need to provide the cascade callbacks option to the relation.
141
-
142
- # Contributing
143
-
144
- See [CONTRIBUTING](CONTRIBUTING.md).
145
-
146
- # Copyright & License
147
-
148
- Copyright (c) 2011-2016 Arkadiy Zabazhanov & Contributors.
149
-
150
- MIT license, see [LICENSE](LICENSE.txt) for details.
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.