mongoid_listable 0.1.0 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- M2JkMzNmNGMyODlkMTEwMzRkZjhkNjcwOGE2ZmEyZDU5YmI3NmE2Zg==
4
+ OGY4YzBjMjJiMzExZjI2M2M2YTFmNTBkMjM5MmY0ZTMyMjNjNzYwZQ==
5
5
  data.tar.gz: !binary |-
6
- MmJjNDY1OGIyOThmNmNkMTVhN2NiNGQ3YzVkYjkwNTdhMDU2YzkzZQ==
6
+ YmVlYmFjMDk1YmE2NjE4ZjkxZDgwZTYwMzhmOWU1ZTI2ZTcyMGZjMw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YzBhYmRkYzMwN2FkNDlhZjNkY2Q0MzI1MzAwNmE4ZjFkZTMxMzNjN2VkNmU3
10
- MzNkZmUxZTEzZmE3YjA2ZjVhNjgzMmIzMDIwODE2MWI2Yzk3OGMyYmJkYjkz
11
- NWFjN2RjYTIzN2I3MmZmYTZmNWI3ZDQyOWEyZDc0YzBhNDUzZmU=
9
+ OTliYmRiODE5MTlmYzA3OTM0MjE2MWMyYzg1OWZiMGIzYmY1ZTIyYzdlZmVh
10
+ MDBhMTcyMjdjMDIxZjdhOTc0OTU0YWNhMGM2YjAwNDlkNjdiOTNkM2M0OTIw
11
+ YTBmOTRmNzRiOWQwNTE4MDYwNTI4ZmUzNzlhOTQxMjVhOWU2N2Q=
12
12
  data.tar.gz: !binary |-
13
- YzI5MGM3MTZjYjg2MWY3ZjQzNTExNGYzMWJmNzA3ZjFkNWZlZTlmMzdlYjQ4
14
- MWVhZWVkMTQ3NGU3ZjFiODI0NTU0NDQ0MWZjNzhkNGM3MGIzMTFiYjliMTRi
15
- M2Q4NDk5MWRlODA5MWIyOTdmOWZhZjFiZjYyODg1NDhkNWFlMTg=
13
+ YWVhZGRiNGFhZGQ3ZjA4MmE0NWQ3ZDdiNjIxYmI5NDk5OTk3OWFiYzdhNTNl
14
+ MGY1NDg0ODhkYzNkNTU5MTg4ZTYxNjBjMDc2MWNkNGNlNTc2ZGJmMzdhYzAx
15
+ OWQzYTRlYWY1MDhiYWEwMmI2YTRiNTZhOGU2NmJhZWRiYWU5OGI=
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/README.md CHANGED
@@ -4,11 +4,28 @@
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 will eventually be a full replacement library for Mongoid List or Mongoid Orderable. Both
8
- libraries fail to accomplish the simple task this library handles: separate position scopes for each
9
- defined `has_many` / `belongs_to` relation.
7
+ Mongoid Listable manages lists for isolated collections or for more complex `has_many` / `belongs_to` relationships.
8
+ There are two main macros:
9
+
10
+ `listed` for isolated lists not belonging to any parent object.
11
+ `lists` for `has_many` / `belongs_to` relationships
12
+
13
+
14
+ ## Basic Usage - Isolated
15
+
16
+ class Photo
17
+ include Mongoid::Document
18
+ include Mongoid::Listable
19
+
20
+ listed
21
+ end
22
+
23
+ The `listed` macro will assign a `position` field and a `list` scope to the Photo class. All Photo instances
24
+ added or removed, (or whose position fields are updated) will trigger automatic reording of all sibling instances.
25
+
26
+
27
+ ## Basic Usage - Has Many
10
28
 
11
- ## Basic Usage
12
29
 
13
30
  class User
14
31
  include Mongoid::Document
@@ -26,16 +43,31 @@ defined `has_many` / `belongs_to` relation.
26
43
  ...
27
44
  end
28
45
 
