Tutorial :How to create a sortable interface with 'acts as nested set' in RubyOnRails



Question:

I've been implementing some nice interactive interfaces that can sort lists in my m rails app for models that use acts_as_list. I have a sort function that gets called and sets the position for each record afterr each drag and drop using the sortable_element script.aculo.us function.

This is an example of the controller action that handles the sort after the drag and drop completes:

  def sort      params[:documents].each_with_index do |id, index|        Document.update_all(['position=?', index+1], ['id=?', id])      end    end  

Now I am trying to do this same thing with a model that is a nested set (acts_as_nested_set). An example of the type of interface interaction: http://script.aculo.us/playground/test/functional/sortable_tree_test.html

I am stuck on how to write the controller action to handle the sort when the drag and drop completes.

I've added the :tree=>true parameter to the sortable _element function so far which appears to send a list of hashes but it seems that I am still missing information about the entire nested order....

I was certain this has been done before and didn't want to try to reinvent the wheel, but I can't seem to find any examples of the controller action <-> view with js function setup to handle a sortable acts_as_nested_set

Any help with creating an interactive sortable nested set in rubyonrails would be appreciated!

Thanks,

John


Solution:1

a good solution with ONE sql-query from http://henrik.nyh.se/2008/11/rails-jquery-sortables

# in your model:    def self.order(ids)    update_all(      ['ordinal = FIND_IN_SET(id, ?)', ids.join(',')],      { :id => ids }    )  end  


Solution:2

see example app here - http://github.com/matenia/jQuery-Awesome-Nested-Set-Drag-and-Drop

It's a hacky way of doing it, but its basically, sort first, then save order. Uses nestedsortables, serializelist, and 2 actions to traverse the tree

PS: I know this question is over a year old but hoping that the link above helps someone else coming here.

edit: added Rails3 example with some slightly cleaner code.


Solution:3

Just found this:

sortable_element_for_nested_set on github

Looks like it'll do the job, however I'm having some bugs while trying to implement it. It basically makes the javascript return the id of the element that was moved, then goes through the elements and returns its new parent, left and right values. Can't believe it's taken this long for something like this to be written! Lucky it was just when I needed it :)


Solution:4

Here's a snippet of code from my project that does the trick:

http://gist.github.com/659532

 def reorder_children(ordered_ids)      ordered_ids = ordered_ids.map(&:to_i)      current_ids = children.map(&:id)      unless current_ids - ordered_ids == [] && ordered_ids - current_ids == []        raise ArgumentError, "Not ordering the same ids that I have as children. My children: #{current_ids.join(", ")}. Your list: #{ordered_ids.join(", ")}. Difference: #{(current_ids - ordered_ids).join(', ')} / #{(ordered_ids - current_ids).join(', ')}"       end      j = 0      transaction do        for new_id in ordered_ids          old_id = current_ids[j]          if new_id == old_id            j += 1          else            Category.find(new_id).move_to_left_of(old_id)            current_ids.delete(new_id)          end        end      end    end  

You call it on the parent, and it'll sort the children.

You just pass in the value that you get from Sortable, like so:

  def reorder      @category.reorder_children(params[:categories])      render :nothing => true    end  

Hope this helps.

//Lars


Solution:5

the_sortable_tree

Sortable Nested Set for Rails 3.1+

Dreaming about Drag and Drop for Nested Sets? It’s should be with JQuery? Here’s the solution!


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »