diff options
author | danielsdeleo <dan@opscode.com> | 2013-01-28 09:02:06 -0800 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2013-01-28 10:56:08 -0800 |
commit | ea0205d629d5eb0aa25823d2cfc33d737adfe171 (patch) | |
tree | 5fec33074514b8bbda8c22729b1799fe9140f7d8 | |
parent | c9afae1142cc7f55bee00e4841c4335a870fde5a (diff) | |
download | chef-ea0205d629d5eb0aa25823d2cfc33d737adfe171.tar.gz |
[CHEF-3799] fixes TypeError for puts on VividMash
-rw-r--r-- | lib/chef/node/attribute_collections.rb | 9 | ||||
-rw-r--r-- | spec/unit/node/attribute_spec.rb | 13 |
2 files changed, 21 insertions, 1 deletions
diff --git a/lib/chef/node/attribute_collections.rb b/lib/chef/node/attribute_collections.rb index dcbb4601bd..d5d496fd60 100644 --- a/lib/chef/node/attribute_collections.rb +++ b/lib/chef/node/attribute_collections.rb @@ -154,7 +154,14 @@ class Chef alias :attribute? :has_key? def method_missing(symbol, *args) - if args.empty? + # Calling `puts arg` implicitly calls #to_ary on `arg`. If `arg` does + # not implement #to_ary, ruby recognizes it as a single argument, and + # if it returns an Array, then ruby prints each element. If we don't + # account for that here, we'll auto-vivify a VividMash for the key + # :to_ary which creates an unwanted key and raises a TypeError. + if symbol == :to_ary + super + elsif args.empty? self[symbol] elsif symbol.to_s =~ /=$/ key_to_set = symbol.to_s[/^(.+)=$/, 1] diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb index fac898be26..435dc3230c 100644 --- a/spec/unit/node/attribute_spec.rb +++ b/spec/unit/node/attribute_spec.rb @@ -234,6 +234,19 @@ describe Chef::Node::Attribute do end end + describe "when printing attribute components" do + + it "does not cause a type error" do + # See CHEF-3799; IO#puts implicitly calls #to_ary on its argument. This + # is expected to raise a NoMethodError or return an Array. `to_ary` is + # the "strict" conversion method that should only be implemented by + # things that are truly Array-like, so NoMethodError is the right choice. + # (cf. there is no Hash#to_ary). + lambda { @attributes.default.to_ary }.should raise_error(NoMethodError) + end + + end + describe "when fetching values based on precedence" do before do @attributes.default["default"] = "cookbook default" |