mongoid_orderable 5.2.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.