29
- In this example photos that are assigned to a user will maintain position based on the index
30
- of the id in the array argument.
46
+ In this example photos that are added to or removed from a user, or have their position attribute updated
47
+ will maintain logical order based on the method used:
48
+
49
+ # setter
50
+ User.first.photos = [ photo_a, photo_c, photo_b ]
51
+ User.first.photos.last == photo_b #=> true
52
+
53
+ # ids setter
54
+ User.first.photo_ids = [ '527fe97c67df6f07e1000003', '527fe97c67df6f07e1000004', '527fe97c67df6f07e1000003' ]
55
+ User.first.photos[1].id == '527fe97c67df6f07e1000004' #=> true
56
+
57
+ # push
58
+ photo = Photo.create
59
+ User.first.photos << photo
60
+ User.first.photos.last == photo #=> true
61
+
62
+
31
63
 
32
- Each photo that belongs to the user will automatically obtain a field called `user_position`. The position field
33
- is derived from the foreign key of the relation, replacing "\_id" with "_position".
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".
34
66
 
35
- The 1-n relation of a user to their photos will automatically be ordered by `user_position` unless otherwise specified
67
+ The `has_many` relation of a user to their photos will automatically be ordered by `user_position` unless otherwise specified
36
68
  via the standard `order` option to the `has_many` macro.
37
69
 
38
- ## Complex Relations
70
+ ## Advanced Usage - Has Many
39
71
 
40
72
  # Handles multiple has_many relations on same model!
41
73
 
@@ -77,13 +109,10 @@ via the standard `order` option to the `has_many` macro.
77
109
  In this example, there are two `has_many` relations defined between a user and photos. Each photo belonging to a user will
78
110
  obtain two position fields: `featured_by_user_position` and `kodaked_by_user_position`.
79
111
 
80
- You can optionally override the name of the position column:
81
-
82
- lists :photos, column: :users_photos_order
83
112
 
84
113
  ## Todo
85
114
 
86
- There's a lot more to add to the library! At this point, it conveniently handles has many relationships.
115
+ Need to test embedded documents.
87
116
 
88
117
  ## Installation
89
118
 
@@ -49,24 +49,17 @@ module Mongoid
49
49
  send(name).uniq(&:id).count
50
50
  end
51
51
 
52
- private
53
-
54
- # Applies a position change on column. Which objects are repositioned
55
- # depends on the direction of the change.
52
+ # Retrieves an object's list siblings
56
53
  #
57
- # @param [ Symbol ] name The name of position column
54
+ # @return [ Array ]
58
55
  #
59
56
  # @since 0.1.0
60
- def apply_change_on column
61
- from, to = change_on column
62
- if to > from
63
- reposition siblings.between(column => from..to), column, from
64
- elsif to < from
65
- reposition siblings.between(column => to..from), column, to + 1
66
- end
67
- set column, to
57
+ def siblings field=:position
58
+ self.class.exists(field => true).ne id: id
68
59
  end
69
60
 
61
+ private
62
+
70
63
  # Resets column on objects starting at 'start'
71
64
  #
72
65
  # @param [ Array ] objects The objects to interate
@@ -80,42 +73,5 @@ module Mongoid
80
73
  end
81
74
  end
82
75
 
83
- # Returns the old and new values for column
84
- #
85
- # @param [ Symbol ] column The column to retrieve the change
86
- # @return [Array] [from, to]
87
- #
88
- # @since 0.1.0
89
- def change_on column
90
- from, to = send "#{column}_change"
91
- to = safe_to to
92
- [from, to]
93
- end
94
-
95
- # Ensures the 'to' value is within acceptable bounds
96
- #
97
- # @param [ Integer ] to The supplied position value
98
- # @return [ Integer ] The acceptable position value
99
- #
100
- # @since 0.1.0
101
- def safe_to to
102
- if to > self.class.count
103
- self.class.count
104
- elsif to < 1
105
- 1
106
- else
107
- to
108
- end
109
- end
110
-
111
- # Retrieves an object's list siblings
112
- #
113
- # @return [ Array ]
114
- #
115
- # @since 0.1.0
116
- def siblings
117
- self.class.list.ne id: id
118
- end
119
-
120
76
  end
121
77
  end
@@ -16,11 +16,12 @@ module Mongoid
16
16
  # @return [ Object ] self
