resort 0.0.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Readme.md +12 -14
- data/lib/generators/active_record/resort_generator.rb +30 -0
- data/lib/generators/active_record/templates/migration.rb +17 -0
- data/lib/resort/version.rb +1 -1
- data/lib/resort.rb +38 -27
- data/resort.gemspec +1 -0
- data/spec/generators/migration_spec.rb +38 -0
- data/spec/resort_spec.rb +133 -28
- data/spec/spec_helper.rb +35 -0
- metadata +17 -2
data/.gitignore
CHANGED
data/Readme.md
CHANGED
@@ -23,21 +23,10 @@ references a `next` element, which seems a bit more sensible :)
|
|
23
23
|
|
24
24
|
##Usage
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
class AddResortFieldsToProducts < ActiveRecord::Migration
|
29
|
-
def self.up
|
30
|
-
add_column :products, :next_id, :integer
|
31
|
-
add_column :products, :first, :boolean
|
32
|
-
add_index :products, :next_id
|
33
|
-
add_index :products, :first
|
34
|
-
end
|
26
|
+
First, run the migration for the model you want to Resort:
|
35
27
|
|
36
|
-
|
37
|
-
|
38
|
-
remove_column :products, :first
|
39
|
-
end
|
40
|
-
end
|
28
|
+
$ rails generate resort:migration product
|
29
|
+
$ rake db:migrate
|
41
30
|
|
42
31
|
Then in your Product model:
|
43
32
|
|
@@ -57,6 +46,15 @@ separate tree of sortable products, you must override the `siblings` method:
|
|
57
46
|
self.product_line.products
|
58
47
|
end
|
59
48
|
end
|
49
|
+
|
50
|
+
### Concurrency
|
51
|
+
|
52
|
+
Multiple users modifying the same list at the same time could be a problem,
|
53
|
+
so it's always a good practice to wrap the changes in a transaction:
|
54
|
+
|
55
|
+
Product.transaction do
|
56
|
+
my_product.append_to(another_product)
|
57
|
+
end
|
60
58
|
|
61
59
|
###API
|
62
60
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module Resort
|
5
|
+
# Module containing Resort generators
|
6
|
+
module Generators
|
7
|
+
|
8
|
+
# Rails generator to add a migration for Resort
|
9
|
+
class MigrationGenerator < ActiveRecord::Generators::Base
|
10
|
+
# Implement the required interface for `Rails::Generators::Migration`.
|
11
|
+
# Taken from `ActiveRecord` code.
|
12
|
+
# @see http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
|
13
|
+
def self.next_migration_number(dirname)
|
14
|
+
if ActiveRecord::Base.timestamped_migrations
|
15
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
16
|
+
else
|
17
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Creates a Resort migration."
|
22
|
+
source_root File.expand_path("../templates", __FILE__)
|
23
|
+
|
24
|
+
# Copies a migration file adding resort fields to a given model
|
25
|
+
def copy_migration_file
|
26
|
+
migration_template 'migration.rb', "db/migrate/add_resort_fields_to_#{table_name.pluralize}.rb"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Migration to add the necessary fields to a resorted model
|
2
|
+
class AddResortFieldsTo<%= table_name.camelize %> < ActiveRecord::Migration
|
3
|
+
# Adds Resort fields, next_id and first, and indexes to a given model
|
4
|
+
def self.up
|
5
|
+
add_column :<%= table_name %>, :next_id, :integer
|
6
|
+
add_column :<%= table_name %>, :first, :boolean
|
7
|
+
add_index :<%= table_name %>, :next_id
|
8
|
+
add_index :<%= table_name %>, :first
|
9
|
+
end
|
10
|
+
|
11
|
+
# Removes Resort fields
|
12
|
+
def self.down
|
13
|
+
remove_column :<%= table_name %>, :next_id
|
14
|
+
remove_column :<%= table_name %>, :first
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/lib/resort/version.rb
CHANGED
data/lib/resort.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'generators/active_record/resort_generator' if defined?(Rails)
|
2
|
+
|
1
3
|
# # Resort
|
2
4
|
#
|
3
5
|
# A tool that allows any ActiveRecord model to be sorted.
|
@@ -71,12 +73,20 @@ module Resort
|
|
71
73
|
#
|
72
74
|
# @return [ActiveRecord::Base] the first element of the list.
|
73
75
|
def first_in_order
|
74
|
-
where(:first => true).first
|
76
|
+
scoped.where(:first => true).first
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the last element of the list.
|
80
|
+
#
|
81
|
+
# @return [ActiveRecord::Base] the last element of the list.
|
82
|
+
def last_in_order
|
83
|
+
scoped.where(:next_id => nil).first
|
75
84
|
end
|
85
|
+
|
76
86
|
|
77
87
|
# Returns eager-loaded Components in order.
|
78
88
|
#
|
79
|
-
# OPTIMIZE:
|
89
|
+
# OPTIMIZE: Use IdentityMap when available
|
80
90
|
# @return [Array<ActiveRecord::Base>] the ordered elements
|
81
91
|
def ordered
|
82
92
|
ordered_elements = []
|
@@ -90,10 +100,12 @@ module Resort
|
|
90
100
|
end
|
91
101
|
end
|
92
102
|
|
103
|
+
raise "Multiple or no first items in the list where found. Consider defining a siblings method" if ordered_elements.length != 1 && elements.length > 0
|
104
|
+
|
93
105
|
elements.length.times do
|
94
106
|
ordered_elements << elements[ordered_elements.last.next_id]
|
95
107
|
end
|
96
|
-
ordered_elements
|
108
|
+
ordered_elements.compact
|
97
109
|
end
|
98
110
|
end
|
99
111
|
|
@@ -146,47 +158,46 @@ module Resort
|
|
146
158
|
|
147
159
|
# Puts the object in the last position of the list.
|
148
160
|
def push
|
149
|
-
self.append_to(
|
161
|
+
self.append_to(_siblings.last_in_order) unless last?
|
150
162
|
end
|
151
163
|
|
152
164
|
# Puts the object right after another object in the list.
|
153
165
|
def append_to(another)
|
154
|
-
if
|
155
|
-
delete_from_list
|
156
|
-
elsif last? && self.previous
|
157
|
-
# self.previous.update_attribute(:next_id, nil)
|
158
|
-
self.previous = nil
|
159
|
-
end
|
166
|
+
return if another.next_id == id
|
160
167
|
|
161
|
-
|
162
|
-
|
168
|
+
delete_from_list
|
169
|
+
|
170
|
+
self.class.transaction do
|
171
|
+
self.update_attribute(:next_id, another.next_id) if self.next_id or (another && another.next_id)
|
172
|
+
another.update_attribute(:next_id, self.id) if another
|
173
|
+
end
|
163
174
|
end
|
164
175
|
|
165
176
|
private
|
166
177
|
|
167
178
|
def delete_from_list
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
self.
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
179
|
+
self.class.transaction do
|
180
|
+
if first? && self.next
|
181
|
+
self.next.update_attribute(:first, true)
|
182
|
+
elsif self.previous
|
183
|
+
self.previous.update_attribute(:next_id, self.next_id)
|
184
|
+
end
|
185
|
+
|
186
|
+
unless frozen?
|
187
|
+
self.first = false
|
188
|
+
self.next = nil
|
189
|
+
self.previous = nil
|
190
|
+
save!
|
191
|
+
end
|
177
192
|
end
|
178
193
|
end
|
179
194
|
|
180
195
|
def last?
|
181
|
-
self.first
|
182
|
-
end
|
183
|
-
|
184
|
-
def last
|
185
|
-
_siblings.where(:next_id => nil).first
|
196
|
+
!self.first && !self.next_id
|
186
197
|
end
|
187
198
|
|
188
199
|
def last!
|
189
|
-
|
200
|
+
_siblings.last_in_order.update_attribute(:next_id, self.id)
|
190
201
|
end
|
191
202
|
|
192
203
|
def _siblings
|
data/resort.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_development_dependency 'rspec', '~> 2.5.0'
|
20
20
|
s.add_development_dependency 'yard'
|
21
21
|
s.add_development_dependency 'bluecloth'
|
22
|
+
s.add_development_dependency 'generator_spec', '~> 0.8.1'
|
22
23
|
|
23
24
|
s.files = `git ls-files`.split("\n")
|
24
25
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'action_controller'
|
3
|
+
require 'action_view'
|
4
|
+
ActionView::Template::Handlers::ERB::ENCODING_FLAG = ActionView::ENCODING_FLAG
|
5
|
+
require 'generator_spec/test_case'
|
6
|
+
|
7
|
+
module Resort
|
8
|
+
module Generators
|
9
|
+
describe MigrationGenerator do
|
10
|
+
include GeneratorSpec::TestCase
|
11
|
+
destination File.expand_path('../../../tmp', __FILE__)
|
12
|
+
tests MigrationGenerator
|
13
|
+
arguments %w(article)
|
14
|
+
|
15
|
+
before(:all) do
|
16
|
+
prepare_destination
|
17
|
+
mkdir File.join(self.test_case.destination_root, 'config')
|
18
|
+
run_generator
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'generates Resort migration' do
|
22
|
+
destination_root.should have_structure {
|
23
|
+
|
24
|
+
directory "db" do
|
25
|
+
directory "migrate" do
|
26
|
+
migration "add_resort_fields_to_articles" do
|
27
|
+
contains "class AddResortFieldsToArticles"
|
28
|
+
contains ":articles, :next_id"
|
29
|
+
contains ":articles, :first"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/resort_spec.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class Article < ActiveRecord::Base
|
4
|
-
resort!
|
5
|
-
end
|
6
|
-
|
7
3
|
module Resort
|
8
4
|
describe Sortable do
|
9
5
|
|
@@ -26,15 +22,8 @@ module Resort
|
|
26
22
|
end
|
27
23
|
|
28
24
|
describe 'ClassMethods' do
|
29
|
-
describe "#first_in_order" do
|
30
|
-
it 'returns the first element of the list' do
|
31
|
-
first = double :article
|
32
|
-
Article.should_receive(:where).with(:first => true).and_return [first]
|
33
25
|
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
37
|
-
describe "#ordered" do
|
26
|
+
describe "ordering" do
|
38
27
|
before do
|
39
28
|
Article.destroy_all
|
40
29
|
|
@@ -42,20 +31,85 @@ module Resort
|
|
42
31
|
Article.create(:name => i.to_s)
|
43
32
|
end
|
44
33
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
34
|
+
Article.find_by_name('0').append_to(Article.find_by_name('3'))
|
35
|
+
Article.find_by_name('1').append_to(Article.find_by_name('3'))
|
36
|
+
Article.find_by_name('2').append_to(Article.find_by_name('3'))
|
37
|
+
|
38
|
+
@article1 = Article.find_by_name('3')
|
39
|
+
@article2 = Article.find_by_name('2')
|
40
|
+
@article3 = Article.find_by_name('1')
|
41
|
+
@article4 = Article.find_by_name('0')
|
49
42
|
end
|
50
|
-
|
51
|
-
|
43
|
+
|
44
|
+
describe "#first_in_order" do
|
45
|
+
it 'returns the first element of the list' do
|
46
|
+
Article.first_in_order.should == @article1
|
47
|
+
end
|
52
48
|
end
|
49
|
+
|
50
|
+
describe "#last_in_order" do
|
51
|
+
it 'returns the last element of the list' do
|
52
|
+
Article.last_in_order.should == @article4
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#ordered" do
|
57
|
+
it 'returns all elements ordered' do
|
58
|
+
Article.ordered.should == [@article1, @article2, @article3, @article4]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
53
62
|
after do
|
54
63
|
Article.destroy_all
|
55
64
|
end
|
56
65
|
end
|
57
66
|
end
|
58
67
|
|
68
|
+
describe "siblings" do
|
69
|
+
before do
|
70
|
+
one_list = List.create(:name => 'My list')
|
71
|
+
another_list = List.create(:name => 'My other list')
|
72
|
+
|
73
|
+
4.times do |i|
|
74
|
+
one_list.items << ListItem.new(:name => "My list item #{i}")
|
75
|
+
another_list.items << ListItem.new(:name => "My other list item #{i}")
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#first_in_order" do
|
81
|
+
it 'returns the first element of the list' do
|
82
|
+
List.find_by_name('My list').items.first_in_order.name.should == "My list item 0"
|
83
|
+
List.find_by_name('My other list').items.first_in_order.name.should == "My other list item 0"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#last_in_order" do
|
88
|
+
it 'returns the last element of the list' do
|
89
|
+
List.find_by_name('My list').items.last_in_order.name.should == "My list item 3"
|
90
|
+
List.find_by_name('My other list').items.last_in_order.name.should == "My other list item 3"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#ordered" do
|
95
|
+
it 'returns all elements ordered' do
|
96
|
+
List.find_by_name('My list').items.ordered.map(&:name).should == ['My list item 0', 'My list item 1', 'My list item 2', 'My list item 3']
|
97
|
+
List.find_by_name('My other list').items.ordered.map(&:name).should == ['My other list item 0', 'My other list item 1', 'My other list item 2', 'My other list item 3']
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'raises when ordering without scope' do
|
101
|
+
expect {
|
102
|
+
ListItem.ordered
|
103
|
+
}.to raise_error
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
after do
|
108
|
+
List.destroy_all
|
109
|
+
ListItem.destroy_all
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
59
113
|
describe "after create" do
|
60
114
|
context 'when there are no siblings' do
|
61
115
|
it 'prepends the element' do
|
@@ -72,14 +126,54 @@ module Resort
|
|
72
126
|
Article.create(:name => 'last!')
|
73
127
|
|
74
128
|
article = Article.find_by_name('last!')
|
129
|
+
first = Article.find_by_name('1')
|
75
130
|
|
76
131
|
article.should be_last
|
132
|
+
article.next_id.should be_nil
|
77
133
|
article.previous.name.should == '1'
|
134
|
+
|
135
|
+
first.next_id.should eq(article.id)
|
78
136
|
end
|
79
137
|
end
|
80
138
|
after do
|
81
139
|
Article.destroy_all
|
82
140
|
end
|
141
|
+
|
142
|
+
context "with custom siblings" do
|
143
|
+
|
144
|
+
context 'when there are no siblings' do
|
145
|
+
it 'prepends the element' do
|
146
|
+
one_list = List.create(:name => 'My list')
|
147
|
+
another_list = List.create(:name => 'My other list')
|
148
|
+
item = ListItem.create(:name => "My list item", :list => one_list)
|
149
|
+
|
150
|
+
item.should be_first
|
151
|
+
item.next.should be_nil
|
152
|
+
item.previous.should be_nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
context 'otherwise' do
|
156
|
+
it 'appends the element' do
|
157
|
+
one_list = List.create(:name => 'My list')
|
158
|
+
another_list = List.create(:name => 'My other list')
|
159
|
+
ListItem.create(:name => "1", :list => one_list)
|
160
|
+
ListItem.create(:name => "last!", :list => one_list)
|
161
|
+
|
162
|
+
first = ListItem.find_by_name('1')
|
163
|
+
last = ListItem.find_by_name('last!')
|
164
|
+
|
165
|
+
last.should be_last
|
166
|
+
last.next_id.should be_nil
|
167
|
+
last.previous.name.should == '1'
|
168
|
+
|
169
|
+
first.next_id.should eq(last.id)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
after do
|
173
|
+
List.destroy_all
|
174
|
+
ListItem.destroy_all
|
175
|
+
end
|
176
|
+
end
|
83
177
|
end
|
84
178
|
|
85
179
|
describe "after destroy" do
|
@@ -190,35 +284,43 @@ module Resort
|
|
190
284
|
it "appends the element after another element" do
|
191
285
|
@article1.append_to(@article2)
|
192
286
|
|
193
|
-
article2 = Article.find_by_name('2')
|
194
|
-
article2.next.name.should == '1'
|
195
|
-
|
196
287
|
article1 = Article.find_by_name('1')
|
197
288
|
article1.next.name.should == '3'
|
198
289
|
article1.previous.name.should == '2'
|
199
290
|
@article3.previous.name.should == '1'
|
291
|
+
end
|
292
|
+
|
293
|
+
it "sets the other element as first" do
|
294
|
+
@article1.append_to(@article2)
|
200
295
|
|
296
|
+
article2 = Article.find_by_name('2')
|
297
|
+
article2.next.name.should == '1'
|
201
298
|
article2.should be_first
|
202
299
|
end
|
203
300
|
end
|
301
|
+
|
204
302
|
context 'appending 1 after 3' do
|
205
303
|
it "appends the element after another element" do
|
206
304
|
@article1.append_to(@article3)
|
207
305
|
|
208
|
-
article2 = Article.find_by_name('2')
|
209
|
-
article2.should be_first
|
210
|
-
article2.previous.should be_nil
|
211
|
-
|
212
306
|
article1 = Article.find_by_name('1')
|
213
307
|
article1.should_not be_first
|
214
308
|
article1.previous.name.should == '3'
|
215
309
|
article1.next.name.should == '4'
|
216
310
|
|
217
311
|
@article3.next.name.should == '1'
|
218
|
-
|
219
312
|
@article4.previous.name.should == '1'
|
220
313
|
end
|
314
|
+
|
315
|
+
it 'resets the first element' do
|
316
|
+
@article1.append_to(@article3)
|
317
|
+
|
318
|
+
article2 = Article.find_by_name('2')
|
319
|
+
article2.should be_first
|
320
|
+
article2.previous.should be_nil
|
321
|
+
end
|
221
322
|
end
|
323
|
+
|
222
324
|
context 'appending 2 after 3' do
|
223
325
|
it "appends the element after another element" do
|
224
326
|
@article2.append_to(@article3)
|
@@ -290,8 +392,11 @@ module Resort
|
|
290
392
|
it 'does nothing' do
|
291
393
|
@article2.append_to(@article1)
|
292
394
|
|
293
|
-
|
294
|
-
|
395
|
+
article1 = Article.find_by_name('1')
|
396
|
+
article2 = Article.find_by_name('2')
|
397
|
+
|
398
|
+
article1.next.name.should == '2'
|
399
|
+
article2.previous.name.should == '1'
|
295
400
|
end
|
296
401
|
end
|
297
402
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require 'resort'
|
3
|
+
require 'logger'
|
3
4
|
|
4
5
|
ActiveRecord::Base.establish_connection(
|
5
6
|
:adapter => 'sqlite3',
|
@@ -16,4 +17,38 @@ ActiveRecord::Schema.define do
|
|
16
17
|
|
17
18
|
t.timestamps
|
18
19
|
end
|
20
|
+
|
21
|
+
create_table :lists do |t|
|
22
|
+
t.string :name
|
23
|
+
t.timestamps
|
24
|
+
end
|
25
|
+
|
26
|
+
create_table :list_items do |t|
|
27
|
+
t.string :name
|
28
|
+
t.boolean :first
|
29
|
+
t.references :next
|
30
|
+
t.references :list
|
31
|
+
t.timestamps
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT)
|
36
|
+
|
37
|
+
class Article < ActiveRecord::Base
|
38
|
+
resort!
|
39
|
+
end
|
40
|
+
|
41
|
+
class List < ActiveRecord::Base
|
42
|
+
has_many :items, :class_name => 'ListItem'
|
43
|
+
end
|
44
|
+
|
45
|
+
class ListItem < ActiveRecord::Base
|
46
|
+
belongs_to :list
|
47
|
+
resort!
|
48
|
+
|
49
|
+
default_scope :order => 'created_at desc'
|
50
|
+
|
51
|
+
def siblings
|
52
|
+
self.list.items
|
53
|
+
end
|
19
54
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: resort
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Oriol Gual
|
@@ -12,7 +12,7 @@ autorequire:
|
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
14
|
|
15
|
-
date: 2011-03-
|
15
|
+
date: 2011-03-30 00:00:00 +02:00
|
16
16
|
default_executable:
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
@@ -70,6 +70,17 @@ dependencies:
|
|
70
70
|
version: "0"
|
71
71
|
type: :development
|
72
72
|
version_requirements: *id005
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: generator_spec
|
75
|
+
prerelease: false
|
76
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ~>
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.8.1
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id006
|
73
84
|
description: Positionless model sorting for Rails 3.
|
74
85
|
email:
|
75
86
|
- info@codegram.com
|
@@ -87,9 +98,12 @@ files:
|
|
87
98
|
- LICENSE
|
88
99
|
- Rakefile
|
89
100
|
- Readme.md
|
101
|
+
- lib/generators/active_record/resort_generator.rb
|
102
|
+
- lib/generators/active_record/templates/migration.rb
|
90
103
|
- lib/resort.rb
|
91
104
|
- lib/resort/version.rb
|
92
105
|
- resort.gemspec
|
106
|
+
- spec/generators/migration_spec.rb
|
93
107
|
- spec/resort_spec.rb
|
94
108
|
- spec/spec_helper.rb
|
95
109
|
has_rdoc: true
|
@@ -121,5 +135,6 @@ signing_key:
|
|
121
135
|
specification_version: 3
|
122
136
|
summary: Positionless model sorting for Rails 3.
|
123
137
|
test_files:
|
138
|
+
- spec/generators/migration_spec.rb
|
124
139
|
- spec/resort_spec.rb
|
125
140
|
- spec/spec_helper.rb
|