mongoid_listable 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/mongoid/listable/accessors.rb +2 -1
- data/lib/mongoid/listable/callbacks.rb +58 -5
- data/lib/mongoid/listable/macros.rb +21 -0
- data/lib/mongoid/listable/version.rb +1 -1
- data/lib/mongoid/listable.rb +71 -0
- data/lib/mongoid_listable.rb +3 -0
- data/spec/models/photo.rb +2 -0
- data/spec/mongoid_listable_spec.rb +100 -19
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
M2JkMzNmNGMyODlkMTEwMzRkZjhkNjcwOGE2ZmEyZDU5YmI3NmE2Zg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MmJjNDY1OGIyOThmNmNkMTVhN2NiNGQ3YzVkYjkwNTdhMDU2YzkzZQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YzBhYmRkYzMwN2FkNDlhZjNkY2Q0MzI1MzAwNmE4ZjFkZTMxMzNjN2VkNmU3
|
10
|
+
MzNkZmUxZTEzZmE3YjA2ZjVhNjgzMmIzMDIwODE2MWI2Yzk3OGMyYmJkYjkz
|
11
|
+
NWFjN2RjYTIzN2I3MmZmYTZmNWI3ZDQyOWEyZDc0YzBhNDUzZmU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YzI5MGM3MTZjYjg2MWY3ZjQzNTExNGYzMWJmNzA3ZjFkNWZlZTlmMzdlYjQ4
|
14
|
+
MWVhZWVkMTQ3NGU3ZjFiODI0NTU0NDQ0MWZjNzhkNGM3MGIzMTFiYjliMTRi
|
15
|
+
M2Q4NDk5MWRlODA5MWIyOTdmOWZhZjFiZjYyODg1NDhkNWFlMTg=
|
@@ -35,8 +35,9 @@ module Mongoid
|
|
35
35
|
# @since 0.0.6
|
36
36
|
def _setter name, meta
|
37
37
|
before_method "#{name}=" do |objects|
|
38
|
+
objects ||= []
|
38
39
|
objects.each_with_index do |object, index|
|
39
|
-
object.
|
40
|
+
object.set field_name(meta), index + 1
|
40
41
|
end
|
41
42
|
|
42
43
|
(send(name).to_a - objects).each do |object|
|
@@ -18,9 +18,11 @@ module Mongoid
|
|
18
18
|
def added name, meta
|
19
19
|
callback = "#{name.to_s.singularize}_added"
|
20
20
|
define_method callback do |object|
|
21
|
-
object
|
21
|
+
if object[field_name(meta)].nil?
|
22
|
+
object.set field_name(meta), has_many_count(name) + 1
|
23
|
+
end
|
22
24
|
end
|
23
|
-
meta[:
|
25
|
+
meta[:before_add] = callback
|
24
26
|
self
|
25
27
|
end
|
26
28
|
|
@@ -41,7 +43,7 @@ module Mongoid
|
|
41
43
|
position = object.send field_name
|
42
44
|
send(name).where(field_name.gt => position)
|
43
45
|
.each_with_index do |object, index|
|
44
|
-
object.
|
46
|
+
object.set field_name, position + index
|
45
47
|
end
|
46
48
|
object.unset field_name
|
47
49
|
end
|
@@ -50,9 +52,60 @@ module Mongoid
|
|
50
52
|
self
|
51
53
|
end
|
52
54
|
|
55
|
+
# Defines a mongoid before_create callback.
|
56
|
+
# Sets the position field to current object count + 1
|
57
|
+
#
|
58
|
+
# @param [ Hash ] The configuration hash
|
59
|
+
#
|
60
|
+
# @return [ Object ] self
|
61
|
+
#
|
62
|
+
# @since 0.1.0
|
63
|
+
def created configuration
|
64
|
+
define_method __method__ do
|
65
|
+
set configuration[:column], self.class.count + 1
|
66
|
+
end
|
67
|
+
before_create __method__
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
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.
|
75
|
+
#
|
76
|
+
# @param [ Hash ] The configuration hash
|
77
|
+
#
|
78
|
+
# @return [ Object ] self
|
79
|
+
#
|
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?")
|
85
|
+
end
|
86
|
+
before_update __method__
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
# Defines a mongoid before_destroy callback.
|
91
|
+
# Resets all sibling object's higher in the list
|
92
|
+
#
|
93
|
+
# @param [ Hash ] The configuration hash
|
94
|
+
#
|
95
|
+
# @return [ Object ] self
|
96
|
+
#
|
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
|
102
|
+
end
|
103
|
+
before_destroy __method__
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
53
107
|
end
|
54
108
|
|
55
|
-
end
|
56
|
-
|
109
|
+
end
|
57
110
|
end
|
58
111
|
end
|
@@ -8,6 +8,27 @@ module Mongoid
|
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
|
11
|
+
# Macro to set basic position field on an object
|
12
|
+
#
|
13
|
+
# @param [ Hash ] options The options hash
|
14
|
+
#
|
15
|
+
# @return self
|
16
|
+
#
|
17
|
+
# @since 0.1.0
|
18
|
+
def listed options={}
|
19
|
+
configuration = { column: :position }
|
20
|
+
configuration.merge! options if options.is_a?(Hash)
|
21
|
+
|
22
|
+
field configuration[:column], type: Integer
|
23
|
+
|
24
|
+
created(configuration)
|
25
|
+
.updated(configuration)
|
26
|
+
.destroyed(configuration)
|
27
|
+
|
28
|
+
scope :list, order_by(configuration[:column] => :asc)
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
11
32
|
# Macro to set relation on which to make a list
|
12
33
|
#
|
13
34
|
# @param [ Symbol ] name The name of the has_many relation
|
data/lib/mongoid/listable.rb
CHANGED
@@ -30,6 +30,7 @@ module Mongoid
|
|
30
30
|
|
31
31
|
# Proxies to the class level version
|
32
32
|
#
|
33
|
+
# @param [ MetaData ] meta The MetaData class
|
33
34
|
# @see Class.field_name
|
34
35
|
#
|
35
36
|
# @since 0.0.6
|
@@ -41,10 +42,80 @@ module Mongoid
|
|
41
42
|
# Needed because the mongoid callbacks dont update
|
42
43
|
# has_many relations until after invoked.
|
43
44
|
#
|
45
|
+
# @param [ Symbol ] name The name of the has_many relation
|
46
|
+
#
|
44
47
|
# @since 0.0.7
|
45
48
|
def has_many_count name
|
46
49
|
send(name).uniq(&:id).count
|
47
50
|
end
|
48
51
|
|
52
|
+
private
|
53
|
+
|
54
|
+
# Applies a position change on column. Which objects are repositioned
|
55
|
+
# depends on the direction of the change.
|
56
|
+
#
|
57
|
+
# @param [ Symbol ] name The name of position column
|
58
|
+
#
|
59
|
+
# @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
|
68
|
+
end
|
69
|
+
|
70
|
+
# Resets column on objects starting at 'start'
|
71
|
+
#
|
72
|
+
# @param [ Array ] objects The objects to interate
|
73
|
+
# @param [ Symbol ] column The column to update
|
74
|
+
# @param [ Integer ] start The starting position
|
75
|
+
#
|
76
|
+
# @since 0.1.0
|
77
|
+
def reposition objects, column, start
|
78
|
+
objects.each_with_index do |object, index|
|
79
|
+
object.set column, start + index
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
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
|
+
|
49
120
|
end
|
50
121
|
end
|
data/lib/mongoid_listable.rb
CHANGED
data/spec/models/photo.rb
CHANGED
@@ -3,41 +3,122 @@ require 'spec_helper'
|
|
3
3
|
describe Mongoid::Listable do
|
4
4
|
|
5
5
|
before :all do
|
6
|
-
|
7
|
-
|
8
|
-
10.times { @photos << Photo.create }
|
6
|
+
User.create!
|
7
|
+
10.times { Photo.create }
|
9
8
|
end
|
10
9
|
|
11
10
|
it 'created a user' do
|
12
|
-
expect(
|
11
|
+
expect(User.first).to be_true
|
13
12
|
end
|
14
13
|
|
15
14
|
it 'created 10 photos' do
|
16
|
-
expect(
|
15
|
+
expect(Photo.count).to eq(10)
|
17
16
|
end
|
18
17
|
|
19
|
-
it '
|
20
|
-
|
21
|
-
expect(@user.photos.count).to eq(@photos.count)
|
18
|
+
it 'added the position field for a photo' do
|
19
|
+
expect(Photo.instance_methods.include?(:position)).to be_true
|
22
20
|
end
|
23
21
|
|
24
|
-
it '
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
it 'orders photos' do
|
23
|
+
Photo.list.each_with_index do |photo, index|
|
24
|
+
expect(photo.position).to eq(index + 1)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
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
|
31
|
+
|
32
|
+
expect(Photo.find(photo_a_id).position).to eq(4)
|
33
|
+
expect(Photo.find(photo_b_id).position).to eq(8)
|
34
|
+
|
35
|
+
Photo.find(photo_a_id).update_attribute :position, 9
|
36
|
+
|
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
|
+
|
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
|
44
|
+
|
45
|
+
expect(Photo.find(photo_a_id).position).to eq(6)
|
46
|
+
expect(Photo.find(photo_b_id).position).to eq(10)
|
47
|
+
|
48
|
+
Photo.find(photo_a_id).update_attribute :position, 2
|
49
|
+
|
50
|
+
expect(Photo.find(photo_a_id).position).to eq(2)
|
51
|
+
expect(Photo.find(photo_b_id).position).to eq(10)
|
52
|
+
end
|
53
|
+
|
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
|
57
|
+
|
58
|
+
expect(Photo.find(photo_b_id).position).to eq(10)
|
59
|
+
|
60
|
+
Photo.find(photo_a_id).destroy
|
61
|
+
|
62
|
+
expect(Photo.find(photo_b_id).position).to eq(9)
|
63
|
+
end
|
64
|
+
|
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
|
70
|
+
|
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
|
75
|
+
|
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)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'removes photos from a user' do
|
83
|
+
User.first.photos = nil
|
84
|
+
expect(User.first.photos.count).to eq(0)
|
85
|
+
end
|
86
|
+
|
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
|
91
|
+
|
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
|
96
|
+
|
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)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
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)
|
28
107
|
end
|
29
108
|
|
30
|
-
it '
|
31
|
-
|
32
|
-
expect(
|
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)
|
33
113
|
end
|
34
114
|
|
35
|
-
it '
|
36
|
-
|
37
|
-
expect(
|
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)
|
38
119
|
end
|
39
120
|
|
40
|
-
it '
|
121
|
+
it 'orders photos for a user' do
|
41
122
|
User.first.photos.each_with_index do |photo, index|
|
42
123
|
expect(photo.user_position).to eq(index + 1)
|
43
124
|
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.0
|
4
|
+
version: 0.1.0
|
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-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mongoid
|