17
17
  #
18
18
  # @since 0.0.6
19
- def _ids_setter name, meta
19
+ def ids_set name, meta
20
20
  ids_method = "#{name.to_s.singularize}_ids="
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
+
24
25
  self
25
26
  end
26
27
 
@@ -33,17 +34,16 @@ module Mongoid
33
34
  # @return [ Object ] self
34
35
  #
35
36
  # @since 0.0.6
36
- def _setter name, meta
37
+ def set name, meta
37
38
  before_method "#{name}=" do |objects|
38
39
  objects ||= []
39
- objects.each_with_index do |object, index|
40
- object.set field_name(meta), index + 1
41
- end
40
+ reposition objects, field_name(meta), 1
42
41
 
43
42
  (send(name).to_a - objects).each do |object|
44
43
  object.unset field_name(meta)
45
44
  end
46
45
  end
46
+
47
47
  self
48
48
  end
49
49
 
@@ -6,104 +6,160 @@ module Mongoid
6
6
 
7
7
  module ClassMethods
8
8
 
9
- # Defines a mongoid relation after_add callback.
10
- # Sets the position attribute to current relations length + 1
9
+ # Defines a mongoid before_create callback.
10
+ # Sets the position field to current object count + 1
11
11
  #
12
- # @param [ Symbol ] name The name of the has_many relation
13
- # @param [ MetaData ] meta The MetaData class
12
+ # @param [ Hash ] The configuration hash
14
13
  #
15
14
  # @return [ Object ] self
16
15
  #
17
- # @since 0.0.6
18
- def added name, meta
19
- callback = "#{name.to_s.singularize}_added"
20
- define_method callback do |object|
21
- if object[field_name(meta)].nil?
22
- object.set field_name(meta), has_many_count(name) + 1
16
+ # @since 0.1.0
17
+ def created name
18
+ callback = "#{name}_#{__method__}"
19
+ define_method callback do
20
+ position = send name
21
+ if position.present?
22
+ siblings = siblings(name).gte name => position
23
+ reposition siblings, name, position + 1
24
+ else
25
+ set name, siblings(name).count + 1
23
26
  end
24
27
  end
25
- meta[:before_add] = callback
28
+
29
+ before_create callback
26
30
  self
27
31
  end
28
32
 
29
- # Defines a mongoid relation before_remove callback.
30
- # Resets the position index on all objects that came after
33
+ # Defines a mongoid before_update callback.
34
+ # If the position column has changed, apply the change.
35
+ # Hoe the change is applied varies depending on the redrection
36
+ # of the update.
31
37
  #
32
- # @param [ Symbol ] name The name of the has_many relation
33
- # @param [ MetaData ] meta The MetaData class
38
+ # @param [ Hash ] The configuration hash
34
39
  #
35
40
  # @return [ Object ] self
36
41
  #
37
- # @since 0.0.6
38
- def removed name, meta
39
- field_name = field_name meta
40
- callback = "#{name.to_s.singularize}_removed"
41
-
42
- define_method callback do |object|
43
- position = object.send field_name
44
- send(name).where(field_name.gt => position)
45
- .each_with_index do |object, index|
46
- object.set field_name, position + index
47
- end
48
- object.unset field_name
42
+ # @since 0.1.0
43
+ def updated name
44
+ callback = "#{name}_#{__method__}"
45
+ define_method callback do
46
+ apply_change_on name if send("#{name}_changed?")
49
47
  end
50
48
 
51
- meta[:before_remove] = callback
49
+ before_update callback
52
50
  self
53
51
  end
54
52
 
55
- # Defines a mongoid before_create callback.
56
- # Sets the position field to current object count + 1
53
+ # Defines a mongoid before_destroy callback.
54
+ # Resets all sibling object's higher in the list
57
55
  #
58
56
  # @param [ Hash ] The configuration hash
59
57
  #
60
58
  # @return [ Object ] self
61
59
  #
62
60
  # @since 0.1.0
