diff --git a/lib/ranked-model.rb b/lib/ranked-model.rb index 6667dae..5e97e57 100644 --- a/lib/ranked-model.rb +++ b/lib/ranked-model.rb @@ -18,7 +18,7 @@ def self.included base before_save :handle_ranking scope :rank, lambda { |name| - order arel_table[ ranker(name.to_sym).column ] + order ranker(name.to_sym).column } end diff --git a/lib/ranked-model/ranker.rb b/lib/ranked-model/ranker.rb index f443189..911cacf 100644 --- a/lib/ranked-model/ranker.rb +++ b/lib/ranked-model/ranker.rb @@ -137,19 +137,21 @@ def assure_unique_position end def rearrange_ranks + _scope = finder + unless instance.id.nil? + # Never update ourself, shift others around us. + _scope = _scope.where( instance.class.arel_table[:id].not_eq(instance.id) ) + end if current_first.rank && current_first.rank > RankedModel::MIN_RANK_VALUE && rank == RankedModel::MAX_RANK_VALUE - instance.class. - where( instance.class.arel_table[:id].not_eq(instance.id) ). + _scope. where( instance.class.arel_table[ranker.column].lteq(rank) ). update_all( "#{ranker.column} = #{ranker.column} - 1" ) elsif current_last.rank && current_last.rank < (RankedModel::MAX_RANK_VALUE - 1) && rank < current_last.rank - instance.class. - where( instance.class.arel_table[:id].not_eq(instance.id) ). + _scope. where( instance.class.arel_table[ranker.column].gteq(rank) ). update_all( "#{ranker.column} = #{ranker.column} + 1" ) elsif current_first.rank && current_first.rank > RankedModel::MIN_RANK_VALUE && rank > current_first.rank - instance.class. - where( instance.class.arel_table[:id].not_eq(instance.id) ). + _scope. where( instance.class.arel_table[ranker.column].lt(rank) ). update_all( "#{ranker.column} = #{ranker.column} - 1" ) rank_at( rank - 1 ) diff --git a/spec/duck-model/lots_of_ducks_spec.rb b/spec/duck-model/lots_of_ducks_spec.rb index 2b2eff5..baba7ea 100644 --- a/spec/duck-model/lots_of_ducks_spec.rb +++ b/spec/duck-model/lots_of_ducks_spec.rb @@ -87,6 +87,32 @@ end + describe "with max value and with_same pond" do + + before { + Duck.first(50).each_with_index do |d, index| + d.update_attributes :age => index % 10, :pond => "Pond #{index / 10}" + end + @duck_11 = Duck.offset(10).first + @duck_12 = Duck.offset(11).first + @ordered = Duck.where(:pond => 'Pond 1').rank(:age).where(Duck.arel_table[:id].not_in([@duck_11.id, @duck_12.id])).collect {|d| d.id } + @duck_11.update_attribute :age, RankedModel::MAX_RANK_VALUE + @duck_12.update_attribute :age, RankedModel::MAX_RANK_VALUE + } + + context { + subject { Duck.where(:pond => 'Pond 1').rank(:age).collect {|d| d.id } } + + it { should == (@ordered[0..-2] + [@ordered[-1], @duck_11.id, @duck_12.id]) } + } + + context { + subject { Duck.first.age } + it { should == 0} + } + + end + describe "with min value" do before {