I came across an issue in my code and after a hard debug session I found something that smells.
First the context of my issue. I have a AR object that has a polymorphic belongs_to currently tied to nothing, I want to dump it to YAML. record.to_yaml This raises the following exception: TypeError: wrong argument type nil (expected Data) from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/ lib/ruby/1.8/yaml.rb:391:in `emit' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/ lib/ruby/1.8/yaml.rb:391:in `quick_emit' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/ lib/ruby/1.8/yaml/rubytypes.rb:15:in `to_yaml'
Now to the point: tracing the code path lead me to AssociationProxy#method_missing which for 2.3.x or 3.0.x is very similar: def method_missing(method, *args) if load_target unless @target.respond_to?(method) message = "undefined method `#{method.to_s}' for \"#{@target}\":#{@target.class.to_s}" raise NoMethodError, message end
if block_given? @target.send(method, *args) { |*block_args| yield(*block_args) } else @target.send(method, *args) end end end
The smell: load_target may return nil, when it does, the return value of method_missing is nil. BUT the caller may have wanted to call a method on nil. Like #to_yaml ! The caller (in this case something in YAML) expects some data back from nil.to_yaml (a string) but it receives nil which later raises the exception.
What about that?
Regards,
Pascal