I'm using acts_as_list v0.9.17 this way:
class ListItem < ActiveRecord::Base
acts_as_list scope: [:column1_id, :column2_id], :add_new_at => :bottom
end
When a new (scoped) @list_item
is created, say the one where column1_id
is 1
, column2_id
is 11
and column3_id
is 37
, the database looks as follows, as expected:
id | position | column1_id | column2_id | column3_id
--- | -------- | ---------- | ---------- | ----------
750 | 1 | 1 | 11 | 89
751 | 2 | 1 | 11 | 56
752 | 3 | 1 | 11 | 105
753 | 4 | 1 | 11 | 25
754 | 5 | 1 | 11 | 37
However, when a @list_item
is destroyed, say the one where column1_id
is 1
, column2_id
is 11
and column3_id
is 56
(record id 751
), then the database looks as follows:
id | position | column1_id | column2_id | column3_id
--- | -------- | ---------- | ---------- | ----------
750 | 1 | 1 | 11 | 89
752 | 3 | 1 | 11 | 105
753 | 4 | 1 | 11 | 25
754 | 5 | 1 | 11 | 37
That means there is a gap for position
2
.
How to prevent or adjust the gap? That is, how to handle reordering of list items when a list item is destroyed?
Note: I know there are methods that change position and reorder list but I don't know whether
and how to use them to solve the issue (maybe using someway remove_from_list
).
As you say you need to use the method you provided, and you can either do it in your controller or the model itself. If you're the kind of guy who likes callbacks, then:
class ListItem < ActiveRecord::Base
acts_as_list scope: [:column1_id, :column2_id], :add_new_at => :bottom
before_destroy { |record| record.remove_from_list }
....
end
Some people don't like handling logic like that as a callback, so you can also add it straight into your controller:
class ListItemsController < Wherever
....
....
def destroy
@list_item.remove_from_list
@list_item.delete
....
end
end
Personally I'd add it into the model but they both do the same thing.
If you need to try and fix a list that has a missing record in it, say you have LineItems with an ID and position of 0-4 and 6-9, missing position 5. You can make a dirtyish fix in console with:
LineItem.where('position >= ?', 5).each { |line_item| line_item.update_attributes(position: line_item.position - 1) }
This will find all LineItems with a position over 4, and decrement each of them by one, leaving you with a correctly ordered list from 0-8.