I just handled the exact same scenario in one of the apps I am building.
The solution in the accepted answer did not work as it will recursively use callbacks to call the object you are trying to update (inside update_attributes). Also we need to skip the id for self object inside the query.
Here is how I am doing it finally, and it does seem to work for all cases.
after_commit :order_priorities, :if => :persisted?
after_destroy :handle_priorities_when_destroyed
def order_priorities
correct_priority = MyModel.where('id != ? AND priority < ?',id,priority).count + 1
MyModel.where.not(id:id).order(:priority).each_with_index {|x,i|
if x.priority < priority
x.update_column(:priority, i+1)
else
x.update_column(:priority, i+2)
end
}
self.update_column(:priority,correct_priority)
end
def handle_priorities_when_destroyed
MyModel.where.not(id:id).order(:priority).each_with_index {|x,i|
x.update_column(:priority, i+1)
}
end
Here I am using after_commit callback, so that I will be able to set correct_priority for self that I define in my method. Other callbacks will not work as the value will be overwritten during commit.
Using update_column, so that callbacks are skipped when I do not want them.
Logic is self explanatory.