[Nitro] Possible BUG in lib/og/relation/has_many.rb (and possible fix)

Aidan Rogers aidan at yoyo.org
Thu Jan 19 02:49:18 EST 2006

Hi all,

I've encountered what is possibly a bug in lib/og/relation/ 
has_many.rb.  Consider this code - assume all that is needed to  
manage Bar and Baz is accurate:

module Foo
class Bar
     property    :bar_prop, String
     has_many    :bazs, Baz

class Baz
     property    :baz_prop, String
     belongs_to  :bar, Bar

bar = Foo::Bar.new
baz = Foo::Baz.create
# bar.save
assert(bar.bazs.to_ary.include? baz)

That assertion should be true (caveat: not a real test case!).   
However, it is false.  This is because the add_baz method (which is  
eval'd to be part of the class in has_many.rb line 57) sets the  
foreign key of the owner of baz to the primary key of the owner.   
However, this doesn't work if the owner hasn't been saved, because it  
does not have a primary key at that point.

One workaround is to save the owner (commented out in the above  
example) before adding, or to use 'create' instead of 'new'.  This  
ensures the owner has a primary key.  No problem in most cases.  The  
reason I discovered this (possible) bug is that I was trying to  
access the various relations of my owner class in a method that I was  
using as a post_insert - can't save in that method, otherwise I'd get  
a nasty infinite loop.

So, one possible fix is to say in the add_* method:

       def add_#{target_singular_name}(obj, options = nil)
         return unless obj
	self.save unless self.saved? # THIS LINE IS THE NEW ONE
         obj.#{foreign_key} = @#{owner_class.primary_key}

However, this may have some unpleasant side effects that I can't  
foresee at this moment.  Can anyone shed any light on this?  Can  
anyone think of a reason this might be bad?


Strange bug part 2.

So, given all of the above, and regardless of how you fix it or  
workaround it, here's the really strange part.  If I then want to  
output my bar to  yaml, I'd require 'yaml' and say:

puts bar.to_yaml

There's no mention of the bazs property, as I'd expect.  This is  
definitely a bug.  Next weirdness:  If before to_yaml I put:

puts bar.bazs.inspect

Yaml complains with /usr/local/lib/ruby/1.8/yaml/rubytypes.rb:9:in  
`to_yaml': can't dump anonymous class Class (TypeError)

but using:


gives no error (although, still no bazs property in the yaml).

Anyone? :-)


ps.  I'll keep investigating this - I think this may be some  
crossover weirdness with YAML and the module_eval that happens in Og.

More information about the Nitro-general mailing list