Beware acts_as_list

by Sean Cribbs

One should be careful when using Rails' acts_as_list macro. I was reimplementing the Radiant "reorder" extension (mostly to simplify it and make it compatible with "shards") for DP when I discovered some strange problems. My reordering controller actions took this format:

def move_higher
  @page = Page.find(params[:id])
  @page.move_higher
  redirect_to page_index
end

But apparently, while my tests didn't show any errors in reordering things, in certain circumstances in production mode I would end up messing it up and get two items with the same position value. This would make it near-impossible to move them in any direction.

However, a member of the team had also run into the issue when using other AR macros, and the problem had to do with scoping. Of course, the Page model has the acts_as_tree macro already applied. The solution, it seems, is to (re-)load all of the models in the same scope before executing the positioning action:

def move_higher
  @page = Page.find(params[:id])
  @page.parent.reload.children.reload
  @page.move_higher
  redirect_to page_index
end

Or more tersely,

@page.parent(true).children(true)

(Incidentally, I have to use the former because I override some of those associations in other extensions.) I hope this prevents you from running into the same problem!

© 2006-present Sean CribbsGithub PagesTufte CSS