I have a model that's set as acts_as_nested_set. I want to try to
display/manage this model in a sane way. For the typical nesting
depth of my application, I think nested activescaffold tables would do
just fine. Running into a a few snags implementing this.
My biggest issue is displaying the tables. Initially I'm used a
conditions_for_collection callback along with a record action link
that just calls the list action. The condtions callback looks to see
if there is an 'id' param set and returns an appropriate condition. So
if there's no id set it selects all the root nodes. If an id is set,
it selects all the nodes that have their parent_id set to the param
id. The action link displays inline and :after. This actually works
fairly well, except for one issue. There's no way to close the
'nested' table, since it's not being rendered with the active scaffold
nested capabilities.
Is there anyway to get the nested capabilities of active scaffold to
display these types of tables? Or at the very least an easy way for me
to display the little 'X' to close the inline table just like the
built-in nested table?
The other minor issue:
I setup a record action link that creates a new child of the current
record. I did this by overriding the 'create' controller method and
doing the correct add_child and save calls. I'm still trying to figure
out what to render/return from this function. Ideally I'd like it to
'open' the nested table for the parent of the newly created child, but
I'd settle for a notification that just said 'child created'. This may
be my inexperience with rails in general showing, but is there a way
to just flash the info message in active scaffold?
I realize this is quite a weird hackery of activescaffold; but I never
got anywhere by doing normal things ;)
Thanks for any assistance
Here's how I'm setting it up:
config.action_links.add 'list', :type => :record, :inline =>
true, :position
=> :after
On Apr 12, 1:33 pm, "Lance Ivy" <l...@cainlevy.net> wrote:
> The box used for nested scaffolds (and Update and Show) is wrapped around
> the response from those action link to adapt the response for inline display
> in the table. Thing is, the inline adapter should be standard fare, unless
> your record action link is ':position => false'. So I'm not sure why you
> don't see it.
>
> Could you paste the configuration where you define these links?
>
Here's the code:
create_table "devicetypes" do |t|
t.column :created_on, :timestamp
t.column :updated_on, :timestamp
t.column :description, :string
t.column :parent_id, :integer
t.column :lft, :integer
t.column :rgt, :integer
end
class Nestedset < ActiveRecord::Base
acts_as_nested_set
has_many :children, :class_name => 'Devicetype', :foreign_key =>
"parent_id"
belongs_to :parent, :class_name => 'Devicetype', :foreign_key =>
"parent_id"
end
class NestedsetController < ApplicationController
active_scaffold :nestedset do |config|
columns[:description].set_link('nested', :parameters =>
{:associations => :children})
config.list.columns.exclude :children,:parent, :lft, :rgt
config.update.columns.exclude :lft, :rgt, :children,:parent
config.create.columns.exclude :lft, :rgt, :children,:parent
end
def after_create_save(record)
return if !@record.parent
@record.parent.add_child(@record)
end
def conditions_for_collection
return ['parent_id is NULL'] if !params.has_key?(:nested)
end
end
Basically you create has_many/belongs_to associations to 'trick'
active scaffold into seeing the acts_as_nested_set in such a way that
it triggers nested tables.
Combined with the conditions_for_collection method you get an initial
display of just the nodes that have no parents ("root" nodes). When
you click on any of the descriptions you get a nested scaffold that
contains only children of that node. And it cascades deeper in the
same manner. The 'Create New' link on each table creates children of
the proper node with help from the after_create_save.
The only bug I've seen is that sometimes after you create a child
display it in the wrong table. This is because the HTML ids are only
unique on a controller basis. There's multiple tables with the same
controller name on the page, so sometimes the javascript finds the
wrong table. The record is created with the correct parent, it'll just
display wrong until you refresh the page. Fixing this would require
some changes in the ActiveScaffold code, which I may tackle a bit
later.
If anyone sees an obvious way to improve on this, please let me know.
On Apr 15, 12:19 pm, "Lance Ivy" <l...@cainlevy.net> wrote:
> Great work!
>
> > return if !...@record.parent
Tried your code and I get the nested tables displayed properly, but
adding a child node has very strange behavior. What happens is no
matter how deep into the tree I am, the child node I add is inserted
into the database with no parent, putting it at the root. For reasons
I don't know, an update query is then done on the original parent
node, making it a child of the record I justed inserted. I don't know
where this query is coming from.
So if it looks like this:
- "Node"
---- (I add "Subnode" here)
When I refresh the page, here's what I get:
- "Subnode"
--- "Node"
Any idea what could be causing this?
> > > active scaffold into seeing theacts_as_nested_setin such a way that
my callback looks like this:
def setchild
if self[:parent_id].nil?
return true
end
self.save
self.move_to_child_of self.parent
return true
end
Note: I'm using the better_nested_set plugin which is where the
move_to_child_of method comes from. If you aren't you just add the
child normally. It also seems it might be smarter to move this to an
after_save callback; but I can't remember if I tried that and it
didn't work or not.
The self[:parent_id] thing is a bit weird. If you just do
self.parent.nil? and it's true, active scaffold breaks when it tries
to force the object and all it's associations to fail. So I have to
avoid a direct reference to self.parent
Guys: the forced saving of a record AND all it's loaded associations
(and their associations etc etc etc) is generating TONS of completely
unecessary SQL UPDATE statements (and breaks in some cases as seen
above with the self.parent case). Normally it's ok if you never touch
the associations, as they aren't loaded. But I've got some code that
loads quite a few associations in order to properly handle some
operations; and they all get updated by active scaffold. I can see
this being the source of some performance issues in the future.
I spent 4 or 5 hours on this last night combing through code, I know
it's going to end up being something really obvious because something
Is happening, it's just backwards.
Here's the model:
class Category < ActiveRecord::Base
has_many :children, :class_name => 'Category', :foreign_key =>
'parent_id'
belongs_to :parent, :class_name => 'Category', :foreign_key =>
'parent_id'
has_many :articles
acts_as_nested_set
validates_presence_of :title
after_create :setchild
def setchild
if self[:parent_id].nil?
return true
end
self.save
self.move_to_child_of self.parent
return true
end
end
And controller:
class CategoryController < ApplicationController
layout 'admin'
active_scaffold :category do |config|
config.columns[:title].set_link('nested', :parameters =>
{:associations => :children})
config.list.columns.exclude :children, :parent, :lft, :rgt
config.create.columns = :title, :description
config.update.columns = :title, :description
end
def conditions_for_collection
return ['parent_id IS NULL'] if !params.has_key?(:nested)
end
end
Jeff: your problem sounds familiar, let me look around my code and see
how I dealt with that.
On May 7, 11:29 am, "Lance Ivy" <l...@cainlevy.net> wrote:
> We've optimized the saving a bit in trunk so that it only saves
> records/associations from the form.
>
Cheers,
Tys