dm-is-list 0.9.5 → 0.9.6
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.
- data/Rakefile +1 -1
- data/lib/dm-is-list.rb +2 -2
- data/lib/dm-is-list/is/list.rb +42 -38
- data/lib/dm-is-list/is/version.rb +1 -1
- data/spec/integration/list_spec.rb +12 -2
- data/spec/spec_helper.rb +1 -1
- metadata +3 -3
data/Rakefile
CHANGED
@@ -45,5 +45,5 @@ end
|
|
45
45
|
desc 'Run specifications'
|
46
46
|
Spec::Rake::SpecTask.new(:spec) do |t|
|
47
47
|
t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
|
48
|
-
t.spec_files = Pathname.glob(
|
48
|
+
t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s)
|
49
49
|
end
|
data/lib/dm-is-list.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'pathname'
|
4
4
|
|
5
|
-
gem 'dm-core', '=0.9.
|
5
|
+
gem 'dm-core', '=0.9.6'
|
6
6
|
require 'dm-core'
|
7
7
|
|
8
|
-
gem 'dm-adjust', '=0.9.
|
8
|
+
gem 'dm-adjust', '=0.9.6'
|
9
9
|
require 'dm-adjust'
|
10
10
|
|
11
11
|
require Pathname(__FILE__).dirname.expand_path / 'dm-is-list' / 'is' / 'list.rb'
|
data/lib/dm-is-list/is/list.rb
CHANGED
@@ -19,31 +19,32 @@ module DataMapper
|
|
19
19
|
# @option :scope<Array> an array of attributes that should be used to scope lists
|
20
20
|
#
|
21
21
|
def is_list(options={})
|
22
|
-
options = { :scope => [] }.merge(options)
|
22
|
+
options = { :scope => [], :first => 1 }.merge(options)
|
23
23
|
|
24
24
|
extend DataMapper::Is::List::ClassMethods
|
25
25
|
include DataMapper::Is::List::InstanceMethods
|
26
26
|
|
27
27
|
property :position, Integer unless properties.detect{|p| p.name == :position && p.type == Integer}
|
28
28
|
|
29
|
-
@
|
29
|
+
@list_options = options
|
30
30
|
|
31
31
|
before :save do
|
32
32
|
if self.new_record?
|
33
33
|
# a position has been set before save => open up and make room for item
|
34
34
|
# no position has been set => move to bottom of my scope-list (or keep detached?)
|
35
|
-
self.
|
35
|
+
self.send(:move_without_saving, (self.position || :lowest))
|
36
36
|
else
|
37
37
|
# if the scope has changed, we need to detach our item from the old list
|
38
38
|
if self.list_scope != self.original_list_scope
|
39
|
-
oldpos = self.original_values[:position]
|
40
39
|
newpos = self.position
|
41
40
|
|
42
41
|
self.detach(self.original_list_scope) # removing from old list
|
43
|
-
self.
|
42
|
+
self.send(:move_without_saving, newpos || :lowest) # moving to pos or bottom of new list
|
44
43
|
|
45
|
-
elsif self.attribute_dirty?(:position)
|
46
|
-
self.
|
44
|
+
elsif self.attribute_dirty?(:position) && !self.moved
|
45
|
+
self.send(:move_without_saving, self.position)
|
46
|
+
else
|
47
|
+
self.moved = false
|
47
48
|
end
|
48
49
|
# a (new) position has been set => move item to this position (only if position has been set manually)
|
49
50
|
# the scope has changed => detach from old list, and possibly move into position
|
@@ -57,13 +58,13 @@ module DataMapper
|
|
57
58
|
|
58
59
|
# we need to make sure that STI-models will inherit the list_scope.
|
59
60
|
after_class_method :inherited do |retval, target|
|
60
|
-
target.instance_variable_set(:@
|
61
|
+
target.instance_variable_set(:@list_options, @list_options.dup)
|
61
62
|
end
|
62
63
|
|
63
64
|
end
|
64
65
|
|
65
66
|
module ClassMethods
|
66
|
-
attr_reader :
|
67
|
+
attr_reader :list_options
|
67
68
|
|
68
69
|
##
|
69
70
|
# use this function to repair / build your lists.
|
@@ -75,19 +76,20 @@ module DataMapper
|
|
75
76
|
# @param scope [Hash]
|
76
77
|
#
|
77
78
|
def repair_list(scope={})
|
78
|
-
return false unless scope.keys.all?{|s|
|
79
|
+
return false unless scope.keys.all?{|s| list_options[:scope].include?(s) || s == :order }
|
79
80
|
all({:order => [:position.asc]}.merge(scope)).each_with_index{ |item,i| item.position = i+1; item.save }
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
83
84
|
module InstanceMethods
|
85
|
+
attr_accessor :moved
|
84
86
|
|
85
87
|
def list_scope
|
86
|
-
self.class.
|
88
|
+
self.class.list_options[:scope].map{|p| [p,attribute_get(p)]}.to_hash
|
87
89
|
end
|
88
90
|
|
89
91
|
def original_list_scope
|
90
|
-
self.class.
|
92
|
+
self.class.list_options[:scope].map{|p| [p,original_values.key?(p) ? original_values[p] : attribute_get(p)]}.to_hash
|
91
93
|
end
|
92
94
|
|
93
95
|
def list_query
|
@@ -112,6 +114,19 @@ module DataMapper
|
|
112
114
|
self.class.repair_list(list_scope.merge(:order => order))
|
113
115
|
end
|
114
116
|
|
117
|
+
def detach(scope=list_scope)
|
118
|
+
list(scope).all(:position.gt => position).adjust!({:position => -1},true)
|
119
|
+
self.position = nil
|
120
|
+
end
|
121
|
+
|
122
|
+
def left_sibling
|
123
|
+
list.reverse.first(:position.lt => position)
|
124
|
+
end
|
125
|
+
|
126
|
+
def right_sibling
|
127
|
+
list.first(:position.gt => position)
|
128
|
+
end
|
129
|
+
|
115
130
|
##
|
116
131
|
# move item to a position in the list. position should _only_ be changed through this
|
117
132
|
#
|
@@ -143,52 +158,41 @@ module DataMapper
|
|
143
158
|
# does all the actual movement in #move, but does not save afterwards. this is used internally in
|
144
159
|
# before :save, and will probably be marked private. should not be used by organic beings.
|
145
160
|
#
|
146
|
-
# @see
|
161
|
+
# @see move
|
162
|
+
private
|
147
163
|
def move_without_saving(vector)
|
148
164
|
if vector.is_a? Hash then action,object = vector.keys[0],vector.values[0] else action = vector end
|
149
165
|
|
150
|
-
|
151
|
-
|
166
|
+
minpos = self.class.list_options[:first]
|
167
|
+
prepos = self.original_values[:position] || self.position
|
168
|
+
maxpos = list.last ? (list.last == self ? prepos : list.last.position + 1) : minpos
|
152
169
|
newpos = case action
|
153
|
-
when :highest then
|
170
|
+
when :highest then minpos
|
154
171
|
when :lowest then maxpos
|
155
|
-
when :higher,:up then [position-1,
|
172
|
+
when :higher,:up then [position-1,minpos].max
|
156
173
|
when :lower,:down then [position+1,maxpos].min
|
157
174
|
when :above then object.position
|
158
175
|
when :below then object.position+1
|
159
|
-
when :to then [object.to_i,maxpos].min
|
176
|
+
when :to then [minpos,[object.to_i,maxpos].min].max
|
177
|
+
else [action.to_i,maxpos].min
|
160
178
|
end
|
161
179
|
|
162
180
|
return false if !newpos || ([:above,:below].include?(action) && list_scope != object.list_scope)
|
163
|
-
return true if newpos == position || (newpos == maxpos && position == maxpos-1)
|
181
|
+
return true if newpos == position && position == prepos || (newpos == maxpos && position == maxpos-1)
|
164
182
|
|
165
183
|
if !position
|
166
184
|
list.all(:position.gte => newpos).adjust!({:position => +1},true) unless action == :lowest
|
167
|
-
elsif newpos >
|
185
|
+
elsif newpos > prepos
|
168
186
|
newpos -= 1 if [:lowest,:above,:below,:to].include?(action)
|
169
|
-
list.all(:position =>
|
170
|
-
elsif newpos <
|
171
|
-
list.all(:position => newpos..
|
187
|
+
list.all(:position => prepos..newpos).adjust!({:position => -1},true)
|
188
|
+
elsif newpos < prepos
|
189
|
+
list.all(:position => newpos..prepos).adjust!({:position => +1},true)
|
172
190
|
end
|
173
191
|
|
174
192
|
self.position = newpos
|
175
|
-
|
193
|
+
self.moved = true
|
176
194
|
true
|
177
195
|
end
|
178
|
-
|
179
|
-
def detach(scope=list_scope)
|
180
|
-
list(scope).all(:position.gt => position).adjust!({:position => -1},true)
|
181
|
-
self.position = nil
|
182
|
-
end
|
183
|
-
|
184
|
-
def left_sibling
|
185
|
-
list.reverse.first(:position.lt => position)
|
186
|
-
end
|
187
|
-
|
188
|
-
def right_sibling
|
189
|
-
list.first(:position.gt => position)
|
190
|
-
end
|
191
|
-
|
192
196
|
end
|
193
197
|
end # List
|
194
198
|
end # Is
|
@@ -57,15 +57,23 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
57
57
|
Todo.get(6).position.should == 3
|
58
58
|
end
|
59
59
|
end
|
60
|
+
|
61
|
+
it 'should rearrange items when setting position yourself' do
|
62
|
+
repository(:default) do |repos|
|
63
|
+
Todo.get(2).update_attributes(:position => 1)
|
64
|
+
Todo.get(2).position.should == 1
|
65
|
+
Todo.get(1).position.should == 2
|
66
|
+
end
|
67
|
+
end
|
60
68
|
end
|
61
69
|
|
62
70
|
describe 'movement' do
|
63
71
|
it 'should rearrange items correctly when moving :higher' do
|
64
72
|
repository(:default) do |repos|
|
65
73
|
Todo.get(3).move :higher
|
74
|
+
Todo.get(4).position.should == 1
|
66
75
|
Todo.get(3).position.should == 2
|
67
76
|
Todo.get(2).position.should == 3
|
68
|
-
Todo.get(4).position.should == 1
|
69
77
|
end
|
70
78
|
end
|
71
79
|
|
@@ -128,7 +136,9 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
128
136
|
item.user_id = 1
|
129
137
|
item.save
|
130
138
|
|
131
|
-
item.
|
139
|
+
item.list_scope.should != item.original_list_scope
|
140
|
+
item.position.should == 1
|
141
|
+
Todo.get(1).position.should == 2
|
132
142
|
Todo.get(5).position.should == 1
|
133
143
|
|
134
144
|
item.user_id = 2
|
data/spec/spec_helper.rb
CHANGED
@@ -10,7 +10,7 @@ def load_driver(name, default_uri)
|
|
10
10
|
lib = "do_#{name}"
|
11
11
|
|
12
12
|
begin
|
13
|
-
gem lib, '
|
13
|
+
gem lib, '>=0.9.5'
|
14
14
|
require lib
|
15
15
|
DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
|
16
16
|
DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-is-list
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sindre Aarsaether
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-10-12 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - "="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.9.
|
23
|
+
version: 0.9.6
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: hoe
|