From 4ee2ade5f72677e2afd92033e6f0d4c244a8e43d Mon Sep 17 00:00:00 2001 From: Elliot Shank Date: Mon, 2 Feb 2015 11:15:23 -0600 Subject: [PATCH 1/3] Be careful about invoking #to_hash on arbitrary objects. --- lib/awesome_print/formatter.rb | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/awesome_print/formatter.rb b/lib/awesome_print/formatter.rb index 329b0e6..0382b02 100644 --- a/lib/awesome_print/formatter.rb +++ b/lib/awesome_print/formatter.rb @@ -62,9 +62,9 @@ module AwesomePrint #------------------------------------------------------------------------------ def awesome_self(object, type) if @options[:raw] && object.instance_variables.any? - awesome_object(object) - elsif object.respond_to?(:to_hash) - awesome_hash(object.to_hash) + return awesome_object(object) + elsif hash = convert_to_hash(object) + awesome_hash(hash) else colorize(object.inspect.to_s, type) end @@ -318,6 +318,26 @@ module AwesomePrint # Utility methods. #------------------------------------------------------------------------------ + def convert_to_hash(object) + if not object.respond_to?(:to_hash) + return nil + end + if object.method(:to_hash).arity != 0 + return nil + end + + hash = object.to_hash + if not hash + return nil + end + + if not hash.respond_to?(:keys) or not hash.respond_to?('[]') + return nil + end + + return hash + end + def align(value, width) if @options[:multiline] if @options[:indent] > 0 From 4391b7175c6cf860b6c45a25d6e6d9a70daea783 Mon Sep 17 00:00:00 2001 From: Elliot Shank Date: Mon, 2 Feb 2015 17:19:15 -0600 Subject: [PATCH 2/3] Fix coding style in formatter. --- lib/awesome_print/formatter.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/awesome_print/formatter.rb b/lib/awesome_print/formatter.rb index 0382b02..0e07ecb 100644 --- a/lib/awesome_print/formatter.rb +++ b/lib/awesome_print/formatter.rb @@ -319,7 +319,7 @@ module AwesomePrint # Utility methods. #------------------------------------------------------------------------------ def convert_to_hash(object) - if not object.respond_to?(:to_hash) + if ! object.respond_to?(:to_hash) return nil end if object.method(:to_hash).arity != 0 @@ -327,11 +327,7 @@ module AwesomePrint end hash = object.to_hash - if not hash - return nil - end - - if not hash.respond_to?(:keys) or not hash.respond_to?('[]') + if ! hash.respond_to?(:keys) || ! hash.respond_to?('[]') return nil end From f6f3914baeb8798ab0b737658beee5fd8420540b Mon Sep 17 00:00:00 2001 From: Elliot Shank Date: Mon, 2 Feb 2015 17:19:45 -0600 Subject: [PATCH 3/3] Test Formatter#to_hash. --- spec/formats_spec.rb | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/spec/formats_spec.rb b/spec/formats_spec.rb index f769663..4c1c8ac 100644 --- a/spec/formats_spec.rb +++ b/spec/formats_spec.rb @@ -708,5 +708,56 @@ EOS my = My.new expect { my.methods.ai(:plain => true) }.not_to raise_error end + + describe "should handle a class that defines its own #to_hash method" do + it "that takes arguments" do + class My + def to_hash(a, b) + end + end + + my = My.new + expect { my.ai(:plain => true) }.not_to raise_error + end + + it "that returns nil" do + class My + def to_hash() + return nil + end + end + + my = My.new + expect { my.ai(:plain => true) }.not_to raise_error + end + + it "that returns an object that doesn't support #keys" do + class My + def to_hash() + object = Object.new + object.define_singleton_method('[]') { return nil } + + return object + end + end + + my = My.new + expect { my.ai(:plain => true) }.not_to raise_error + end + + it "that returns an object that doesn't support subscripting" do + class My + def to_hash() + object = Object.new + object.define_singleton_method(:keys) { return [:foo] } + + return object + end + end + + my = My.new + expect { my.ai(:plain => true) }.not_to raise_error + end + end end end