mongoid_listable 0.2.1 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +31 -18
- data/lib/mongoid/listable/accessors.rb +3 -5
- data/lib/mongoid/listable/callbacks.rb +37 -46
- data/lib/mongoid/listable/macros.rb +22 -12
- data/lib/mongoid/listable/version.rb +1 -1
- data/lib/mongoid/listable.rb +28 -27
- data/spec/models/item.rb +1 -1
- data/spec/mongoid_listable_spec.rb +46 -33
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YWE5MDIwMmJjOWRhNTM2NzU2Yzg2OWYzYTI4YmM4NGQ3ODczYjg0Mw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDJmNTM5NzAyYjM4MGU2ZjEyZWFiYjY0NmY2YWYzMzEyMDVlYmRlYQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
M2JhNWFhMjcwNjUxMTE5OGM1MzU1OTZlN2U3NDNiNzI2N2M5MjY5YmQxNWY1
|
10
|
+
MzBiMDkzZDliOTJjNTNkZmQyN2MwYjU3NDhiZGE3NmU3YTdhZmFiYWRmOGU2
|
11
|
+
YzBkNzM3Njg3MTA0ODg2ZTQ5MzY1YTc1YWM4Yzk1Y2NmNWQ5NjQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MGQwYTNkYzcyNjk2OGU3YWMzODliODEyMWY0MzQ4ZTE0MGIyOGRkOTc5MzUx
|
14
|
+
ZjU1OTA4ZGRkOWNiNTc0ZDNhNjYxMTBjNDUyZmRhMThkNzQ4NWY1NTc4Y2Ey
|
15
|
+
NTgwZTU4OTk2NDMwOGQyN2I4MTVmMGFkYzBjNmM5NTUxZjg2ZTg=
|
data/README.md
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# Mongoid Listable
|
2
|
-
[![Code Climate](https://codeclimate.com/
|
2
|
+
[![Code Climate](https://codeclimate.com/github/richardcalahan/mongoid_listable.png)](https://codeclimate.com/github/richardcalahan/mongoid_listable)
|
3
3
|
[![Build Status](https://travis-ci.org/richardcalahan/mongoid_listable.png?branch=master)](https://travis-ci.org/richardcalahan/mongoid_listable)
|
4
4
|
[![Coverage Status](https://coveralls.io/repos/richardcalahan/mongoid_listable/badge.png?branch=master)](https://coveralls.io/r/richardcalahan/mongoid_listable?branch=master)
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/mongoid_listable.png)](http://badge.fury.io/rb/mongoid_listable)
|
6
6
|
|
7
|
-
Mongoid Listable
|
7
|
+
Mongoid Listable is a library for managing listable relations. It works great for isolated collections or for more complex `has_many` / `embeds_many` relationships.
|
8
|
+
|
8
9
|
There are two main macros:
|
9
10
|
|
10
|
-
`listed` for
|
11
|
-
`lists` for `has_many` / `
|
11
|
+
* `listed` for non-relational lists that do not belong to any objects.
|
12
|
+
* `lists` for `has_many` / `embeds_many` relationships.
|
12
13
|
|
13
14
|
|
14
15
|
## Basic Usage - Isolated
|
@@ -20,11 +21,23 @@ There are two main macros:
|
|
20
21
|
listed
|
21
22
|
end
|
22
23
|
|
23
|
-
The `listed` macro will assign a `position` field and a `list` scope to the Photo class. All Photo instances
|
24
|
-
|
25
|
-
|
24
|
+
The `listed` macro will assign a `position` field and a `list` scope to the Photo class. All Photo instances that are
|
25
|
+
created, destroyed, or have their position field updated will trigger a reording of all sibling instances.
|
26
|
+
|
27
|
+
Non-relational lists can have as many listed contexts as needed. You'll need to specify both the `scope` and the
|
28
|
+
`field` options in these cases.
|
29
|
+
|
30
|
+
class Photo
|
31
|
+
|
32
|
+
include Mongoid::Document
|
33
|
+
include Mongoid::Listable
|
34
|
+
|
35
|
+
listed :scope :list, field: :position
|
36
|
+
listed :scope :slideshow, field: :slideshow_position
|
37
|
+
|
38
|
+
end
|
26
39
|
|
27
|
-
## Basic Usage - Has Many
|
40
|
+
## Basic Usage - Has Many / Embeds Many
|
28
41
|
|
29
42
|
|
30
43
|
class User
|
@@ -32,6 +45,8 @@ added or removed, (or whose position fields are updated) will trigger automatic
|
|
32
45
|
include Mongoid:Listable
|
33
46
|
|
34
47
|
has_many :photos
|
48
|
+
# or embeds_many :photos
|
49
|
+
|
35
50
|
lists :photos
|
36
51
|
...
|
37
52
|
end
|
@@ -40,11 +55,12 @@ added or removed, (or whose position fields are updated) will trigger automatic
|
|
40
55
|
include Mongoid::Document
|
41
56
|
|
42
57
|
belongs_to :user
|
58
|
+
# or embedded_in :user
|
43
59
|
...
|
44
60
|
end
|
45
61
|
|
46
|
-
In this example photos that are added to or removed from a user, or have their position attribute updated
|
47
|
-
will
|
62
|
+
In this example photos that are added to or removed from a user's collection, or have their position attribute updated
|
63
|
+
will trigger a reordering of all sibling instances. For example:
|
48
64
|
|
49
65
|
# setter
|
50
66
|
User.first.photos = [ photo_a, photo_c, photo_b ]
|
@@ -61,13 +77,14 @@ will maintain logical order based on the method used:
|
|
61
77
|
|
62
78
|
|
63
79
|
|
64
|
-
Each photo that belongs to the user will automatically obtain a field called `user_position`. The field
|
65
|
-
is derived from the foreign key of the relation, replacing "\_id" with "_position".
|
80
|
+
Each photo that belongs to the user will automatically obtain a field called `user_position`. The field name
|
81
|
+
is derived from the foreign key of the relation, replacing "\_id" with "_position". Having a unique position key
|
82
|
+
for each 1-n relationship allows for more complex lists.
|
66
83
|
|
67
|
-
The `has_many`
|
84
|
+
The `has_many` / `embeds_many` relationship of a user to their photos will automadtically be ordered by `user_position` unless otherwise specified
|
68
85
|
via the standard `order` option to the `has_many` macro.
|
69
86
|
|
70
|
-
## Advanced Usage - Has Many
|
87
|
+
## Advanced Usage - Has Many / Embeds Many
|
71
88
|
|
72
89
|
# Handles multiple has_many relations on same model!
|
73
90
|
|
@@ -110,10 +127,6 @@ In this example, there are two `has_many` relations defined between a user and p
|
|
110
127
|
obtain two position fields: `featured_by_user_position` and `kodaked_by_user_position`.
|
111
128
|
|
112
129
|
|
113
|
-
## Todo
|
114
|
-
|
115
|
-
Need to test embedded documents.
|
116
|
-
|
117
130
|
## Installation
|
118
131
|
|
119
132
|
Add this line to your application's Gemfile:
|
@@ -21,7 +21,6 @@ module Mongoid
|
|
21
21
|
redefine_method ids_method do |ids|
|
22
22
|
send meta.setter, meta.klass.find(ids).sort_by_attr(:id, ids)
|
23
23
|
end
|
24
|
-
|
25
24
|
self
|
26
25
|
end
|
27
26
|
|
@@ -37,14 +36,13 @@ module Mongoid
|
|
37
36
|
def set name, meta
|
38
37
|
before_method "#{name}=" do |objects|
|
39
38
|
objects ||= []
|
40
|
-
|
41
|
-
reposition objects,
|
39
|
+
|
40
|
+
reposition objects, position_field_name(meta), 1
|
42
41
|
|
43
42
|
(send(name).to_a - objects).each do |object|
|
44
|
-
object.unset
|
43
|
+
object.unset position_field_name(meta)
|
45
44
|
end
|
46
45
|
end
|
47
|
-
|
48
46
|
self
|
49
47
|
end
|
50
48
|
|
@@ -9,25 +9,20 @@ module Mongoid
|
|
9
9
|
# Defines a mongoid before_create callback.
|
10
10
|
# Sets the position field to current object count + 1
|
11
11
|
#
|
12
|
-
# @param [
|
12
|
+
# @param [ Symbol ] The name of the position field
|
13
13
|
#
|
14
14
|
# @return [ Object ] self
|
15
15
|
#
|
16
16
|
# @since 0.1.0
|
17
17
|
def created name
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
siblings = siblings name
|
23
|
-
reposition siblings.gte(name => position), name, position + 1
|
18
|
+
register_callback name, :before_create do
|
19
|
+
if position = send(name)
|
20
|
+
objects = siblings(name).gte(name => position)
|
21
|
+
reposition objects, name, position + 1
|
24
22
|
else
|
25
23
|
set name, siblings(name).count + 1
|
26
24
|
end
|
27
25
|
end
|
28
|
-
|
29
|
-
before_create callback
|
30
|
-
self
|
31
26
|
end
|
32
27
|
|
33
28
|
# Defines a mongoid before_update callback.
|
@@ -35,41 +30,33 @@ module Mongoid
|
|
35
30
|
# Hoe the change is applied varies depending on the redrection
|
36
31
|
# of the update.
|
37
32
|
#
|
38
|
-
# @param [
|
33
|
+
# @param [ Symbol ] The name of the position field
|
39
34
|
#
|
40
35
|
# @return [ Object ] self
|
41
36
|
#
|
42
37
|
# @since 0.1.0
|
43
38
|
def updated name
|
44
|
-
|
45
|
-
define_method callback do
|
39
|
+
register_callback name, :before_update do
|
46
40
|
apply_change_on name if send("#{name}_changed?")
|
47
41
|
end
|
48
|
-
before_update callback
|
49
|
-
self
|
50
42
|
end
|
51
43
|
|
52
44
|
# Defines a mongoid before_destroy callback.
|
53
45
|
# Resets all sibling object's higher in the list
|
54
46
|
#
|
55
|
-
# @param [
|
47
|
+
# @param [ Symbol ] The name of the position field
|
56
48
|
#
|
57
49
|
# @return [ Object ] self
|
58
50
|
#
|
59
51
|
# @since 0.1.0
|
60
52
|
def destroyed name
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
siblings = siblings(name).gt(name => position)
|
65
|
-
reposition siblings, name, position
|
53
|
+
register_callback name, :before_destroy do
|
54
|
+
siblings = siblings(name).gt(name => send(name))
|
55
|
+
reposition siblings, name, send(name)
|
66
56
|
end
|
67
|
-
|
68
|
-
before_destroy callback
|
69
|
-
self
|
70
57
|
end
|
71
58
|
|
72
|
-
# Defines a mongoid
|
59
|
+
# Defines a mongoid 1-n relation after_add callback.
|
73
60
|
# Sets the position attribute to current relations length + 1
|
74
61
|
#
|
75
62
|
# @param [ Symbol ] name The name of the has_many relation
|
@@ -79,22 +66,19 @@ module Mongoid
|
|
79
66
|
#
|
80
67
|
# @since 0.0.6
|
81
68
|
def added name, meta
|
82
|
-
|
83
|
-
define_method callback do |object|
|
69
|
+
register_callback name, :after_add do |object|
|
84
70
|
return unless object.new_record?
|
85
|
-
field_name =
|
71
|
+
field_name = position_field_name meta
|
86
72
|
if position = object.send(field_name)
|
87
73
|
objects = object.siblings(field_name).gte(field_name => position)
|
88
74
|
reposition objects, field_name, position + 1
|
89
75
|
else
|
90
|
-
object.set field_name,
|
76
|
+
object.set field_name, many(name).count
|
91
77
|
end
|
92
78
|
end
|
93
|
-
meta[:after_add] = callback
|
94
|
-
self
|
95
79
|
end
|
96
80
|
|
97
|
-
# Defines a mongoid
|
81
|
+
# Defines a mongoid 1-n relation before_remove callback.
|
98
82
|
# Resets the position index on all objects that came after
|
99
83
|
#
|
100
84
|
# @param [ Symbol ] name The name of the has_many relation
|
@@ -103,17 +87,25 @@ module Mongoid
|
|
103
87
|
# @return [ Object ] self
|
104
88
|
#
|
105
89
|
# @since 0.0.6
|
106
|
-
def removed name, meta
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
reposition object.
|
112
|
-
field_name
|
113
|
-
object.unset field_name
|
90
|
+
def removed name, meta
|
91
|
+
register_callback name, :before_remove do |object|
|
92
|
+
field_name = position_field_name meta
|
93
|
+
objects = object.siblings(field_name)
|
94
|
+
.gt(field_name => object.send(field_name))
|
95
|
+
reposition objects, field_name, object.send(field_name)
|
96
|
+
object.unset field_name
|
114
97
|
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def register_callback name, hook, &block
|
103
|
+
meta = reflect_on_association name
|
104
|
+
callback = "#{hook}_#{name}"
|
105
|
+
|
106
|
+
define_method callback, &block
|
115
107
|
|
116
|
-
meta[
|
108
|
+
meta ? meta[hook] = callback : send(hook, callback)
|
117
109
|
self
|
118
110
|
end
|
119
111
|
|
@@ -121,19 +113,18 @@ module Mongoid
|
|
121
113
|
|
122
114
|
private
|
123
115
|
|
124
|
-
# Applies a position change on
|
116
|
+
# Applies a position change on field. Which objects are repositioned
|
125
117
|
# depends on the direction of the change.
|
126
118
|
#
|
127
|
-
# @param [ Symbol ] name The name of position
|
119
|
+
# @param [ Symbol ] name The name of position field
|
128
120
|
#
|
129
121
|
# @since 0.1.0
|
130
122
|
def apply_change_on name
|
131
123
|
from, to = change_on name
|
132
|
-
siblings = siblings name
|
133
124
|
if to > from
|
134
|
-
reposition siblings.between(name => from..to), name, from
|
125
|
+
reposition siblings(name).between(name => from..to), name, from
|
135
126
|
elsif to < from
|
136
|
-
reposition siblings.between(name => to..from), name, to + 1
|
127
|
+
reposition siblings(name).between(name => to..from), name, to + 1
|
137
128
|
end
|
138
129
|
set name, to
|
139
130
|
end
|
@@ -15,14 +15,22 @@ module Mongoid
|
|
15
15
|
# @return self
|
16
16
|
#
|
17
17
|
# @since 0.1.0
|
18
|
-
def listed
|
19
|
-
|
18
|
+
def listed options={}
|
19
|
+
config = {
|
20
|
+
field: :position,
|
21
|
+
scope: :list
|
22
|
+
}
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
config.merge! options
|
25
|
+
|
26
|
+
field config[:field], type: Integer
|
27
|
+
|
28
|
+
created config[:field]
|
29
|
+
updated config[:field]
|
30
|
+
destroyed config[:field]
|
31
|
+
|
32
|
+
scope config[:scope], order_by(config[:field] => :asc)
|
24
33
|
|
25
|
-
scope :list, order_by(:position => :asc)
|
26
34
|
self
|
27
35
|
end
|
28
36
|
|
@@ -34,19 +42,21 @@ module Mongoid
|
|
34
42
|
# @return [ Mongoid:Relations:Metadata ] Instance of metadata
|
35
43
|
#
|
36
44
|
# @since 0.0.1
|
37
|
-
def lists
|
38
|
-
meta
|
45
|
+
def lists association, options={}
|
46
|
+
meta = reflect_on_association association
|
47
|
+
field_name = determine_position_field_name meta
|
39
48
|
|
40
|
-
field_name = field_name(meta)
|
41
49
|
meta.klass.send :field, field_name, type: Integer
|
42
50
|
|
43
|
-
ids_set
|
44
|
-
|
51
|
+
ids_set association, meta
|
52
|
+
set association, meta
|
53
|
+
added association, meta
|
54
|
+
removed association, meta
|
45
55
|
|
46
56
|
meta.klass.send :include, Mongoid::Listable
|
47
57
|
meta.klass.updated(field_name).destroyed(field_name)
|
48
58
|
|
49
|
-
meta[:order] ||= "#{field_name
|
59
|
+
meta[:order] ||= "#{field_name} asc"
|
50
60
|
end
|
51
61
|
|
52
62
|
end
|
data/lib/mongoid/listable.rb
CHANGED
@@ -13,43 +13,29 @@ module Mongoid
|
|
13
13
|
include Mongoid::Listable::Macros
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
# Generates the position field name using the MetaData class
|
19
|
-
#
|
20
|
-
# @param [ MetaData ] meta The MetaData class
|
21
|
-
#
|
22
|
-
# @return Symbol
|
23
|
-
#
|
24
|
-
# @since 0.0.6
|
25
|
-
def field_name meta
|
26
|
-
(meta.foreign_key.to_s.gsub(/_?id$/, '_position')).to_sym
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
# Proxies to the class level version
|
16
|
+
# Proxies to the class level determine_position_field_name
|
32
17
|
#
|
33
18
|
# @param [ MetaData ] meta The MetaData class
|
34
19
|
# @see Class.field_name
|
35
20
|
#
|
36
21
|
# @since 0.0.6
|
37
|
-
def
|
38
|
-
self.class.
|
22
|
+
def position_field_name meta
|
23
|
+
self.class.determine_position_field_name meta
|
39
24
|
end
|
40
25
|
|
41
|
-
#
|
26
|
+
# Finds unique instances of objects for a given relation
|
42
27
|
# Needed because the mongoid callbacks dont update
|
43
28
|
# has_many relations until after invoked.
|
44
29
|
#
|
45
30
|
# @param [ Symbol ] name The name of the has_many relation
|
46
31
|
#
|
47
|
-
# @since 0.
|
48
|
-
def
|
49
|
-
send(name).uniq(&:id)
|
32
|
+
# @since 0.2.1
|
33
|
+
def many name
|
34
|
+
send(name).uniq(&:id)
|
50
35
|
end
|
51
36
|
|
52
|
-
# Retrieves an object
|
37
|
+
# Retrieves siblings of an object in a list.
|
38
|
+
# Scoped by the position fiels name
|
53
39
|
#
|
54
40
|
# @return [ Array ]
|
55
41
|
#
|
@@ -61,18 +47,33 @@ module Mongoid
|
|
61
47
|
|
62
48
|
private
|
63
49
|
|
64
|
-
# Resets
|
50
|
+
# Resets position field on objects starting at 'start'
|
65
51
|
#
|
66
52
|
# @param [ Array ] objects The objects to interate
|
67
|
-
# @param [ Symbol ] column The
|
53
|
+
# @param [ Symbol ] column The field to update
|
68
54
|
# @param [ Integer ] start The starting position
|
69
55
|
#
|
70
56
|
# @since 0.1.0
|
71
|
-
def reposition objects,
|
57
|
+
def reposition objects, field, start
|
72
58
|
objects.each_with_index do |object, index|
|
73
|
-
object.set
|
59
|
+
object.set field, start + index
|
74
60
|
end
|
75
61
|
end
|
76
62
|
|
63
|
+
module ClassMethods
|
64
|
+
|
65
|
+
# Generates the position field name using the MetaData instance
|
66
|
+
#
|
67
|
+
# @param [ MetaData ] meta The MetaData instance
|
68
|
+
#
|
69
|
+
# @return Symbol
|
70
|
+
#
|
71
|
+
# @since 0.2.1
|
72
|
+
def determine_position_field_name meta
|
73
|
+
(meta.foreign_key.to_s.gsub(/_?id$/, '_position')).to_sym
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
77
78
|
end
|
78
79
|
end
|
data/spec/models/item.rb
CHANGED
@@ -10,90 +10,93 @@ describe Mongoid::Listable do
|
|
10
10
|
|
11
11
|
describe 'listed' do
|
12
12
|
|
13
|
+
FIELD = :custom_field
|
14
|
+
SCOPE = :custom_scope
|
15
|
+
|
13
16
|
before :each do
|
14
17
|
Item.destroy_all
|
15
18
|
10.times { Item.create! }
|
16
|
-
end
|
19
|
+
end
|
17
20
|
|
18
21
|
after :each do
|
19
|
-
ensure_order Item.
|
22
|
+
ensure_order Item.send(SCOPE), FIELD
|
20
23
|
end
|
21
24
|
|
22
25
|
it 'should have a position field' do
|
23
|
-
expect(Item.fields.key?(
|
26
|
+
expect(Item.fields.key?(FIELD.to_s)).to be_true
|
24
27
|
end
|
25
28
|
|
26
29
|
it 'should have a list scope' do
|
27
|
-
expect(Item.scopes.key?(
|
30
|
+
expect(Item.scopes.key?(SCOPE)).to be_true
|
28
31
|
end
|
29
32
|
|
30
33
|
it 'should append new object at position 1' do
|
31
|
-
item = Item.create
|
32
|
-
expect(item.
|
34
|
+
item = Item.create FIELD => 1
|
35
|
+
expect(item.send(FIELD)).to eq(1)
|
33
36
|
end
|
34
37
|
|
35
38
|
it 'should append new object at position 5' do
|
36
|
-
item = Item.create
|
37
|
-
expect(item.
|
39
|
+
item = Item.create FIELD => 5
|
40
|
+
expect(item.send(FIELD)).to eq(5)
|
38
41
|
end
|
39
42
|
|
40
43
|
it 'should append new object at end of list' do
|
41
44
|
item = Item.create
|
42
|
-
expect(item.
|
45
|
+
expect(item.send(FIELD)).to eq(11)
|
43
46
|
end
|
44
47
|
|
45
48
|
it 'should maintain order when removing object at position 1' do
|
46
|
-
Item.
|
49
|
+
Item.send(SCOPE).first.destroy
|
47
50
|
end
|
48
51
|
|
49
52
|
it 'should maintain order when removing object at position 5' do
|
50
|
-
Item.where(
|
53
|
+
Item.where(FIELD => 5).destroy
|
51
54
|
end
|
52
55
|
|
53
56
|
it 'should maintain order when removing object at position 10' do
|
54
|
-
Item.
|
57
|
+
Item.send(SCOPE).last.destroy
|
55
58
|
end
|
56
59
|
|
57
60
|
it 'should maintain order when moving object from position 1 to 5' do
|
58
|
-
item = Item.
|
59
|
-
item.update_attribute
|
60
|
-
expect(Item.
|
61
|
+
item = Item.send(SCOPE).first
|
62
|
+
item.update_attribute FIELD, 5
|
63
|
+
expect(Item.send(SCOPE).where(FIELD => 5).first).to eq(item)
|
61
64
|
end
|
62
65
|
|
63
66
|
it 'should maintain order when moving object from position 10 to 5' do
|
64
|
-
item = Item.
|
65
|
-
item.update_attribute
|
66
|
-
expect(Item.
|
67
|
+
item = Item.send(SCOPE).last
|
68
|
+
item.update_attribute FIELD, 5
|
69
|
+
expect(Item.send(SCOPE).where(FIELD => 5).first).to eq(item)
|
67
70
|
end
|
68
71
|
|
69
72
|
it 'should maintain order when moving object from position 2 to 6' do
|
70
|
-
item = Item.
|
71
|
-
item.update_attribute
|
72
|
-
expect(Item.
|
73
|
+
item = Item.send(SCOPE).where(FIELD => 2).first
|
74
|
+
item.update_attribute FIELD, 6
|
75
|
+
expect(Item.send(SCOPE).where(FIELD => 6).first).to eq(item)
|
73
76
|
end
|
74
77
|
|
75
78
|
it 'should maintain order when moving object from position 8 to 4' do
|
76
|
-
item = Item.
|
77
|
-
item.update_attribute
|
78
|
-
expect(Item.
|
79
|
+
item = Item.send(SCOPE).where(FIELD => 8).first
|
80
|
+
item.update_attribute FIELD, 4
|
81
|
+
expect(Item.send(SCOPE).where(FIELD => 4).first).to eq(item)
|
79
82
|
end
|
80
83
|
|
81
84
|
it 'should do nothing when assigning object to same position' do
|
82
|
-
item = Item.
|
83
|
-
item.update_attribute
|
84
|
-
expect(Item.
|
85
|
+
item = Item.send(SCOPE).where(FIELD => 5).first
|
86
|
+
item.update_attribute FIELD, 5
|
87
|
+
expect(Item.send(SCOPE).where(FIELD => 5).first).to eq(item)
|
85
88
|
end
|
86
89
|
|
87
90
|
it 'should compensate for updated positions that are higher than bounds' do
|
88
|
-
item = Item.
|
89
|
-
item.update_attribute
|
90
|
-
expect(Item.
|
91
|
+
item = Item.send(SCOPE).where(FIELD => 5).first
|
92
|
+
item.update_attribute FIELD, 100
|
93
|
+
expect(Item.send(SCOPE).last).to eq(item)
|
91
94
|
end
|
92
95
|
|
93
96
|
it 'should compensate for updated positions that are lower than bounds' do
|
94
|
-
item = Item.
|
95
|
-
item.update_attribute
|
96
|
-
expect(Item.
|
97
|
+
item = Item.send(SCOPE).where(FIELD => 5).first
|
98
|
+
item.update_attribute FIELD, -100
|
99
|
+
expect(Item.send(SCOPE).first).to eq(item)
|
97
100
|
end
|
98
101
|
|
99
102
|
end
|
@@ -145,6 +148,11 @@ describe Mongoid::Listable do
|
|
145
148
|
Article.first.sections.first.destroy
|
146
149
|
end
|
147
150
|
|
151
|
+
it 'should maintain order when removing object at position 2' do
|
152
|
+
section = Article.first.sections.where(article_position: 2).first
|
153
|
+
Article.first.sections.delete(section)
|
154
|
+
end
|
155
|
+
|
148
156
|
it 'should maintain order when removing object at position 5' do
|
149
157
|
Article.first.sections.where(article_position: 5).first.destroy
|
150
158
|
end
|
@@ -258,6 +266,11 @@ describe Mongoid::Listable do
|
|
258
266
|
User.first.photos.first.destroy
|
259
267
|
end
|
260
268
|
|
269
|
+
it 'should maintain order when removing object at position 2' do
|
270
|
+
photo = User.first.photos.where(user_position: 2).first
|
271
|
+
User.first.photos.delete(photo)
|
272
|
+
end
|
273
|
+
|
261
274
|
it 'should maintain order when removing object at position 5' do
|
262
275
|
User.first.photos.where(user_position: 5).first.destroy
|
263
276
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid_listable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- richardcalahan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mongoid
|