63
- def created configuration
64
- define_method __method__ do
65
- set configuration[:column], self.class.count + 1
61
+ def destroyed name
62
+ callback = "#{name}_#{__method__}"
63
+ define_method callback do
64
+ position = send name
65
+ siblings = siblings(name).gt(name => position)
66
+ reposition siblings, name, position
66
67
  end
67
- before_create __method__
68
+
69
+ before_destroy callback
68
70
  self
69
71
  end
70
72
 
71
- # Defines a mongoid before_update callback.
72
- # If the position column has changed, apply the change.
73
- # Hoe the change is applied varies depending on the redrection
74
- # of the update.
73
+ # Defines a mongoid has_many relation after_add callback.
74
+ # Sets the position attribute to current relations length + 1
75
75
  #
76
- # @param [ Hash ] The configuration hash
76
+ # @param [ Symbol ] name The name of the has_many relation
77
+ # @param [ MetaData ] meta The MetaData class
77
78
  #
78
79
  # @return [ Object ] self
79
80
  #
80
- # @since 0.1.0
81
- def updated configuration
82
- define_method __method__ do
83
- column = configuration[:column]
84
- apply_change_on column if send("#{column}_changed?")
81
+ # @since 0.0.6
82
+ def added name, meta
83
+ callback = "#{name.to_s.singularize}_added"
84
+ define_method callback do |object|
85
+ if object[field_name(meta)].nil?
86
+ object.set field_name(meta), has_many_count(name) + 1
87
+ end
85
88
  end
86
- before_update __method__
89
+ meta[:before_add] = callback
87
90
  self
88
91
  end
89
92
 
90
- # Defines a mongoid before_destroy callback.
91
- # Resets all sibling object's higher in the list
93
+ # Defines a mongoid has_many relation before_remove callback.
94
+ # Resets the position index on all objects that came after
92
95
  #
93
- # @param [ Hash ] The configuration hash
96
+ # @param [ Symbol ] name The name of the has_many relation
97
+ # @param [ MetaData ] meta The MetaData class
94
98
  #
95
99
  # @return [ Object ] self
96
100
  #
97
- # @since 0.1.0
98
- def destroyed configuration
99
- define_method __method__ do
100
- column = configuration[:column]
101
- reposition siblings.gt(column => position), column, position
101
+ # @since 0.0.6
102
+ def removed name, meta
103
+ field_name = field_name meta
104
+ callback = "#{name.to_s.singularize}_removed"
105
+ define_method callback do |object|
106
+ position = object.send field_name
107
+ reposition object.siblings(field_name).gt(field_name => position),
108
+ field_name, position
109
+ object.unset field_name
102
110
  end
103
- before_destroy __method__
111
+
112
+ meta[:before_remove] = callback
104
113
  self
105
114
  end
106
115
 
116
+ end # ClassMethods
117
+
118
+ private
119
+
120
+ # Applies a position change on column. Which objects are repositioned
121
+ # depends on the direction of the change.
122
+ #
123
+ # @param [ Symbol ] name The name of position column
124
+ #
125
+ # @since 0.1.0
126
+ def apply_change_on name
127
+ from, to = change_on name
128
+ siblings = siblings name
129
+ if to > from
130
+ reposition siblings.between(name => from..to), name, from
131
+ elsif to < from
132
+ reposition siblings.between(name => to..from), name, to + 1
133
+ end
134
+ set name, to
135
+ end
136
+
137
+ # Returns the old and new values for column
138
+ #
139
+ # @param [ Symbol ] column The column to retrieve the change
140
+ # @return [Array] [from, to]
141
+ #
142
+ # @since 0.1.0
143
+ def change_on column
144
+ from, to = send "#{column}_change"
145
+ to = safe_to to
146
+ [from, to]
147
+ end
148
+
149
+ # Ensures the 'to' value is within acceptable bounds
150
+ #
151
+ # @param [ Integer ] to The supplied position value
152
+ # @return [ Integer ] The acceptable position value
153
+ #
154
+ # @since 0.1.0
155
+ def safe_to to
156
+ if to > self.class.count
157
+ self.class.count
158
+ elsif to < 1
159
+ 1
160
+ else
161
+ to
162
+ end
107
163
  end
108
164
 
109
165
  end
