brendon / acts_as_list

An ActiveRecord plugin for managing lists.

Home Page:http://brendon.github.io/acts_as_list/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

danielpuglisi opened this issue · comments

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?

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 :)

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