sortability 0.1.0 → 1.0.0
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.
- checksums.yaml +5 -5
- data/README.md +2 -2
- data/lib/sortability/active_record/base.rb +10 -7
- data/lib/sortability/version.rb +1 -1
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/models/container.rb +5 -0
- data/spec/dummy/app/models/item.rb +3 -0
- data/spec/dummy/config/application.rb +3 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20190523235417_create_containers.rb +9 -0
- data/spec/dummy/db/migrate/20190523235430_create_items.rb +12 -0
- data/spec/dummy/db/schema.rb +29 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +140 -0
- data/spec/dummy/log/test.log +4220 -0
- data/spec/lib/sortability/active_record/base_spec.rb +202 -1
- data/spec/lib/sortability/active_record/connection_adapters/table_definition_spec.rb +21 -1
- data/spec/lib/sortability/active_record/migration_spec.rb +44 -1
- metadata +41 -42
@@ -3,7 +3,208 @@ require "rails_helper"
|
|
3
3
|
module Sortability
|
4
4
|
module ActiveRecord
|
5
5
|
RSpec.describe Base do
|
6
|
-
|
6
|
+
context 'unscoped' do
|
7
|
+
let(:container_1) { Container.new }
|
8
|
+
let(:container_2) { Container.new }
|
9
|
+
|
10
|
+
it 'can return the sort peers for a record' do
|
11
|
+
expect(container_1.sort_position_peers).to be_empty
|
12
|
+
expect(container_2.sort_position_peers).to be_empty
|
13
|
+
|
14
|
+
container_1.save!
|
15
|
+
expect(container_1.sort_position_peers).to eq [ container_1 ]
|
16
|
+
expect(container_2.sort_position_peers).to eq [ container_1 ]
|
17
|
+
|
18
|
+
container_2.save!
|
19
|
+
expect(container_1.sort_position_peers).to eq [ container_1, container_2 ]
|
20
|
+
expect(container_2.sort_position_peers).to eq [ container_1, container_2 ]
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'automatically assigns sequential sort_positions to created records' do
|
24
|
+
expect(container_1.sort_position).to be_nil
|
25
|
+
expect(container_2.sort_position).to be_nil
|
26
|
+
|
27
|
+
container_1.save!
|
28
|
+
expect(container_1.sort_position).to eq 1
|
29
|
+
expect(container_2.sort_position).to be_nil
|
30
|
+
|
31
|
+
container_2.save!
|
32
|
+
expect(container_1.sort_position).to eq 1
|
33
|
+
expect(container_2.sort_position).to eq 2
|
34
|
+
end
|
35
|
+
|
36
|
+
it "automatically increases other records' sort_positions to avoid conflicts" do
|
37
|
+
container_1.save!
|
38
|
+
container_2.save!
|
39
|
+
container_3 = Container.create! sort_position: 1
|
40
|
+
|
41
|
+
expect(container_1.reload.sort_position).to eq 2
|
42
|
+
expect(container_2.reload.sort_position).to eq 3
|
43
|
+
expect(container_3.sort_position).to eq 1
|
44
|
+
expect(container_3.reload.sort_position).to eq 1
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'can return the next record by sort_position' do
|
48
|
+
container_1.save!
|
49
|
+
container_2.save!
|
50
|
+
|
51
|
+
expect(container_1.next_by_sort_position).to eq container_2
|
52
|
+
expect(container_2.next_by_sort_position).to be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can return the previous record by sort_position' do
|
56
|
+
container_1.save!
|
57
|
+
container_2.save!
|
58
|
+
|
59
|
+
expect(container_1.previous_by_sort_position).to be_nil
|
60
|
+
expect(container_2.previous_by_sort_position).to eq container_1
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'can compact the sort peers to make their numbers sequential' do
|
64
|
+
container_1.sort_position = 21
|
65
|
+
container_1.save!
|
66
|
+
container_2.sort_position = 42
|
67
|
+
container_2.save!
|
68
|
+
|
69
|
+
expect(container_1.reload.sort_position).to eq 21
|
70
|
+
expect(container_2.reload.sort_position).to eq 42
|
71
|
+
|
72
|
+
container_1.compact_sort_position_peers!
|
73
|
+
|
74
|
+
expect(container_1.sort_position).to eq 1
|
75
|
+
expect(container_1.reload.sort_position).to eq 1
|
76
|
+
expect(container_2.reload.sort_position).to eq 2
|
77
|
+
|
78
|
+
container_2.compact_sort_position_peers!
|
79
|
+
|
80
|
+
expect(container_1.reload.sort_position).to eq 1
|
81
|
+
expect(container_2.sort_position).to eq 2
|
82
|
+
expect(container_2.reload.sort_position).to eq 2
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'scoped' do
|
87
|
+
let(:container_1) { Container.create }
|
88
|
+
let(:container_2) { Container.create }
|
89
|
+
let(:item_1) { Item.new(container: container_1) }
|
90
|
+
let(:item_2) { Item.new(container: container_1) }
|
91
|
+
let(:item_3) { Item.new(container: container_2) }
|
92
|
+
|
93
|
+
it 'can return the sort peers for a record' do
|
94
|
+
expect(item_1.sort_position_peers).to be_empty
|
95
|
+
expect(item_2.sort_position_peers).to be_empty
|
96
|
+
expect(item_3.sort_position_peers).to be_empty
|
97
|
+
|
98
|
+
item_1.save!
|
99
|
+
expect(item_1.sort_position_peers).to eq [ item_1 ]
|
100
|
+
expect(item_2.sort_position_peers).to eq [ item_1 ]
|
101
|
+
expect(item_3.sort_position_peers).to be_empty
|
102
|
+
|
103
|
+
container_1.reload
|
104
|
+
container_2.reload
|
105
|
+
|
106
|
+
item_2.save!
|
107
|
+
expect(item_1.sort_position_peers).to eq [ item_1, item_2 ]
|
108
|
+
expect(item_2.sort_position_peers).to eq [ item_1, item_2 ]
|
109
|
+
expect(item_3.sort_position_peers).to be_empty
|
110
|
+
|
111
|
+
container_1.reload
|
112
|
+
container_2.reload
|
113
|
+
|
114
|
+
item_3.save!
|
115
|
+
expect(item_1.sort_position_peers).to eq [ item_1, item_2 ]
|
116
|
+
expect(item_2.sort_position_peers).to eq [ item_1, item_2 ]
|
117
|
+
expect(item_3.sort_position_peers).to eq [ item_3 ]
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'automatically assigns sequential sort_positions to created records in each scope' do
|
121
|
+
expect(item_1.sort_position).to be_nil
|
122
|
+
expect(item_2.sort_position).to be_nil
|
123
|
+
expect(item_3.sort_position).to be_nil
|
124
|
+
|
125
|
+
item_1.save!
|
126
|
+
expect(item_1.sort_position).to eq 1
|
127
|
+
expect(item_2.sort_position).to be_nil
|
128
|
+
expect(item_3.sort_position).to be_nil
|
129
|
+
|
130
|
+
item_2.save!
|
131
|
+
expect(item_1.sort_position).to eq 1
|
132
|
+
expect(item_2.sort_position).to eq 2
|
133
|
+
expect(item_3.sort_position).to be_nil
|
134
|
+
|
135
|
+
item_3.save!
|
136
|
+
expect(item_1.sort_position).to eq 1
|
137
|
+
expect(item_2.sort_position).to eq 2
|
138
|
+
expect(item_3.sort_position).to eq 1
|
139
|
+
end
|
140
|
+
|
141
|
+
it "automatically increases other records' sort_positions to avoid conflicts" do
|
142
|
+
item_1.save!
|
143
|
+
item_2.save!
|
144
|
+
item_3.save!
|
145
|
+
item_4 = Item.create! container: container_1, sort_position: 1
|
146
|
+
|
147
|
+
expect(item_1.reload.sort_position).to eq 2
|
148
|
+
expect(item_2.reload.sort_position).to eq 3
|
149
|
+
expect(item_3.reload.sort_position).to eq 1
|
150
|
+
expect(item_4.sort_position).to eq 1
|
151
|
+
expect(item_4.reload.sort_position).to eq 1
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'can return the next record by sort_position' do
|
155
|
+
item_1.save!
|
156
|
+
item_2.save!
|
157
|
+
item_3.save!
|
158
|
+
|
159
|
+
expect(item_1.next_by_sort_position).to eq item_2
|
160
|
+
expect(item_2.next_by_sort_position).to be_nil
|
161
|
+
expect(item_3.next_by_sort_position).to be_nil
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'can return the previous record by sort_position' do
|
165
|
+
item_1.save!
|
166
|
+
item_2.save!
|
167
|
+
item_3.save!
|
168
|
+
|
169
|
+
expect(item_1.previous_by_sort_position).to be_nil
|
170
|
+
expect(item_2.previous_by_sort_position).to eq item_1
|
171
|
+
expect(item_3.previous_by_sort_position).to be_nil
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'can compact the sort peers to make their numbers sequential' do
|
175
|
+
item_1.sort_position = 21
|
176
|
+
item_1.save!
|
177
|
+
item_2.sort_position = 42
|
178
|
+
item_2.save!
|
179
|
+
item_3.sort_position = 84
|
180
|
+
item_3.save!
|
181
|
+
|
182
|
+
expect(item_1.reload.sort_position).to eq 21
|
183
|
+
expect(item_2.reload.sort_position).to eq 42
|
184
|
+
expect(item_3.reload.sort_position).to eq 84
|
185
|
+
|
186
|
+
item_1.compact_sort_position_peers!
|
187
|
+
|
188
|
+
expect(item_1.sort_position).to eq 1
|
189
|
+
expect(item_1.reload.sort_position).to eq 1
|
190
|
+
expect(item_2.reload.sort_position).to eq 2
|
191
|
+
expect(item_3.reload.sort_position).to eq 84
|
192
|
+
|
193
|
+
item_2.compact_sort_position_peers!
|
194
|
+
|
195
|
+
expect(item_1.reload.sort_position).to eq 1
|
196
|
+
expect(item_2.sort_position).to eq 2
|
197
|
+
expect(item_2.reload.sort_position).to eq 2
|
198
|
+
expect(item_3.reload.sort_position).to eq 84
|
199
|
+
|
200
|
+
item_3.compact_sort_position_peers!
|
201
|
+
|
202
|
+
expect(item_1.reload.sort_position).to eq 1
|
203
|
+
expect(item_2.reload.sort_position).to eq 2
|
204
|
+
expect(item_3.sort_position).to eq 1
|
205
|
+
expect(item_3.reload.sort_position).to eq 1
|
206
|
+
end
|
207
|
+
end
|
7
208
|
end
|
8
209
|
end
|
9
210
|
end
|
@@ -4,7 +4,27 @@ module Sortability
|
|
4
4
|
module ActiveRecord
|
5
5
|
module ConnectionAdapters
|
6
6
|
RSpec.describe TableDefinition do
|
7
|
-
|
7
|
+
let(:table_definition) { ::ActiveRecord::ConnectionAdapters::TableDefinition.new :test }
|
8
|
+
|
9
|
+
context 'without :on and :null' do
|
10
|
+
let(:options) { { something: :else } }
|
11
|
+
|
12
|
+
it '#sortable calls the #integer method, adding defaults' do
|
13
|
+
expect(table_definition).to(
|
14
|
+
receive(:integer).with(:sort_position, options.merge(null: false))
|
15
|
+
)
|
16
|
+
table_definition.sortable options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with :on and :null' do
|
21
|
+
let(:options) { { something: :else, on: :pos, null: true } }
|
22
|
+
|
23
|
+
it '#sortable calls the #integer method with the given options' do
|
24
|
+
expect(table_definition).to receive(:integer).with(:pos, options.except(:on))
|
25
|
+
table_definition.sortable options
|
26
|
+
end
|
27
|
+
end
|
8
28
|
end
|
9
29
|
end
|
10
30
|
end
|
@@ -3,7 +3,50 @@ require "rails_helper"
|
|
3
3
|
module Sortability
|
4
4
|
module ActiveRecord
|
5
5
|
RSpec.describe Migration do
|
6
|
-
|
6
|
+
let(:migration) { ::ActiveRecord::Migration.new }
|
7
|
+
let(:table) { :test }
|
8
|
+
|
9
|
+
context 'without some options' do
|
10
|
+
let(:options) { { something: :else } }
|
11
|
+
|
12
|
+
it '#add_sortable_column can add a sortable column, adding defaults' do
|
13
|
+
expect(migration).to receive(:method_missing).with(
|
14
|
+
:add_column, table, :sort_position, :integer, options.merge(null: false)
|
15
|
+
)
|
16
|
+
|
17
|
+
migration.add_sortable_column table, options
|
18
|
+
end
|
19
|
+
|
20
|
+
it '#add_sortable_index can add a sortable index, adding defaults' do
|
21
|
+
expect(migration).to receive(:method_missing).with(
|
22
|
+
:add_index, table, [ :sort_position ], options.merge(unique: true)
|
23
|
+
)
|
24
|
+
|
25
|
+
migration.add_sortable_index table, options
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with all options' do
|
30
|
+
let(:options) do
|
31
|
+
{ something: :else, on: :pos, null: true, unique: false, scope: :container_id }
|
32
|
+
end
|
33
|
+
|
34
|
+
it '#add_sortable_column can add a sortable column with the given options' do
|
35
|
+
expect(migration).to receive(:method_missing).with(
|
36
|
+
:add_column, table, :pos, :integer, options.except(:on)
|
37
|
+
)
|
38
|
+
|
39
|
+
migration.add_sortable_column table, options
|
40
|
+
end
|
41
|
+
|
42
|
+
it '#add_sortable_index can add a sortable index with the given options' do
|
43
|
+
expect(migration).to receive(:method_missing).with(
|
44
|
+
:add_index, table, [ :container_id, :pos ], options.except(:on, :scope)
|
45
|
+
)
|
46
|
+
|
47
|
+
migration.add_sortable_index table, options
|
48
|
+
end
|
49
|
+
end
|
7
50
|
end
|
8
51
|
end
|
9
52
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sortability
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dante Soares
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-05-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -25,20 +25,6 @@ dependencies:
|
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
|
-
- !ruby/object:Gem::Dependency
|
29
|
-
name: squeel
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
31
|
-
requirements:
|
32
|
-
- - ">="
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '0'
|
35
|
-
type: :runtime
|
36
|
-
prerelease: false
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
38
|
-
requirements:
|
39
|
-
- - ">="
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
version: '0'
|
42
28
|
- !ruby/object:Gem::Dependency
|
43
29
|
name: sqlite3
|
44
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -89,6 +75,9 @@ files:
|
|
89
75
|
- spec/dummy/app/assets/stylesheets/application.css
|
90
76
|
- spec/dummy/app/controllers/application_controller.rb
|
91
77
|
- spec/dummy/app/helpers/application_helper.rb
|
78
|
+
- spec/dummy/app/models/application_record.rb
|
79
|
+
- spec/dummy/app/models/container.rb
|
80
|
+
- spec/dummy/app/models/item.rb
|
92
81
|
- spec/dummy/app/views/layouts/application.html.erb
|
93
82
|
- spec/dummy/bin/bundle
|
94
83
|
- spec/dummy/bin/rails
|
@@ -112,6 +101,10 @@ files:
|
|
112
101
|
- spec/dummy/config/locales/en.yml
|
113
102
|
- spec/dummy/config/routes.rb
|
114
103
|
- spec/dummy/config/secrets.yml
|
104
|
+
- spec/dummy/db/development.sqlite3
|
105
|
+
- spec/dummy/db/migrate/20190523235417_create_containers.rb
|
106
|
+
- spec/dummy/db/migrate/20190523235430_create_items.rb
|
107
|
+
- spec/dummy/db/schema.rb
|
115
108
|
- spec/dummy/db/test.sqlite3
|
116
109
|
- spec/dummy/log/development.log
|
117
110
|
- spec/dummy/log/test.log
|
@@ -143,50 +136,56 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
136
|
- !ruby/object:Gem::Version
|
144
137
|
version: '0'
|
145
138
|
requirements: []
|
146
|
-
|
147
|
-
rubygems_version: 2.4.5.1
|
139
|
+
rubygems_version: 3.0.1
|
148
140
|
signing_key:
|
149
141
|
specification_version: 4
|
150
142
|
summary: Rails gem that provides easy to use ordered records
|
151
143
|
test_files:
|
144
|
+
- spec/rails_helper.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
- spec/dummy/app/models/application_record.rb
|
147
|
+
- spec/dummy/app/models/item.rb
|
148
|
+
- spec/dummy/app/models/container.rb
|
152
149
|
- spec/dummy/app/assets/javascripts/application.js
|
153
150
|
- spec/dummy/app/assets/stylesheets/application.css
|
151
|
+
- spec/dummy/app/views/layouts/application.html.erb
|
154
152
|
- spec/dummy/app/controllers/application_controller.rb
|
155
153
|
- spec/dummy/app/helpers/application_helper.rb
|
156
|
-
- spec/dummy/
|
157
|
-
- spec/dummy/
|
154
|
+
- spec/dummy/db/migrate/20190523235430_create_items.rb
|
155
|
+
- spec/dummy/db/migrate/20190523235417_create_containers.rb
|
156
|
+
- spec/dummy/db/development.sqlite3
|
157
|
+
- spec/dummy/db/test.sqlite3
|
158
|
+
- spec/dummy/db/schema.rb
|
159
|
+
- spec/dummy/log/test.log
|
160
|
+
- spec/dummy/log/development.log
|
161
|
+
- spec/dummy/README.md
|
162
|
+
- spec/dummy/public/favicon.ico
|
163
|
+
- spec/dummy/public/422.html
|
164
|
+
- spec/dummy/public/404.html
|
165
|
+
- spec/dummy/public/500.html
|
166
|
+
- spec/dummy/config.ru
|
158
167
|
- spec/dummy/bin/rails
|
159
168
|
- spec/dummy/bin/rake
|
169
|
+
- spec/dummy/bin/bundle
|
160
170
|
- spec/dummy/config/application.rb
|
161
|
-
- spec/dummy/config/
|
162
|
-
- spec/dummy/config/database.yml
|
163
|
-
- spec/dummy/config/environment.rb
|
164
|
-
- spec/dummy/config/environments/development.rb
|
165
|
-
- spec/dummy/config/environments/production.rb
|
166
|
-
- spec/dummy/config/environments/test.rb
|
171
|
+
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
167
172
|
- spec/dummy/config/initializers/assets.rb
|
168
|
-
- spec/dummy/config/initializers/backtrace_silencers.rb
|
169
173
|
- spec/dummy/config/initializers/cookies_serializer.rb
|
170
|
-
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
171
174
|
- spec/dummy/config/initializers/inflections.rb
|
172
|
-
- spec/dummy/config/initializers/
|
173
|
-
- spec/dummy/config/initializers/session_store.rb
|
175
|
+
- spec/dummy/config/initializers/backtrace_silencers.rb
|
174
176
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
177
|
+
- spec/dummy/config/initializers/session_store.rb
|
178
|
+
- spec/dummy/config/initializers/mime_types.rb
|
175
179
|
- spec/dummy/config/locales/en.yml
|
176
180
|
- spec/dummy/config/routes.rb
|
181
|
+
- spec/dummy/config/database.yml
|
182
|
+
- spec/dummy/config/environment.rb
|
183
|
+
- spec/dummy/config/boot.rb
|
184
|
+
- spec/dummy/config/environments/production.rb
|
185
|
+
- spec/dummy/config/environments/test.rb
|
186
|
+
- spec/dummy/config/environments/development.rb
|
177
187
|
- spec/dummy/config/secrets.yml
|
178
|
-
- spec/dummy/config.ru
|
179
|
-
- spec/dummy/db/test.sqlite3
|
180
|
-
- spec/dummy/log/development.log
|
181
|
-
- spec/dummy/log/test.log
|
182
|
-
- spec/dummy/public/404.html
|
183
|
-
- spec/dummy/public/422.html
|
184
|
-
- spec/dummy/public/500.html
|
185
|
-
- spec/dummy/public/favicon.ico
|
186
188
|
- spec/dummy/Rakefile
|
187
|
-
- spec/dummy/README.md
|
188
|
-
- spec/lib/sortability/active_record/base_spec.rb
|
189
189
|
- spec/lib/sortability/active_record/connection_adapters/table_definition_spec.rb
|
190
190
|
- spec/lib/sortability/active_record/migration_spec.rb
|
191
|
-
- spec/
|
192
|
-
- spec/spec_helper.rb
|
191
|
+
- spec/lib/sortability/active_record/base_spec.rb
|