Today I would like to show how easy it can be to setup a tree structure with activescaffold.
At the end of this post we should have a tree structure in which we can CRUD elements, even changing the parent of a child.
In addition we can sort children of a parent by drag and drop.
As usual we will need my little how-to application.
1. Create a new menu model
rails g active_scaffold Menu name:string action:string position:integer ancestry:string rake db:migrate
position attribute is needed for sorting and ancestry attribute for ancestry plugin.
2. Install plugins
rails plugin install git://github.com/rails/acts_as_list.git rails plugin install git://github.com/vhochstein/active_scaffold_sortable.git rails plugin install git://github.com/stefankroes/ancestry.git
3. Include ancestry into Menu Model
app/model/menu.rb class Menu < ActiveRecord::Base has_ancestry end
4. Configure Menu Controller
app/controller/menus_controller.rb
class MenusController < ApplicationController
active_scaffold :menu do |conf|
conf.nested.add_scoped_link(:children) #nested link to children
end
protected
# If nested let active_scaffold manage everything
# if not just show all root nodes
def beginning_of_chain
nested? ? super : active_scaffold_config.model.roots
end
# Assign parent node to just created node
def after_create_save(record)
if (nested? && nested.scope)
parent = nested_parent_record(:read)
record.send("#{nested.scope}").send(:<<, parent) unless parent.nil?
end
end
end
5. Starting server and creating menu records
Create records, edit records, delete records,…..
6. Something is missing…. Sorting
app/model/menu.rb class Menu < ActiveRecord::Base acts_as_list has_ancestry end
You have to restart your server to enable sorting feature in your UI.
Oct 22, 2010 @ 10:57:56
I must be doing something wrong. I get the children added to a menu item, but I get an error whenever I try to edit any menu item
ActionView::Template::Error (wrong number of arguments (1 for 2)):
4: <label for="">
5:
6:
7:
8:
9: :render_field, :id => params[:id]) %>
10:
Is there supposed to be something meaningful in action, like a link_to something? I don’t see any draggability, either, so I must be missing something major. Is there a working demonstration anywhere so I can understand how it should work?
Oct 22, 2010 @ 10:59:49
I don’t know what happened to the error messages … let me try again:
ActionView::Template::Error (wrong number of arguments (1 for 2)): 4: <label for=""> 5: 6: 7: 8: 9: :render_field, :id => params[:id]) %> 10:Oct 22, 2010 @ 11:09:29
Sorry, trying to figure out how to escape the HTML …
ActionView::Template::Error (wrong number of arguments (1 for 2)): 4: <label for="<%= active_scaffold_input_options(column, scope)[:id] %>"><%= column.label %></label> 5: </dt> 6: <dd> 7: <%= active_scaffold_input_for column, scope %> 8: <% if column.update_columns -%> 9: <%= loading_indicator_tag(:action => :render_field, :id => params[:id]) %> 10: <% end -%>Oct 25, 2010 @ 12:10:40
My example did nt work with ruby 1.9.2. It s fixed now.
Thanks a lot for reporting and sorry for the issue…
Dec 21, 2010 @ 13:08:03
Editing ancestry seems not working…
To reproduce this issue… :
- create menu 1
– create two sub-menus (childrens : 11, 12)
- edit sub-menu 12 change ancestry to ‘__11′
- menu 11 is lost… (field value for ancestry = 3 (should be : 1/3 ?)
Dec 21, 2010 @ 13:20:45
Can you please open an issue. Thanks a lot
Dec 28, 2010 @ 09:02:58
Your issue is hopefully fixed now.