Ancestry fails. how about setting new primary_key_formats? #174

Open
djoy82 opened this Issue Jan 7, 2014 · 4 comments

Comments

Projects
None yet
4 participants

djoy82 commented Jan 7, 2014

Hi,

The tree that I want to construct has a primary key that follows the format /XXX:[0-9][0-9][0-9]/. The ids are set exactly as imported from an ontology file (i.e: they are the same as in the ontology file). I set the primary key format in my model "TreeNode" using the following line:

has_ancestry :primary_key_format => /XXX:[0-9][0-9][0-9]/

However, I can only create the root (there is only one). I assume that because it is the root, his "ancestry" will be "NULL". However, for all other nodes (which according to the definition are its children), I cannot create a TreeNode. the validation fails. I tried to investigate, and make sure the the format of the ancestry column is flexible.
Indeed, the validation in "lib/ancestry/has_ancestry.rb" shows the following in line 35
"validates_format_of ancestry_column, :with => /\A#{primary_key_format.source}(/#{primary_key_format.source})*\Z/, :allow_nil => true"

In my case, this will translate to '/\AXXX:[0-9][0-9]0-9*\Z/'

To circumvent the error meessage, I tried this

Treenode.create (:name=>"Root", :id=>"XXX:000"). In my model, it is OK not to have a parent_id if the node is the root.
t = TreeNode.new(:name=>"bblabla", :id=>"XXX:123", :parent_id=>"XXX:000")

t.ancestry gives me "XXX:000", which is OK.
t.ancestry_depth gives 1, which is OK

However, when I try to save (t.save!), I get the error message shown below (ERROR I). But I have no clue what exactly is causing Ancestry to be invalid.

t.valid? yields "false"
I tried the different t.validates (e.g. t.validates_presence_of(:parent_id); t.validates_format_of :id, :with /\AXXX:[0-9][0-9]0-9*\Z/). Things seemed to be OK.

I realized later on that I have both the 1.2.5 and the 2.0.0 versions of the gem.

In the second version, ANCESTRY_PATTERN is defined /\A[0-9]+(/[0-9]+)*\Z/, and I do NOT find where it can be overriden in case you want to set a different primary key format.

I looks like the problem comes from there.

I updated my gem list through bundler and NOW, I cannot even set a primary key format.

When I try to create a root node, I get the ERROR 2. So, although the literature still mention the possibility of setting a different key format, it looks like it is actually impossible now.

Please help me here. Could you let me know what's wrong?

Thank you

""" ERROR I """"
Validation failed: Ancestry is invalid
/Users/yandj/Programming/sampl_app/vendor/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/validations.rb:56:in save!' /Users/yandj/Programming/sampl_app/vendor/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/attribute_methods/dirty.rb:33:insave!'
/Users/yandj/Programming/sampl_app/vendor/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/transactions.rb:264:in block in save!' /Users/yandj/Programming/sampl_app/vendor/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/transactions.rb:313:inblock in with_transaction_returning_status'
/Users/yandj/Programming/sampl_app/vendor/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in transaction' /Users/yandj/Programming/sampl_app/vendor/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/transactions.rb:208:intransaction'
/Users/yandj/Programming/sampl_app/vendor/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/transactions.rb:311:in with_transaction_returning_status' /Users/yandj/Programming/sampl_app/vendor/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/transactions.rb:264:insave!'
...

"""

""" ERROR II """
Ancestry::AncestryException: Unknown option for has_ancestry: :primary_key_format => /XXX:[0-9][0-9][0-9][0-9]/.

"""

Primary_key_format appears to no longer be an option in Ancestry which is also causing me challenges since my primary key is a uuid, not an int.

This may be your issue too since the last error you have listed above is:

Ancestry::AncestryException: Unknown option for has_ancestry: :primary_key_format => /XXX:[0-9][0-9][0-9][0-9]/.

Be great if this option came back. Until then, fork time.

For a quick and dirty solution that seems so far to work for me, create an initialiser with the contents (based upon your regexp above):

module Ancestry
send :remove_const, :ANCESTRY_PATTERN
const_set :ANCESTRY_PATTERN, /\AXXX:[0-9][0-9][0-9]0-9*\Z/
end

👍 @kipcole9 re: UUID support.

halo commented Nov 29, 2014

For UUID in Postgres, this worked for me. Thanks for the hint.

module Ancestry
  send :remove_const, :ANCESTRY_PATTERN
  const_set :UUID_PATTERN, '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
  const_set :ANCESTRY_PATTERN, %r{\A#{UUID_PATTERN}(\/#{UUID_PATTERN})*\Z}
end

There seems to be an open pull request for this by the way: #191

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment