0

I'm using acts_as_nested_set on a model which is called node. There are multiple lists stored in the database, each starting with the root node. The root node doesn't have a parent, that's how I know it's a root.

Now this all works as expected, but the problem is this:

All nodes have an alias, which needs to be unique in that list.

So, all children of a root have a unique alias, but all nodes are in a single db-table.

Does anyone know a solution for checking uniqueness only in the tree the node is in?

EDIT:

As Baldrick points out I'd be off good using a custom validation. The problem is, in the validation root returns nil. As shown below:

class Baco::Node < ActiveRecord::Base

  set_table_name "baco_nodes"

  acts_as_nested_set :order => :position

  acts_as_list :scope => :parent_id

  default_scope order("parent_id, position")

  validate :alias_uniqueness

  def alias_uniqueness

    p self.parent.parent       # return the root
    p self.parent              # returns the parent
    p self.root                # returns nil

    if parent.nil?
      root = self
    else
      root = self.parent.root
    end

    if root.descendants.index { |node| node != self && node.alias == self.alias }
      errors.add(:alias, "Alias already used")
    end
  end

end

EDIT 2

The problem appeared when creating a child. So it's a new node that only has a parent yet, but no left and right values.. Instead of getting the root of the new node I now get the root of it's parent, which of course would be the same.. So the custom validation above works now.

Thanks

Tim Baas
  • 6,035
  • 5
  • 45
  • 72

1 Answers1

0

Use a custom validation method to check that the alias is not already used by a node descendant of the same root:

class Node < ActiveRecord::Base
  validate :alias_uniqueness

  def alias_uniqueness
    if self.root.descendants.index {|node| node != self && node.alias == self.alias}
      errors.add(:alias, "Alias already used")
    end
  end

  ...
end
Baldrick
  • 23,882
  • 6
  • 74
  • 79
  • I don't think this will work because the root method gets the first root from the database. And the problem is I have multiple trees in one table. Though a custom validation may be my only option, I'll try and tweak it and let you know how that works out.. Thanks – Tim Baas Feb 10 '12 at 14:30
  • `self.root` should get the root of the current node. – Baldrick Feb 10 '12 at 14:33
  • Oh, that would be great! I was looking in the source of awesome_nested_set and found the root method (pasted it in my post), but it didn't seem to get the right root. Now when looking further I see there is another root method (also in my post).. – Tim Baas Feb 10 '12 at 14:41
  • Calling root in that validator returns a nil. – Tim Baas Feb 10 '12 at 14:56
  • The problem is the node doesn't have it's left and right values there for some reason.. – Tim Baas Feb 10 '12 at 15:10
  • @Tim : Did you use `move_to_child_of` as suggested in the Cheat Sheet? https://github.com/collectiveidea/awesome_nested_set/wiki/Awesome-Nested-Set-Cheat-Sheet – Baldrick Feb 10 '12 at 15:16
  • No, I just found a solution: The problem appeared when creating a child. So it's a new node that only has a parent yet, but no left and right values.. Instead of getting the root of the new node I now get the root of it's parent, which of course would be the same.. Anyway, thanks for your custom-validation solution! – Tim Baas Feb 10 '12 at 15:25