chef-shell will free your mind...
$ chef-shell -s
chef > recipe_mode
chef:recipe > node.default['noxexistent'].class
=> Chef::Node::VividMash
When you access an attribute that does not exist from a recipe, it returns as an empty Chef::Node::VividMash object, not nil.
This is why your 'or' statement is failing =)
Some other trivia: 'node.set' is the same as 'node.normal'.
chef:recipe > node.default['foo'] = "bar"
=> "bar"
chef:recipe > node['foo']
=> "bar"
chef:recipe > node.normal['foo'] = "baz"
=> "baz"
chef:recipe > node['foo']
=> "baz"
chef:recipe > node.override['foo'] = "biz"
=> "biz"
chef:recipe > node['foo']
=> "biz"
Yet, all three are actually persisted on the node object
chef:recipe > node.default['foo']
=> "bar"
chef:recipe > node.normal['foo']
=> "baz"
chef:recipe > node.override['foo']
=> "biz"
The chef-client only consumes the one with the highest precedence.
-s