@@ -16,16 +16,16 @@ module Mongoid
16
16
  #
17
17
  # @since 0.1.0
18
18
  def listed options={}
19
- configuration = { column: :position }
19
+ configuration = { field_name: :position }
20
20
  configuration.merge! options if options.is_a?(Hash)
21
21
 
22
- field configuration[:column], type: Integer
22
+ field_name = configuration[:field_name]
23
23
 
24
- created(configuration)
25
- .updated(configuration)
26
- .destroyed(configuration)
24
+ field field_name, type: Integer
27
25
 
28
- scope :list, order_by(configuration[:column] => :asc)
26
+ created(field_name).updated(field_name).destroyed(field_name)
27
+
28
+ scope :list, order_by(field_name => :asc)
29
29
  self
30
30
  end
31
31
 
@@ -39,11 +39,13 @@ module Mongoid
39
39
  # @since 0.0.1
40
40
  def lists name, options={}
41
41
  meta = reflect_on_association name
42
- meta.klass.send :field, field_name(meta), type: Integer
43
- _ids_setter(name, meta)
44
- ._setter(name, meta)
45
- .added(name, meta)
46
- .removed(name, meta)
42
+ field_name = field_name(meta)
43
+ meta.klass.send :field, field_name, type: Integer
44
+ ids_set(name, meta).set(name, meta)
45
+ .added(name, meta).removed(name, meta)
46
+
47
+ meta.klass.updated(field_name).destroyed(field_name)
48
+
47
49
  meta[:order] ||= "#{field_name(meta)} asc"
48
50
  end
49
51
 
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Listable
3
- VERSION = '0.1.0'
3
+ VERSION = '0.1.3'
4
4
  end
5
5
  end
@@ -1,126 +1,162 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Mongoid::Listable do
3
+ describe Mongoid::Listable do
4
4
 
5
- before :all do
6
- User.create!
7
- 10.times { Photo.create }
8
- end
9
-
10
- it 'created a user' do
11
- expect(User.first).to be_true
5
+ def ensure_order objects, field
6
+ objects.each_with_index do |object, index|
7
+ expect(object[field]).to eq(index + 1)
8
+ end
12
9
  end
13
10
 
14
- it 'created 10 photos' do
15
- expect(Photo.count).to eq(10)
16
- end
11
+ describe 'listed' do
17
12
 
18
- it 'added the position field for a photo' do
19
- expect(Photo.instance_methods.include?(:position)).to be_true
20
- end
13
+ before :all do
14
+ Photo.destroy_all
15
+ 10.times { Photo.create }
16
+ end
21
17
 
22
- it 'orders photos' do
23
- Photo.list.each_with_index do |photo, index|
24
- expect(photo.position).to eq(index + 1)
18
+ after :each do
19
+ ensure_order Photo.list, :position
25
20
  end
26
- end
27
21
 
28
- it 'updates photo order on position change higher' do
29
- photo_a_id = Photo.list[3].id
30
- photo_b_id = Photo.list[7].id
22
+ it 'adds an object to the beginning of a list on create' do
23
+ photo = Photo.create position: 1
24
+ expect(Photo.list.first.position).to eq(1)
25
+ expect(photo.id).to eq(Photo.list.first.id)
26
+ end
31
27
 
32
- expect(Photo.find(photo_a_id).position).to eq(4)
33
- expect(Photo.find(photo_b_id).position).to eq(8)
28
+ it 'adds an object to the middle of a list on create' do
29
+ photo = Photo.create position: 5
30
+ expect(Photo.list[4].position).to eq(5)
31
+ expect(photo.id).to eq(Photo.list[4].id)
32
+ end
34
33
 
35
- Photo.find(photo_a_id).update_attribute :position, 9
34
+ it 'adds an object to the end of a list on create' do
35
+ photo = Photo.create
36
+ expect(Photo.list.last.position).to eq(13)
37
+ expect(photo.id).to eq(Photo.list.last.id)
38
+ end
36
39
 
37
- expect(Photo.find(photo_a_id).position).to eq(9)
38
- expect(Photo.find(photo_b_id).position).to eq(7)
39
- end
40
+ it 'updates the position of an object higher' do
41
+ photo_id = Photo.list[1].id
42
+ Photo.list[1].update_attribute :position, 4
43
+ expect(photo_id).to eq(Photo.list[3].id)
44
+ expect(Photo.list[3].position).to eq(4)
45
+ end
40
46
 
41
- it 'updates photo order on position change lower' do
42
- photo_a_id = Photo.list[5].id
43
- photo_b_id = Photo.list[9].id
47
+ it 'updates the position of an object lower' do
48
+ photo_id = Photo.list[9].id
49
+ Photo.list[9].update_attribute :position, 2
50
+ expect(photo_id).to eq(Photo.list[1].id)
51
+ expect(Photo.list[1].position).to eq(2)
52
+ end
44
53
 
45
- expect(Photo.find(photo_a_id).position).to eq(6)
46
- expect(Photo.find(photo_b_id).position).to eq(10)
54
+ it 'updates the position of an object the same' do
55
+ photo_id = Photo.list[4].id
56
+ Photo.list[4].update_attribute :position, 5
57
+ expect(photo_id).to eq(Photo.list[4].id)
58
+ expect(Photo.list[4].position).to eq(5)
59
+ end
47
60
 
48
- Photo.find(photo_a_id).update_attribute :position, 2
61
+ it 'removes an object from the beginning of a list on destroy' do
62
+ Photo.list.first.destroy
63
+ expect(Photo.list.first.position).to eq(1)
64
+ end
49
65
 
50
- expect(Photo.find(photo_a_id).position).to eq(2)
51
- expect(Photo.find(photo_b_id).position).to eq(10)
52
- end
66
+ it 'removes an object from the middle of a list on destroy' do
67
+ Photo.list[6].destroy
68
+ expect(Photo.list.first.position).to eq(1)
69
+ expect(Photo.list[6].position).to eq(7)
70
+ expect(Photo.list.last.position).to eq(11)
71
+ end
53
72
 
54
- it 'updates photo order on photo destroy' do
55
- photo_a_id = Photo.list[5].id
56
- photo_b_id = Photo.list[9].id
73
+ it 'removes an object from the end of a list on destroy' do
74
+ Photo.list.last.destroy
75
+ expect(Photo.list.last.position).to eq(10)
76
+ end
77
+ end
57
78
 
58
- expect(Photo.find(photo_b_id).position).to eq(10)
79
+ describe 'lists' do
59
80
 
60
- Photo.find(photo_a_id).destroy
81
+ before :all do
82
+ User.destroy_all
83
+ Photo.destroy_all
61
84
 
62
- expect(Photo.find(photo_b_id).position).to eq(9)
63
- end
85
+ User.create
86
+ 10.times { Photo.create }
87
+ end
64
88
 
65
- it 'creates a new photo' do
66
- Photo.create
67
- expect(Photo.all.count).to eq(10)
68
- expect(Photo.last.position).to eq(10)
69
- end
89
+ after :each do
90
+ ensure_order User.first.photos, :user_position
91
+ end
70
92
 
71
- it 'adds photos to a user with the default setter' do
72
- User.first.photos = Photo.all
73
- expect(User.first.photos.count).to eq(10)
74
- end
93
+ it 'sets object list of an owner with the default setter' do
94
+ photos = Photo.all
95
+ User.first.photos = photos
96
+ photos.each_with_index do |photo, index|
97
+ expect(photo.id).to eq(User.first.photos[index].id)
98
+ end
99
+ expect(User.first.photos.count).to eq(Photo.count)
100
+ end
75
101
 
76
- it 'orders photos for a user' do
77
- User.first.photos.each_with_index do |photo, index|
78
- expect(photo.user_position).to eq(index + 1)
102
+ it 'sets object list of an owner with the default ids setter' do
103
+ ids = Photo.all[2..7].collect(&:id)
104
+ User.first.photo_ids = ids
105
+ ids.each_with_index do |id, index|
106
+ expect(id).to eq(User.first.photos[index].id)
107
+ end
108
+ expect(User.first.photos.count).to eq(6)
79
109
  end
80
- end
81
110
 
