ranked-model 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ranked-model/ranker.rb +32 -8
- data/lib/ranked-model/version.rb +1 -1
- data/spec/duck-model/duck_spec.rb +81 -0
- data/spec/sti-model/element_spec.rb +41 -0
- data/spec/support/active_record.rb +6 -0
- metadata +11 -13
data/lib/ranked-model/ranker.rb
CHANGED
@@ -34,8 +34,17 @@ module RankedModel
|
|
34
34
|
raise RankedModel::InvalidScope, %Q{No scope called "#{ranker.scope}" found in model}
|
35
35
|
end
|
36
36
|
|
37
|
-
if ranker.with_same
|
38
|
-
|
37
|
+
if ranker.with_same
|
38
|
+
if (case ranker.with_same
|
39
|
+
when Symbol
|
40
|
+
!instance.respond_to?(ranker.with_same)
|
41
|
+
when Array
|
42
|
+
ranker.with_same.detect {|attr| !instance.respond_to?(attr) }
|
43
|
+
else
|
44
|
+
false
|
45
|
+
end)
|
46
|
+
raise RankedModel::InvalidField, %Q{No field called "#{ranker.with_same}" found in model}
|
47
|
+
end
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
@@ -128,17 +137,17 @@ module RankedModel
|
|
128
137
|
end
|
129
138
|
|
130
139
|
def rearrange_ranks
|
131
|
-
if current_first.rank > RankedModel::MIN_RANK_VALUE && rank == RankedModel::MAX_RANK_VALUE
|
140
|
+
if current_first.rank && current_first.rank > RankedModel::MIN_RANK_VALUE && rank == RankedModel::MAX_RANK_VALUE
|
132
141
|
instance.class.
|
133
142
|
where( instance.class.arel_table[:id].not_eq(instance.id) ).
|
134
143
|
where( instance.class.arel_table[ranker.column].lteq(rank) ).
|
135
144
|
update_all( "#{ranker.column} = #{ranker.column} - 1" )
|
136
|
-
elsif current_last.rank < (RankedModel::MAX_RANK_VALUE - 1) && rank < current_last.rank
|
145
|
+
elsif current_last.rank && current_last.rank < (RankedModel::MAX_RANK_VALUE - 1) && rank < current_last.rank
|
137
146
|
instance.class.
|
138
147
|
where( instance.class.arel_table[:id].not_eq(instance.id) ).
|
139
148
|
where( instance.class.arel_table[ranker.column].gteq(rank) ).
|
140
149
|
update_all( "#{ranker.column} = #{ranker.column} + 1" )
|
141
|
-
elsif current_first.rank > RankedModel::MIN_RANK_VALUE && rank > current_first.rank
|
150
|
+
elsif current_first.rank && current_first.rank > RankedModel::MIN_RANK_VALUE && rank > current_first.rank
|
142
151
|
instance.class.
|
143
152
|
where( instance.class.arel_table[:id].not_eq(instance.id) ).
|
144
153
|
where( instance.class.arel_table[ranker.column].lt(rank) ).
|
@@ -177,9 +186,24 @@ module RankedModel
|
|
177
186
|
if ranker.scope
|
178
187
|
_finder = _finder.send ranker.scope
|
179
188
|
end
|
180
|
-
|
181
|
-
|
182
|
-
|
189
|
+
case ranker.with_same
|
190
|
+
when Symbol
|
191
|
+
_finder = _finder.where \
|
192
|
+
instance.class.arel_table[ranker.with_same].eq(instance.attributes["#{ranker.with_same}"])
|
193
|
+
when Array
|
194
|
+
_finder = _finder.where(
|
195
|
+
ranker.with_same[1..-1].inject(
|
196
|
+
instance.class.arel_table[ranker.with_same.first].eq(
|
197
|
+
instance.attributes["#{ranker.with_same.first}"]
|
198
|
+
)
|
199
|
+
) {|scoper, attr|
|
200
|
+
scoper.and(
|
201
|
+
instance.class.arel_table[attr].eq(
|
202
|
+
instance.attributes["#{attr}"]
|
203
|
+
)
|
204
|
+
)
|
205
|
+
}
|
206
|
+
)
|
183
207
|
end
|
184
208
|
if !new_record?
|
185
209
|
_finder = _finder.where \
|
data/lib/ranked-model/version.rb
CHANGED
@@ -14,6 +14,8 @@ describe Duck do
|
|
14
14
|
it { subject.respond_to?(:size_position=).should be_true }
|
15
15
|
it { subject.respond_to?(:age_position).should be_true }
|
16
16
|
it { subject.respond_to?(:age_position=).should be_true }
|
17
|
+
it { subject.respond_to?(:landing_order_position).should be_true }
|
18
|
+
it { subject.respond_to?(:landing_order_position=).should be_true }
|
17
19
|
|
18
20
|
end
|
19
21
|
|
@@ -288,3 +290,82 @@ describe Duck do
|
|
288
290
|
end
|
289
291
|
|
290
292
|
end
|
293
|
+
|
294
|
+
describe Duck do
|
295
|
+
|
296
|
+
before {
|
297
|
+
@ducks = {
|
298
|
+
:quacky => Duck.create(
|
299
|
+
:name => 'Quacky',
|
300
|
+
:lake_id => 0,
|
301
|
+
:flock_id => 0 ),
|
302
|
+
:feathers => Duck.create(
|
303
|
+
:name => 'Feathers',
|
304
|
+
:lake_id => 0,
|
305
|
+
:flock_id => 0 ),
|
306
|
+
:wingy => Duck.create(
|
307
|
+
:name => 'Wingy',
|
308
|
+
:lake_id => 0,
|
309
|
+
:flock_id => 0 ),
|
310
|
+
:webby => Duck.create(
|
311
|
+
:name => 'Webby',
|
312
|
+
:lake_id => 1,
|
313
|
+
:flock_id => 1 ),
|
314
|
+
:waddly => Duck.create(
|
315
|
+
:name => 'Waddly',
|
316
|
+
:lake_id => 1,
|
317
|
+
:flock_id => 0 ),
|
318
|
+
:beaky => Duck.create(
|
319
|
+
:name => 'Beaky',
|
320
|
+
:lake_id => 0,
|
321
|
+
:flock_id => 1 ),
|
322
|
+
}
|
323
|
+
@ducks.each { |name, duck|
|
324
|
+
duck.reload
|
325
|
+
duck.update_attribute :landing_order_position, 0
|
326
|
+
duck.save!
|
327
|
+
}
|
328
|
+
@ducks.each {|name, duck| duck.reload }
|
329
|
+
}
|
330
|
+
|
331
|
+
describe "sorting by landing_order" do
|
332
|
+
|
333
|
+
before {
|
334
|
+
@ducks[:quacky].update_attribute :landing_order_position, 0
|
335
|
+
@ducks[:wingy].update_attribute :landing_order_position, 1
|
336
|
+
}
|
337
|
+
|
338
|
+
subject { Duck.in_lake_and_flock(0,0).rank(:landing_order).all }
|
339
|
+
|
340
|
+
its(:size) { should == 3 }
|
341
|
+
|
342
|
+
its(:first) { should == @ducks[:quacky] }
|
343
|
+
|
344
|
+
its(:last) { should == @ducks[:feathers] }
|
345
|
+
|
346
|
+
end
|
347
|
+
|
348
|
+
describe "sorting by landing_order doesn't touch other items" do
|
349
|
+
|
350
|
+
before {
|
351
|
+
@untouchable_ranks = lambda {
|
352
|
+
[:webby, :waddly, :beaky].inject([]) do |ranks, untouchable_duck|
|
353
|
+
ranks << @ducks[untouchable_duck].landing_order
|
354
|
+
end
|
355
|
+
}
|
356
|
+
|
357
|
+
@previous_ranks = @untouchable_ranks.call
|
358
|
+
|
359
|
+
@ducks[:quacky].update_attribute :landing_order_position, 0
|
360
|
+
@ducks[:wingy].update_attribute :landing_order_position, 1
|
361
|
+
@ducks[:feathers].update_attribute :landing_order_position, 0
|
362
|
+
@ducks[:wingy].update_attribute :landing_order_position, 1
|
363
|
+
}
|
364
|
+
|
365
|
+
subject { @untouchable_ranks.call }
|
366
|
+
|
367
|
+
it { should == @previous_ranks }
|
368
|
+
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
@@ -78,4 +78,45 @@ describe Element do
|
|
78
78
|
|
79
79
|
end
|
80
80
|
|
81
|
+
describe "setting positions on STI classes" do
|
82
|
+
|
83
|
+
before {
|
84
|
+
@elements[:helium].update_attribute :combination_order_position, :first
|
85
|
+
@elements[:xenon].update_attribute :combination_order_position, :first
|
86
|
+
@elements[:argon].update_attribute :combination_order_position, :first
|
87
|
+
|
88
|
+
@elements[:chromium].update_attribute :combination_order_position, 1
|
89
|
+
@elements[:manganese].update_attribute :combination_order_position, 1
|
90
|
+
@elements[:manganese].update_attribute :combination_order_position, 0
|
91
|
+
@elements[:chromium].update_attribute :combination_order_position, 0
|
92
|
+
@elements[:manganese].update_attribute :combination_order_position, 0
|
93
|
+
@elements[:chromium].update_attribute :combination_order_position, 0
|
94
|
+
}
|
95
|
+
|
96
|
+
describe "NobleGas" do
|
97
|
+
|
98
|
+
subject { NobleGas.rank(:combination_order) }
|
99
|
+
|
100
|
+
its(:size) { should == 3 }
|
101
|
+
|
102
|
+
its(:first) { should == @elements[:argon] }
|
103
|
+
|
104
|
+
its(:last) { should == @elements[:helium] }
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "TransitionMetal" do
|
109
|
+
|
110
|
+
subject { TransitionMetal.rank(:combination_order) }
|
111
|
+
|
112
|
+
its(:size) { should == 2 }
|
113
|
+
|
114
|
+
its(:first) { should == @elements[:chromium] }
|
115
|
+
|
116
|
+
its(:last) { should == @elements[:manganese] }
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
81
122
|
end
|
@@ -16,6 +16,9 @@ ActiveRecord::Schema.define :version => 0 do
|
|
16
16
|
t.integer :row
|
17
17
|
t.integer :size
|
18
18
|
t.integer :age
|
19
|
+
t.integer :lake_id
|
20
|
+
t.integer :flock_id
|
21
|
+
t.integer :landing_order
|
19
22
|
t.string :pond
|
20
23
|
end
|
21
24
|
|
@@ -44,6 +47,9 @@ class Duck < ActiveRecord::Base
|
|
44
47
|
ranks :row
|
45
48
|
ranks :size, :scope => :in_shin_pond
|
46
49
|
ranks :age, :with_same => :pond
|
50
|
+
|
51
|
+
ranks :landing_order, :with_same => [:lake_id, :flock_id]
|
52
|
+
scope :in_lake_and_flock, lambda {|lake, flock| where(:lake_id => lake, :flock_id => flock) }
|
47
53
|
|
48
54
|
scope :in_shin_pond, where(:pond => 'Shin')
|
49
55
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ranked-model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matthew Beale
|
@@ -15,11 +15,9 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-08-22 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
|
-
name: activerecord
|
23
21
|
prerelease: false
|
24
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
23
|
none: false
|
@@ -34,8 +32,8 @@ dependencies:
|
|
34
32
|
version: 3.0.3
|
35
33
|
type: :runtime
|
36
34
|
version_requirements: *id001
|
35
|
+
name: activerecord
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
|
-
name: rspec
|
39
37
|
prerelease: false
|
40
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
@@ -48,8 +46,8 @@ dependencies:
|
|
48
46
|
version: "0"
|
49
47
|
type: :development
|
50
48
|
version_requirements: *id002
|
49
|
+
name: rspec
|
51
50
|
- !ruby/object:Gem::Dependency
|
52
|
-
name: rspec-rails
|
53
51
|
prerelease: false
|
54
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
53
|
none: false
|
@@ -62,8 +60,8 @@ dependencies:
|
|
62
60
|
version: "0"
|
63
61
|
type: :development
|
64
62
|
version_requirements: *id003
|
63
|
+
name: rspec-rails
|
65
64
|
- !ruby/object:Gem::Dependency
|
66
|
-
name: sqlite3
|
67
65
|
prerelease: false
|
68
66
|
requirement: &id004 !ruby/object:Gem::Requirement
|
69
67
|
none: false
|
@@ -76,8 +74,8 @@ dependencies:
|
|
76
74
|
version: "0"
|
77
75
|
type: :development
|
78
76
|
version_requirements: *id004
|
77
|
+
name: sqlite3
|
79
78
|
- !ruby/object:Gem::Dependency
|
80
|
-
name: genspec
|
81
79
|
prerelease: false
|
82
80
|
requirement: &id005 !ruby/object:Gem::Requirement
|
83
81
|
none: false
|
@@ -90,8 +88,8 @@ dependencies:
|
|
90
88
|
version: "0"
|
91
89
|
type: :development
|
92
90
|
version_requirements: *id005
|
91
|
+
name: genspec
|
93
92
|
- !ruby/object:Gem::Dependency
|
94
|
-
name: mocha
|
95
93
|
prerelease: false
|
96
94
|
requirement: &id006 !ruby/object:Gem::Requirement
|
97
95
|
none: false
|
@@ -104,6 +102,7 @@ dependencies:
|
|
104
102
|
version: "0"
|
105
103
|
type: :development
|
106
104
|
version_requirements: *id006
|
105
|
+
name: mocha
|
107
106
|
description: ranked-model is a modern row sorting library built for Rails 3. It uses ARel aggressively and is better optimized than most other libraries.
|
108
107
|
email:
|
109
108
|
- matt.beale@madhatted.com
|
@@ -136,7 +135,6 @@ files:
|
|
136
135
|
- spec/support/active_record.rb
|
137
136
|
- spec/support/database.yml
|
138
137
|
- tmp/.gitignore
|
139
|
-
has_rdoc: true
|
140
138
|
homepage: https://github.com/harvesthq/ranked-model
|
141
139
|
licenses: []
|
142
140
|
|
@@ -166,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
164
|
requirements: []
|
167
165
|
|
168
166
|
rubyforge_project:
|
169
|
-
rubygems_version: 1.
|
167
|
+
rubygems_version: 1.8.8
|
170
168
|
signing_key:
|
171
169
|
specification_version: 3
|
172
170
|
summary: An acts_as_sortable replacement built for Rails 3
|