mongoid_listable 0.1.0 → 0.1.3

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.
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