82
- it 'removes photos from a user' do
83
- User.first.photos = nil
84
- expect(User.first.photos.count).to eq(0)
85
- end
111
+ it 'pushes objects to the list of an owner' do
112
+ User.first.photos << Photo.all
113
+ expect(User.first.photos.count).to eq(10)
114
+ end
86
115
 
87
- it 'adds 5 photos to a user with the default ids setter' do
88
- User.first.photo_ids = Photo.all[0..4].map &:id
89
- expect(User.first.photos.count).to eq(5)
90
- end
116
+ it 'updates the position of an object higher' do
117
+ photo_id = User.first.photos[4].id
118
+ Photo.find(photo_id).update_attribute :user_position, 6
119
+ expect(photo_id).to eq(User.first.photos[5].id)
120
+ expect(User.first.photos[5].user_position).to eq(6)
121
+ end
91
122
 
92
- it 'adds all photos to a user with the default ids setter' do
93
- User.first.photo_ids = Photo.all.map &:id
94
- expect(User.first.photos.count).to eq(10)
95
- end
123
+ it 'updates the position of an object lower' do
124
+ photo_id = User.first.photos[4].id
125
+ Photo.find(photo_id).update_attribute :user_position, 1
126
+ expect(photo_id).to eq(User.first.photos[0].id)
127
+ expect(User.first.photos[0].user_position).to eq(1)
128
+ end
96
129
 
97
- it 'orders photos for a user' do
98
- User.first.photos.each_with_index do |photo, index|
99
- expect(photo.user_position).to eq(index + 1)
130
+ it 'updates the position of an object the same' do
131
+ photo_id = User.first.photos[4].id
132
+ Photo.find(photo_id).update_attribute :user_position, 5
133
+ expect(photo_id).to eq(User.first.photos[4].id)
134
+ expect(User.first.photos[4].user_position).to eq(5)
100
135
  end
101
- end
102
136
 
103
- it 'adds a new photo to a user' do
104
- User.first.photos << Photo.new
105
- expect(User.first.photos.count).to eq(11)
106
- expect(User.first.photos.last.user_position).to eq(11)
107
- end
137
+ it 'updates the position of an object out of bounds high' do
138
+ photo_id = User.first.photos[4].id
139
+ Photo.find(photo_id).update_attribute :user_position, 1000
140
+ expect(photo_id).to eq(User.first.photos.last.id)
141
+ expect(User.first.photos.last.user_position).to eq(User.first.photos.count)
142
+ end
108
143
 
109
- it 'adds a created photo to a user' do
110
- User.first.photos << Photo.create
111
- expect(User.first.photos.count).to eq(12)
112
- expect(User.first.photos.last.user_position).to eq(12)
113
- end
144
+ it 'updates the position of an object out of bounds low' do
145
+ photo_id = User.first.photos[4].id
146
+ Photo.find(photo_id).update_attribute :user_position, -2
147
+ expect(photo_id).to eq(User.first.photos.first.id)
148
+ expect(User.first.photos.first.user_position).to eq(1)
149
+ end
114
150
 
115
- it 'deletes a photo from a user' do
116
- User.first.photos.delete(Photo.all[5])
117
- expect(User.first.photos.count).to eq(11)
118
- expect(User.first.photos.last.user_position).to eq(11)
119
- end
151
+ it 'removes objects from the list of an owner with the default unsetter' do
152
+ User.first.photos.delete(Photo.first)
153
+ expect(User.first.photos.count).to eq(9)
154
+ end
120
155
 
121
- it 'orders photos for a user' do
122
- User.first.photos.each_with_index do |photo, index|
123
- expect(photo.user_position).to eq(index + 1)
156
+ it 'removes objects from the list of an owner by destroy' do
157
+ Photo.all[3].destroy
158
+ expect(User.first.photos.count).to eq(8)
159
+ Photo.first.destroy
124
160
  end
125
161
  end
126
162
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_listable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - richardcalahan
@@ -61,6 +61,7 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - .coveralls.yml
63
63
  - .gitignore
64
+ - .rspec
64
65
  - .travis.yml
65
66
  - Gemfile
66
67
  - LICENSE.txt