sequel_orderable 0.0.1
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/CHANGELOG +1 -0
- data/COPYING +18 -0
- data/README +187 -0
- data/Rakefile +158 -0
- data/lib/sequel_orderable.rb +84 -0
- data/spec/sequel_orderable_spec.rb +116 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +6 -0
- metadata +78 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* 2007.12.02 Initial working revision.
|
data/COPYING
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2007 Sharon Rosner, Wayne E. Seguin, Aman Gupta
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
= Sequel Orderable Plugin
|
2
|
+
|
3
|
+
Allows for model instances to be part of an ordered list,
|
4
|
+
based on a 'position' field in the database.
|
5
|
+
|
6
|
+
== Basic Usage
|
7
|
+
|
8
|
+
Load the plugin into the model:
|
9
|
+
|
10
|
+
is :orderable
|
11
|
+
|
12
|
+
Given:
|
13
|
+
|
14
|
+
class Item < Sequel::Model(:items)
|
15
|
+
set_schema do
|
16
|
+
primary_key :id
|
17
|
+
varchar :name
|
18
|
+
int :position
|
19
|
+
end
|
20
|
+
is :orderable, :field => :position
|
21
|
+
end
|
22
|
+
|
23
|
+
item = Item[1]
|
24
|
+
|
25
|
+
The plugin provides access to the previous and next item in the list
|
26
|
+
|
27
|
+
item.next
|
28
|
+
item.prev
|
29
|
+
|
30
|
+
And methods to change the position of an item (and update affected items accordingly)
|
31
|
+
|
32
|
+
item.move_to(new_position)
|
33
|
+
item.move_to_top
|
34
|
+
item.move_to_bottom
|
35
|
+
item.move_up
|
36
|
+
item.move_down
|
37
|
+
|
38
|
+
== Scoping
|
39
|
+
|
40
|
+
You can scope the position field by another field.
|
41
|
+
|
42
|
+
For example, to allow each user to have their own a distinct orderable list:
|
43
|
+
|
44
|
+
class UserItem < Sequel::Model(:items)
|
45
|
+
set_schema do
|
46
|
+
primary_key :id
|
47
|
+
varchar :name
|
48
|
+
int :user_id
|
49
|
+
int :pos
|
50
|
+
end
|
51
|
+
is :orderable, :field => :pos, :scope => :user_id
|
52
|
+
end
|
53
|
+
|
54
|
+
All the defined methods will operate within the 'user_id' field's scope.
|
55
|
+
|
56
|
+
== Examples
|
57
|
+
|
58
|
+
# Input: irb
|
59
|
+
require "sequel"
|
60
|
+
|
61
|
+
DB = Sequel.sqlite
|
62
|
+
class Item < Sequel::Model(:items)
|
63
|
+
set_schema do
|
64
|
+
primary_key :id
|
65
|
+
varchar :name
|
66
|
+
int :position
|
67
|
+
end
|
68
|
+
is :orderable, :field => :position
|
69
|
+
end
|
70
|
+
|
71
|
+
Item.create_table!
|
72
|
+
Item.create :name => "alice", :position => 2
|
73
|
+
Item.create :name => "bob", :position => 1
|
74
|
+
Item.create :name => "charlie", :position => 4
|
75
|
+
Item.create :name => "darwin", :position => 3
|
76
|
+
|
77
|
+
Item.print
|
78
|
+
|
79
|
+
Item[:name => "alice"].move_down
|
80
|
+
Item.print
|
81
|
+
Item[:name => "darwin"].move_to_top
|
82
|
+
Item.print
|
83
|
+
Item[:name => "alice"].next
|
84
|
+
Item.print
|
85
|
+
Item[:name => "bob"].prev
|
86
|
+
Item.print
|
87
|
+
Item[:name => "darwin"].move_to(3)
|
88
|
+
Item.print
|
89
|
+
Item[:name => "bob"].move_to_bottom
|
90
|
+
Item.print
|
91
|
+
|
92
|
+
|
93
|
+
# Output
|
94
|
+
>> Item.print
|
95
|
+
+--+-------+--------+
|
96
|
+
|id|name |position|
|
97
|
+
+--+-------+--------+
|
98
|
+
| 2|bob | 1|
|
99
|
+
| 1|alice | 2|
|
100
|
+
| 4|darwin | 3|
|
101
|
+
| 3|charlie| 4|
|
102
|
+
+--+-------+--------+
|
103
|
+
=> nil
|
104
|
+
|
105
|
+
>> Item[:name => "alice"].move_down
|
106
|
+
=> {:position=>3}
|
107
|
+
|
108
|
+
>> Item.print
|
109
|
+
+--+-------+--------+
|
110
|
+
|id|name |position|
|
111
|
+
+--+-------+--------+
|
112
|
+
| 2|bob | 1|
|
113
|
+
| 4|darwin | 2|
|
114
|
+
| 1|alice | 3|
|
115
|
+
| 3|charlie| 4|
|
116
|
+
+--+-------+--------+
|
117
|
+
=> nil
|
118
|
+
|
119
|
+
>> Item[:name => "darwin"].move_to_top
|
120
|
+
=> {:position=>1}
|
121
|
+
|
122
|
+
>> Item.print
|
123
|
+
+--+-------+--------+
|
124
|
+
|id|name |position|
|
125
|
+
+--+-------+--------+
|
126
|
+
| 4|darwin | 1|
|
127
|
+
| 2|bob | 2|
|
128
|
+
| 1|alice | 3|
|
129
|
+
| 3|charlie| 4|
|
130
|
+
+--+-------+--------+
|
131
|
+
=> nil
|
132
|
+
|
133
|
+
>> Item[:name => "alice"].next
|
134
|
+
=> #<Item:0x119dbc8 @values={:position=>4, :name=>"charlie", :id=>3}, newfalse
|
135
|
+
|
136
|
+
>> Item.print
|
137
|
+
+--+-------+--------+
|
138
|
+
|id|name |position|
|
139
|
+
+--+-------+--------+
|
140
|
+
| 4|darwin | 1|
|
141
|
+
| 2|bob | 2|
|
142
|
+
| 1|alice | 3|
|
143
|
+
| 3|charlie| 4|
|
144
|
+
+--+-------+--------+
|
145
|
+
=> nil
|
146
|
+
|
147
|
+
>> Item[:name => "bob"].prev
|
148
|
+
=> #<Item:0x1184bb4 @values={:position=>1, :name=>"darwin", :id=>4}, newfalse
|
149
|
+
|
150
|
+
>> Item.print
|
151
|
+
+--+-------+--------+
|
152
|
+
|id|name |position|
|
153
|
+
+--+-------+--------+
|
154
|
+
| 4|darwin | 1|
|
155
|
+
| 2|bob | 2|
|
156
|
+
| 1|alice | 3|
|
157
|
+
| 3|charlie| 4|
|
158
|
+
+--+-------+--------+
|
159
|
+
=> nil
|
160
|
+
|
161
|
+
>> Item[:name => "darwin"].move_to(3)
|
162
|
+
=> {:position=>3}
|
163
|
+
|
164
|
+
>> Item.print
|
165
|
+
+--+-------+--------+
|
166
|
+
|id|name |position|
|
167
|
+
+--+-------+--------+
|
168
|
+
| 2|bob | 1|
|
169
|
+
| 1|alice | 2|
|
170
|
+
| 4|darwin | 3|
|
171
|
+
| 3|charlie| 4|
|
172
|
+
+--+-------+--------+
|
173
|
+
=> nil
|
174
|
+
|
175
|
+
>> Item[:name => "bob"].move_to_bottom
|
176
|
+
=> {:position=>4}
|
177
|
+
|
178
|
+
>> Item.print
|
179
|
+
+--+-------+--------+
|
180
|
+
|id|name |position|
|
181
|
+
+--+-------+--------+
|
182
|
+
| 1|alice | 1|
|
183
|
+
| 4|darwin | 2|
|
184
|
+
| 3|charlie| 3|
|
185
|
+
| 2|bob | 4|
|
186
|
+
+--+-------+--------+
|
187
|
+
=> nil
|
data/Rakefile
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# Constants
|
3
|
+
##############################################################################
|
4
|
+
|
5
|
+
PluginName = "sequel_orderable"
|
6
|
+
Version = "0.0.1"
|
7
|
+
Title = "Orderable Sequel Plugin"
|
8
|
+
Summary = "Sequel Plugin"
|
9
|
+
Authors = "Wayne E. Seguin & Aman Gupta"
|
10
|
+
Emails = "wayneeseugin@gmail.com,sequel@tmm1.net"
|
11
|
+
Homepage = "http://sequel.rubyforge.org"
|
12
|
+
|
13
|
+
##############################################################################
|
14
|
+
# Gem Management
|
15
|
+
##############################################################################
|
16
|
+
require "rake"
|
17
|
+
require "rake/clean"
|
18
|
+
require "rake/gempackagetask"
|
19
|
+
require "rake/rdoctask"
|
20
|
+
require "fileutils"
|
21
|
+
|
22
|
+
include FileUtils
|
23
|
+
|
24
|
+
CLEAN.include ["**/.*.sw?", "pkg/*", ".config", "doc/*", "coverage/*"]
|
25
|
+
|
26
|
+
RDocOptions = [
|
27
|
+
"--quiet", "--title", Title,
|
28
|
+
"--opname", "index.html",
|
29
|
+
"--line-numbers",
|
30
|
+
"--main", "README",
|
31
|
+
"--inline-source"
|
32
|
+
]
|
33
|
+
|
34
|
+
desc "Packages up the Sequel Plugin: #{PluginName}."
|
35
|
+
task :default => [:package]
|
36
|
+
task :package => [:clean]
|
37
|
+
|
38
|
+
task :doc => [:rdoc]
|
39
|
+
|
40
|
+
Rake::RDocTask.new do |rdoc|
|
41
|
+
rdoc.rdoc_dir = "doc/rdoc"
|
42
|
+
rdoc.options += RDocOptions
|
43
|
+
rdoc.main = "README"
|
44
|
+
rdoc.title = Title
|
45
|
+
rdoc.rdoc_files.add ["README", "COPYING", "lib/#{PluginName}.rb", "lib/**/*.rb"]
|
46
|
+
end
|
47
|
+
|
48
|
+
spec = Gem::Specification.new do |s|
|
49
|
+
s.name = PluginName
|
50
|
+
s.version = Version
|
51
|
+
s.platform = Gem::Platform::RUBY
|
52
|
+
s.has_rdoc = true
|
53
|
+
s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"]
|
54
|
+
s.rdoc_options += RDocOptions# +
|
55
|
+
#["--exclude", "^(examples|extras)\/", "--exclude", "lib/sequel.rb"]
|
56
|
+
s.summary = Summary
|
57
|
+
s.description = Summary
|
58
|
+
s.author = Authors
|
59
|
+
s.email = Emails
|
60
|
+
s.homepage = Homepage
|
61
|
+
# change this to the plugin name, if the plugin has command line portion
|
62
|
+
#s.executables = ["sequel"]
|
63
|
+
|
64
|
+
s.add_dependency("sequel")
|
65
|
+
#s.add_dependency("sequel", ">= 0.4.1")
|
66
|
+
|
67
|
+
#s.required_ruby_version = ">= 1.8.4" # Sequel should take care of this :)
|
68
|
+
|
69
|
+
s.files = %w(COPYING README Rakefile) + Dir.glob("{bin,doc,spec,lib}/**/*")
|
70
|
+
|
71
|
+
s.require_path = "lib"
|
72
|
+
s.bindir = "bin"
|
73
|
+
end
|
74
|
+
|
75
|
+
Rake::GemPackageTask.new(spec) do |p|
|
76
|
+
p.need_tar = true
|
77
|
+
p.gem_spec = spec
|
78
|
+
end
|
79
|
+
|
80
|
+
task :release => [:package] do
|
81
|
+
sh %{rubyforge login}
|
82
|
+
sh %{rubyforge add_release sequel #{PluginName} #{Version} pkg/#{PluginName}-#{Version}.tgz}
|
83
|
+
sh %{rubyforge add_file sequel #{PluginName} #{Version} pkg/#{PluginName}-#{Version}.gem}
|
84
|
+
end
|
85
|
+
|
86
|
+
task :install do
|
87
|
+
sh %{rake package}
|
88
|
+
sh %{sudo gem install pkg/#{PluginName}-#{Version}.gem}
|
89
|
+
end
|
90
|
+
|
91
|
+
task :install_no_docs do
|
92
|
+
sh %{rake package}
|
93
|
+
sh %{sudo gem install pkg/#{PluginName}-#{Version} --no-rdoc --no-ri}
|
94
|
+
end
|
95
|
+
|
96
|
+
task :uninstall => [:clean] do
|
97
|
+
sh %{sudo gem uninstall #{PluginName}}
|
98
|
+
end
|
99
|
+
|
100
|
+
desc "Update docs and upload to rubyforge.org"
|
101
|
+
task :doc_rforge do
|
102
|
+
sh %{rake doc}
|
103
|
+
sh %{scp -r doc/rdoc/* ciconia@rubyforge.org:/var/www/gforge-projects/sequel/plugins/#{PluginName}}
|
104
|
+
end
|
105
|
+
|
106
|
+
##############################################################################
|
107
|
+
# rSpec
|
108
|
+
##############################################################################
|
109
|
+
|
110
|
+
require "spec/rake/spectask"
|
111
|
+
|
112
|
+
desc "Run specs with coverage"
|
113
|
+
Spec::Rake::SpecTask.new("spec") do |spec_task|
|
114
|
+
spec_task.spec_opts = File.read("spec/spec.opts").split("\n")
|
115
|
+
spec_task.spec_files = FileList["spec/*_spec.rb"].sort
|
116
|
+
spec_task.rcov = true
|
117
|
+
end
|
118
|
+
|
119
|
+
desc "Run specs without coverage"
|
120
|
+
Spec::Rake::SpecTask.new("spec_no_cov") do |spec_task|
|
121
|
+
spec_task.spec_opts = File.read("spec/spec.opts").split("\n")
|
122
|
+
spec_task.spec_files = FileList["spec/*_spec.rb"].sort
|
123
|
+
end
|
124
|
+
|
125
|
+
desc "Run all specs with coverage"
|
126
|
+
Spec::Rake::SpecTask.new("specs") do |spec_task|
|
127
|
+
spec_task.spec_opts = File.read("spec/spec.opts").split("\n")
|
128
|
+
spec_task.spec_files = FileList["spec/**/*_spec.rb"].sort
|
129
|
+
spec_task.rcov = true
|
130
|
+
end
|
131
|
+
|
132
|
+
desc "Run all specs without coverage"
|
133
|
+
Spec::Rake::SpecTask.new("specs_no_cov") do |spec_task|
|
134
|
+
spec_task.spec_opts = File.read("spec/spec.opts").split("\n")
|
135
|
+
spec_task.spec_files = FileList["spec/**/*_spec.rb"].sort
|
136
|
+
end
|
137
|
+
|
138
|
+
desc "Run all specs and output html"
|
139
|
+
Spec::Rake::SpecTask.new("specs_html") do |spec_task|
|
140
|
+
spec_task.spec_opts = ["--format", "html"]
|
141
|
+
spec_task.spec_files = Dir["spec/**/*_spec.rb"].sort
|
142
|
+
end
|
143
|
+
|
144
|
+
##############################################################################
|
145
|
+
# Statistics
|
146
|
+
##############################################################################
|
147
|
+
|
148
|
+
STATS_DIRECTORIES = [
|
149
|
+
%w(Code lib/),
|
150
|
+
%w(Spec spec/)
|
151
|
+
].collect { |name, dir| [ name, "./#{dir}" ] }.select { |name, dir| File.directory?(dir) }
|
152
|
+
|
153
|
+
desc "Report code statistics (KLOCs, etc) from the application"
|
154
|
+
task :stats do
|
155
|
+
require "extra/stats"
|
156
|
+
verbose = true
|
157
|
+
CodeStatistics.new(*STATS_DIRECTORIES).to_s
|
158
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
module Orderable
|
4
|
+
|
5
|
+
def self.apply(model, opts = {})
|
6
|
+
position_field = opts[:field] || :position
|
7
|
+
scope_field = opts[:scope]
|
8
|
+
|
9
|
+
model.class_def(:at_position) do |p|
|
10
|
+
if scope_field
|
11
|
+
dataset.first(scope_field => @values[scope_field], position_field => p)
|
12
|
+
else
|
13
|
+
dataset.first(position_field => p)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
model.class_def(:move_to) do |pos|
|
18
|
+
# XXX: error checking, negative pos?
|
19
|
+
cur_pos = position
|
20
|
+
return self if pos == cur_pos
|
21
|
+
|
22
|
+
db.transaction do
|
23
|
+
if pos < cur_pos
|
24
|
+
ds = self.class.filter {position_field >= pos and position_field < cur_pos}
|
25
|
+
ds.filter!(scope_field => @values[scope_field]) if scope_field
|
26
|
+
ds.update(position_field => "#{position_field} + 1".lit)
|
27
|
+
elsif pos > cur_pos
|
28
|
+
ds = self.class.filter {position_field > cur_pos and position_field <= pos}
|
29
|
+
ds.filter!(scope_field => @values[scope_field]) if scope_field
|
30
|
+
ds.update(position_field => "#{position_field} - 1".lit)
|
31
|
+
end
|
32
|
+
set(position_field => pos)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
model.class_def(:move_to_bottom) do
|
37
|
+
ds = dataset
|
38
|
+
ds = ds.filter(scope_field => @values[scope_field]) if scope_field
|
39
|
+
last = ds.select(:max[position_field] => :max).first.values[:max].to_i
|
40
|
+
self.move_to(last)
|
41
|
+
end
|
42
|
+
|
43
|
+
model.class_def(:position) {self[position_field]}
|
44
|
+
|
45
|
+
if scope_field
|
46
|
+
model.dataset.order!(scope_field, position_field)
|
47
|
+
else
|
48
|
+
model.dataset.order!(position_field)
|
49
|
+
end
|
50
|
+
|
51
|
+
model.send(:include, InstanceMethods)
|
52
|
+
end
|
53
|
+
|
54
|
+
module InstanceMethods
|
55
|
+
def prev(n = 1)
|
56
|
+
target = position - n
|
57
|
+
# XXX: error checking, negative target?
|
58
|
+
return self if position == target
|
59
|
+
at_position(target)
|
60
|
+
end
|
61
|
+
|
62
|
+
def next(n = 1)
|
63
|
+
target = position + n
|
64
|
+
at_position(target)
|
65
|
+
end
|
66
|
+
|
67
|
+
def move_up(n = 1)
|
68
|
+
# XXX: position == 1 already?
|
69
|
+
self.move_to(position-n)
|
70
|
+
end
|
71
|
+
|
72
|
+
def move_down(n = 1)
|
73
|
+
# XXX: what if we're already at the bottom
|
74
|
+
self.move_to(position+n)
|
75
|
+
end
|
76
|
+
|
77
|
+
def move_to_top
|
78
|
+
self.move_to(1)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
DB = Sequel.sqlite
|
4
|
+
|
5
|
+
class Item < Sequel::Model(:items)
|
6
|
+
|
7
|
+
set_schema do
|
8
|
+
primary_key :id
|
9
|
+
varchar :name
|
10
|
+
int :pos
|
11
|
+
end
|
12
|
+
|
13
|
+
is :orderable, :field => :pos
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Item do
|
18
|
+
before(:all) {
|
19
|
+
Item.create_table!
|
20
|
+
|
21
|
+
Item.create :name => "one", :pos => 3
|
22
|
+
Item.create :name => "two", :pos => 2
|
23
|
+
Item.create :name => "three", :pos => 1
|
24
|
+
}
|
25
|
+
|
26
|
+
it "should return rows in order of position" do
|
27
|
+
Item.map(&:pos).should == [1,2,3]
|
28
|
+
Item.map(&:name).should == %w[ three two one ]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should define prev and next" do
|
32
|
+
i = Item[:name => "two"]
|
33
|
+
i.prev.should == Item[:name => "three"]
|
34
|
+
i.next.should == Item[:name => "one"]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should define move_to" do
|
38
|
+
Item[:name => "two"].move_to(1)
|
39
|
+
Item.map(&:name).should == %w[ two three one ]
|
40
|
+
|
41
|
+
Item[:name => "two"].move_to(3)
|
42
|
+
Item.map(&:name).should == %w[ three one two ]
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should define move_to_top and move_to_bottom" do
|
46
|
+
Item[:name => "two"].move_to_top
|
47
|
+
Item.map(&:name).should == %w[ two three one ]
|
48
|
+
|
49
|
+
Item[:name => "two"].move_to_bottom
|
50
|
+
Item.map(&:name).should == %w[ three one two ]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should define move_up and move_down" do
|
54
|
+
Item[:name => "one"].move_up
|
55
|
+
Item.map(&:name).should == %w[ one three two ]
|
56
|
+
|
57
|
+
Item[:name => "three"].move_down
|
58
|
+
Item.map(&:name).should == %w[ one two three ]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
class ListItem < Sequel::Model(:list_items)
|
64
|
+
|
65
|
+
set_schema do
|
66
|
+
primary_key :id
|
67
|
+
int :list_id
|
68
|
+
varchar :name
|
69
|
+
int :position
|
70
|
+
end
|
71
|
+
|
72
|
+
is :orderable, :scope => :list_id
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe ListItem do
|
77
|
+
|
78
|
+
before(:all) {
|
79
|
+
ListItem.create_table!
|
80
|
+
|
81
|
+
ListItem.create :name => "a", :list_id => 1, :position => 3
|
82
|
+
ListItem.create :name => "b", :list_id => 1, :position => 2
|
83
|
+
ListItem.create :name => "c", :list_id => 1, :position => 1
|
84
|
+
|
85
|
+
ListItem.create :name => "d", :list_id => 2, :position => 1
|
86
|
+
ListItem.create :name => "e", :list_id => 2, :position => 2
|
87
|
+
ListItem.create :name => "f", :list_id => 2, :position => 3
|
88
|
+
}
|
89
|
+
|
90
|
+
it "should print in order with scope provided" do
|
91
|
+
ListItem.map(&:name).should == %w[ c b a d e f ]
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should fetch prev and next records with scope" do
|
95
|
+
b = ListItem[:name => "b"]
|
96
|
+
b.next.name.should == "a"
|
97
|
+
b.prev.name.should == "c"
|
98
|
+
b.next.next.should be_nil
|
99
|
+
b.prev.prev.should be_nil
|
100
|
+
|
101
|
+
e = ListItem[:name => "e"]
|
102
|
+
e.next.name.should == "f"
|
103
|
+
e.prev.name.should == "d"
|
104
|
+
e.next.next.should be_nil
|
105
|
+
e.prev.prev.should be_nil
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should move only within the scope provided" do
|
109
|
+
ListItem[:name => "b"].move_to_top
|
110
|
+
ListItem.map(&:name).should == %w[ b c a d e f ]
|
111
|
+
|
112
|
+
ListItem[:name => "c"].move_to_bottom
|
113
|
+
ListItem.map(&:name).should == %w[ b a c d e f ]
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sequel_orderable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wayne E. Seguin & Aman Gupta
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2007-12-04 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: sequel
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
description: Sequel Plugin
|
25
|
+
email: wayneeseugin@gmail.com,sequel@tmm1.net
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- README
|
32
|
+
- CHANGELOG
|
33
|
+
- COPYING
|
34
|
+
files:
|
35
|
+
- COPYING
|
36
|
+
- README
|
37
|
+
- Rakefile
|
38
|
+
- spec/sequel_orderable_spec.rb
|
39
|
+
- spec/spec.opts
|
40
|
+
- spec/spec_helper.rb
|
41
|
+
- lib/sequel_orderable.rb
|
42
|
+
- CHANGELOG
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://sequel.rubyforge.org
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options:
|
47
|
+
- --quiet
|
48
|
+
- --title
|
49
|
+
- Orderable Sequel Plugin
|
50
|
+
- --opname
|
51
|
+
- index.html
|
52
|
+
- --line-numbers
|
53
|
+
- --main
|
54
|
+
- README
|
55
|
+
- --inline-source
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 0.9.5
|
74
|
+
signing_key:
|
75
|
+
specification_version: 2
|
76
|
+
summary: Sequel Plugin
|
77
|
+
test_files: []
|
78
|
+
|