brendon / acts_as_list

An ActiveRecord plugin for managing lists.
http://brendon.github.io/acts_as_list/
MIT License
2.04k stars 355 forks source link

Best practice for reordering when updating the scope of multiple list items? #348

Closed danielpuglisi closed 5 years ago

danielpuglisi commented 5 years ago

Hello there. Not sure if this was asked somewhere else before.

I'm currently working on a project where items can belong to a list, but don't have to.

class ListItem
  belongs_to :list, optional: true
  acts_as_list scope: [:list_id]
end

I was wondering if there is some sort of best practice for adding multiple list items at once when changing the scope of those items? In my case, I want users to be able to remove lists, but not the list items they contain. So the list items should get appended to the scope where list_id is nil.

One option would be to just iterate through all the list items and appending them to the new scope:

ActiveRecord::Base.transaction do
  list_items = @list.list_items
  list_items.each do |list_item|
    list_item.update(
      list_id: nil,
      position: :bottom
    )
  end
  @list.destroy
end

But this obviously results in n+1 queries which I'm trying to avoid. Nullifying the foreign key could be done directly on the database, but this messes up the ordering when there are already existing list items in the nil scope.

Any ideas?

brendon commented 5 years ago

Hi @danielpuglisi, unfortunately I don't know that there's a way to bulk update list items as the process of shuffling items around in the list to fill the hole is relative to each moved items. I think you'd have to do each one individually.

You don't have to specify position: :bottom in your update call above as that's the default.

If you're destroying the list then you can just do an update_all position: nil on the list items and wrap it in an acts_as_list_no_update block per: https://github.com/swanandp/acts_as_list#disabling-temporarily

I hope that helps :) Feel free to close this if that solves your problem :)

danielpuglisi commented 5 years ago

Hi @brendon, okay I see. Yes, this helps. Thank you!