1

I am having a problem when updating acts_as_list positions with nested_attributes, I have worked my way down and noticed the issue is still happening on the model level (as shown below). The problem is occurring when building a nested_attribute object and replacing another object at it's position. Has anyone experienced similar problems or point me in the right direction please ?

The setup:

class List < ActiveRecord
  has_many :list_items, -> { order(position: :asc) }, dependent: :destroy, inverse_of: :list
  accepts_nested_attributes_for :list_items, reject_if: :all_blank, allow_destroy: true
end

class ListItem < ActiveRecord
  acts_as_list scope: [:list_id, { deleted_at: nil }]
  belongs_to :list, inverse_of: :list_items
end

The Problem: The issue Im having is when building a new list_item in place of an existing one.

Example:

list = ListItem.create
list.list_items.create(name: 'Item 1')
list.list_items.create(name: 'Item 2')

#ListItems output
list.list_items.first.position #=> 1
list.list_items.last.position #=> 2

# Re-Order
new_item = list.list_items.build(name: 'New Item 2', position: 2)
list.list_items.second.position = 3

#Output 
list.list_items.first.position #=> 1
list.list_items.second.position #=> 3
list.list_items.last.position #=> 2

list.save

#Output 
list.list_items.first.position #=> 1
list.list_items.second.position #=> 3
list.list_items.last.position #=> 2

At this point all seems to work fine, however when I reload the 'list' from the database I get a weird issue ... (the list items are being ordered on 'id' as default for this example)

list.reload

#Output 
list.list_items.first.position #=> 1
list.list_items.second.position #=> 4
list.list_items.last.position #=> 2

After testing it seems that the items positions below the newly inserted item(s) is off by the number of newly inserted items.

Has anyone experienced the same issue and found the problem either in the code of acts_as_list itself ?

Thank you in advance for any help

1
  • Encountering the same issue, let me know if you were able to resolve it. Commented Jul 10, 2023 at 12:44

1 Answer 1

0

Just looking at your code you have a double comma in your has_many definition:

has_many :list_items, , -> { order(position: :asc) }, dependent: :destroy, inverse_of: :list

Remove the extra comma and see what happens. My guess is that the order is not being applied because it's not being provided and Rails is silently ignoring the proc.

2
  • Thank you, that was a typo. I removed the double comma but unfortunately have the same behaviour
    – k.jobbins
    Commented Jan 4, 2021 at 9:36
  • It might pay to reload list.list_items after adding items. You probably can't rely on .second being up to date in this case. Also try running the code in your example because you have another typo on the first line list = ListItem.create. Just to make sure this is actual code that is failing. Probably the best thing from here would be to clone the acts_as_list GitHub repo and make a failing test, then raise that as a Pull Request for me. Commented Jan 4, 2021 at 20:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.