mongoid_orderable 6.0.2 → 6.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/README.md +21 -2
- data/lib/mongoid/orderable/configs/field_config.rb +2 -0
- data/lib/mongoid/orderable/generators/helpers.rb +8 -0
- data/lib/mongoid/orderable/generators/lock_collection.rb +2 -0
- data/lib/mongoid/orderable/handlers/base.rb +24 -2
- data/lib/mongoid/orderable/installer.rb +1 -1
- data/lib/mongoid/orderable/version.rb +1 -1
- data/spec/integration/conditional_spec.rb +36 -0
- data/spec/support/models.rb +12 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8882038ec4e57486bd693bc1732f935f2d01f949aeedc7f71b3c54bca5ac0b44
|
4
|
+
data.tar.gz: c0c82c4802280dfe6005e89122e9f7905fabcdf261bc9b3864016d10a70c112c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64332b6ae9d7786864d238accdd3ec81c8defa059ff1d7e1763e487a271c2dffb2f25b3a1a2332947a3b262ecc6cb8da33aae0acdab0cd04bd3ac6e0a2a2ca44
|
7
|
+
data.tar.gz: 918ea29f2b71caf6cfba5cdc7e145bba69d0d90d2561e1983676fa13a3517f87eaabd7f66d628fbae1ec45df56fe82a11a723de632bbd1650697f39939d10534
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
-
### 6.0.
|
1
|
+
### 6.0.4 (Next)
|
2
2
|
|
3
3
|
* Your contribution here.
|
4
4
|
|
5
|
+
### 6.0.3 (2021/06/27)
|
6
|
+
|
7
|
+
* [#72](https://github.com/mongoid/mongoid_orderable/pull/72): Feature: Add :if and :unless conditions which disable callbacks.
|
8
|
+
* [#71](https://github.com/mongoid/mongoid_orderable/pull/71): Fix: Add TTL index to locks table.
|
9
|
+
|
5
10
|
### 6.0.2 (2021/01/26)
|
6
11
|
|
7
12
|
* [#70](https://github.com/mongoid/mongoid_orderable/pull/70): Fix: Transactions should not use around callbacks - [@johnnyshields](https://github.com/johnnyshields).
|
data/README.md
CHANGED
@@ -138,7 +138,8 @@ book.previous_#{field}_item
|
|
138
138
|
|
139
139
|
where `#{field}` is either `position` or `serial_no`.
|
140
140
|
|
141
|
-
When a model defines multiple orderable fields, the original helpers are also available and work
|
141
|
+
When a model defines multiple orderable fields, the original helpers are also available and work
|
142
|
+
on the first orderable field.
|
142
143
|
|
143
144
|
```ruby
|
144
145
|
@book1 = Book.create!
|
@@ -181,6 +182,24 @@ end
|
|
181
182
|
To ensure the position is written correctly, you will need to set
|
182
183
|
`cascade_callbacks: true` on the relation.
|
183
184
|
|
185
|
+
### Disable Ordering
|
186
|
+
|
187
|
+
You can disable position tracking for specific documents using the `:if` and `:unless` options.
|
188
|
+
This is in advanced scenarios where you want to control position manually for certain documents.
|
189
|
+
In general, the disable condition should match a specific scope.
|
190
|
+
**Warning:** If used improperly, this will cause your documents to become out-of-order.
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
class Book
|
194
|
+
include Mongoid::Document
|
195
|
+
include Mongoid::Orderable
|
196
|
+
|
197
|
+
field :track_position, type: Boolean
|
198
|
+
|
199
|
+
orderable if: :track_position, unless: -> { created_at < Date.parse('2020-01-01') }
|
200
|
+
end
|
201
|
+
```
|
202
|
+
|
184
203
|
## Transaction Support
|
185
204
|
|
186
205
|
By default, Mongoid Orderable does not guarantee ordering consistency
|
@@ -219,7 +238,7 @@ After `transaction_max_retries` has been exceeded, a
|
|
219
238
|
|
220
239
|
When using transactions, Mongoid Orderable creates a collection
|
221
240
|
`mongoid_orderable_locks` which is used to store temporary lock objects.
|
222
|
-
|
241
|
+
Lock collections use a TTL index which auto-deletes objects older than 1 day.
|
223
242
|
|
224
243
|
You can change the lock collection name globally or per model:
|
225
244
|
|
@@ -17,6 +17,14 @@ module Generators
|
|
17
17
|
field ||= default_orderable_field
|
18
18
|
#{self_class}.orderable_configs[field][:field]
|
19
19
|
end
|
20
|
+
|
21
|
+
def orderable_if(field)
|
22
|
+
#{self_class}.orderable_configs[field][:if]
|
23
|
+
end
|
24
|
+
|
25
|
+
def orderable_unless(field)
|
26
|
+
#{self_class}.orderable_configs[field][:unless]
|
27
|
+
end
|
20
28
|
KLASS
|
21
29
|
|
22
30
|
generate_method(:orderable_inherited_class) do
|
@@ -12,12 +12,14 @@ module Generators
|
|
12
12
|
module Models
|
13
13
|
class #{model_name}
|
14
14
|
include Mongoid::Document
|
15
|
+
include Mongoid::Timestamps::Updated::Short
|
15
16
|
|
16
17
|
store_in collection: :#{collection_name}
|
17
18
|
|
18
19
|
field :scope, type: String
|
19
20
|
|
20
21
|
index({ scope: 1 }, { unique: 1 })
|
22
|
+
index({ updated_at: 1 }, { expire_after_seconds: 86400 })
|
21
23
|
end
|
22
24
|
end
|
23
25
|
KLASS
|
@@ -15,6 +15,8 @@ module Handlers
|
|
15
15
|
delegate :orderable_keys,
|
16
16
|
:orderable_field,
|
17
17
|
:orderable_position,
|
18
|
+
:orderable_if,
|
19
|
+
:orderable_unless,
|
18
20
|
:orderable_scope,
|
19
21
|
:orderable_scope_changed?,
|
20
22
|
:orderable_top,
|
@@ -39,7 +41,7 @@ module Handlers
|
|
39
41
|
end
|
40
42
|
|
41
43
|
def apply_one_position(field, target_position)
|
42
|
-
return unless changed?(field)
|
44
|
+
return unless allowed?(field) && changed?(field)
|
43
45
|
|
44
46
|
set_lock(field) if use_transactions
|
45
47
|
|
@@ -94,6 +96,7 @@ module Handlers
|
|
94
96
|
end
|
95
97
|
|
96
98
|
def remove_one_position(field)
|
99
|
+
return unless allowed?(field)
|
97
100
|
f = orderable_field(field)
|
98
101
|
current = orderable_position(field)
|
99
102
|
set_lock(field) if use_transactions
|
@@ -127,6 +130,25 @@ module Handlers
|
|
127
130
|
target_position
|
128
131
|
end
|
129
132
|
|
133
|
+
def allowed?(field)
|
134
|
+
cond_if = orderable_if(field)
|
135
|
+
cond_unless = orderable_unless(field)
|
136
|
+
|
137
|
+
(cond_if.nil? || resolve_condition(cond_if)) &&
|
138
|
+
(cond_unless.nil? || !resolve_condition(cond_unless))
|
139
|
+
end
|
140
|
+
|
141
|
+
def resolve_condition(condition)
|
142
|
+
case condition
|
143
|
+
when Proc
|
144
|
+
condition.arity.zero? ? doc.instance_exec(&condition) : condition.call(doc)
|
145
|
+
when Symbol
|
146
|
+
doc.send(condition)
|
147
|
+
else
|
148
|
+
condition || false
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
130
152
|
def changed?(field)
|
131
153
|
return true if new_record? || !doc.send(orderable_field(field)) || move_all[field]
|
132
154
|
changeable_keys(field).any? {|f| doc.send("#{f}_changed?") }
|
@@ -153,7 +175,7 @@ module Handlers
|
|
153
175
|
model_name = doc.class.orderable_configs[field][:lock_collection].to_s.singularize.classify
|
154
176
|
model = Mongoid::Orderable::Models.const_get(model_name)
|
155
177
|
attrs = lock_scope(field, generic)
|
156
|
-
model.where(attrs).find_one_and_update(attrs, { upsert: true })
|
178
|
+
model.where(attrs).find_one_and_update(attrs.merge(updated_at: Time.now), { upsert: true })
|
157
179
|
end
|
158
180
|
|
159
181
|
def lock_scope(field, generic = false)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe ConditionalOrderable do
|
4
|
+
|
5
|
+
shared_examples_for 'conditional_orderable' do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
ConditionalOrderable.create!(cond_a: false, cond_b: nil)
|
9
|
+
ConditionalOrderable.create!(cond_a: false, cond_b: 1)
|
10
|
+
ConditionalOrderable.create!(cond_a: true, cond_b: 2)
|
11
|
+
ConditionalOrderable.create!(cond_a: false, cond_b: 3)
|
12
|
+
ConditionalOrderable.create!(cond_a: true, cond_b: 4)
|
13
|
+
ConditionalOrderable.create!(cond_a: true, cond_b: 5)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should have proper position field' do
|
17
|
+
orderables = ConditionalOrderable.all.sort_by {|x| x.cond_b || 0 }
|
18
|
+
|
19
|
+
expect(orderables.map(&:pos_a)).to eq [nil, nil, 1, nil, 2, 3]
|
20
|
+
expect(orderables.map(&:pos_b)).to eq [nil, 1, 2, 3, 4, nil]
|
21
|
+
expect(orderables.map(&:pos_c)).to eq [1, 2, 3, 4, 5, 6]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with transactions' do
|
26
|
+
enable_transactions!
|
27
|
+
|
28
|
+
it_behaves_like 'conditional_orderable'
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'without transactions' do
|
32
|
+
disable_transactions!
|
33
|
+
|
34
|
+
it_behaves_like 'conditional_orderable'
|
35
|
+
end
|
36
|
+
end
|
data/spec/support/models.rb
CHANGED
@@ -13,6 +13,18 @@ class SimpleOrderable
|
|
13
13
|
orderable
|
14
14
|
end
|
15
15
|
|
16
|
+
class ConditionalOrderable
|
17
|
+
include Mongoid::Document
|
18
|
+
include Mongoid::Orderable
|
19
|
+
|
20
|
+
field :cond_a, type: Boolean
|
21
|
+
field :cond_b, type: Integer
|
22
|
+
|
23
|
+
orderable field: :pos_a, if: :cond_a, unless: ->(obj) { obj.cond_b&.<(2) }
|
24
|
+
orderable field: :pos_b, if: -> { cond_b&.<=(4) }
|
25
|
+
orderable field: :pos_c, unless: false
|
26
|
+
end
|
27
|
+
|
16
28
|
class ScopedGroup
|
17
29
|
include Mongoid::Document
|
18
30
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid_orderable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.
|
4
|
+
version: 6.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pyromaniac
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -117,6 +117,7 @@ files:
|
|
117
117
|
- lib/mongoid/orderable/version.rb
|
118
118
|
- lib/mongoid_orderable.rb
|
119
119
|
- spec/integration/concurrency_spec.rb
|
120
|
+
- spec/integration/conditional_spec.rb
|
120
121
|
- spec/integration/customized_spec.rb
|
121
122
|
- spec/integration/embedded_spec.rb
|
122
123
|
- spec/integration/foreign_key_spec.rb
|
@@ -131,7 +132,8 @@ files:
|
|
131
132
|
- spec/spec_helper.rb
|
132
133
|
- spec/support/models.rb
|
133
134
|
homepage: https://github.com/mongoid/mongoid_orderable
|
134
|
-
licenses:
|
135
|
+
licenses:
|
136
|
+
- MIT
|
135
137
|
metadata: {}
|
136
138
|
post_install_message:
|
137
139
|
rdoc_options: []
|
@@ -148,12 +150,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
150
|
- !ruby/object:Gem::Version
|
149
151
|
version: '0'
|
150
152
|
requirements: []
|
151
|
-
rubygems_version: 3.
|
153
|
+
rubygems_version: 3.2.9
|
152
154
|
signing_key:
|
153
155
|
specification_version: 4
|
154
156
|
summary: Mongoid orderable list implementation
|
155
157
|
test_files:
|
156
158
|
- spec/integration/concurrency_spec.rb
|
159
|
+
- spec/integration/conditional_spec.rb
|
157
160
|
- spec/integration/customized_spec.rb
|
158
161
|
- spec/integration/embedded_spec.rb
|
159
162
|
- spec/integration/foreign_key_spec.rb
|