summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2013-01-28 09:02:06 -0800
committerdanielsdeleo <dan@opscode.com>2013-01-28 10:56:08 -0800
commitea0205d629d5eb0aa25823d2cfc33d737adfe171 (patch)
tree5fec33074514b8bbda8c22729b1799fe9140f7d8
parentc9afae1142cc7f55bee00e4841c4335a870fde5a (diff)
downloadchef-ea0205d629d5eb0aa25823d2cfc33d737adfe171.tar.gz
[CHEF-3799] fixes TypeError for puts on VividMash
-rw-r--r--lib/chef/node/attribute_collections.rb9
-rw-r--r--spec/unit/node/attribute_spec.rb13
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"