sequel_orderable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|