4

This code broke on Ruby 2.1

class Test
  def to_s()
    "hi"
  end
end

puts [Test.new(), Test.new()].to_s

Ruby 1.9.3:

$ ruby --version
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
$ /opt/chef/embedded/bin/ruby test.rb
[hi, hi]

Ruby 2.1:

$ ruby --version
ruby 2.1.4p265 (2014-10-27 revision 48166) [x86_64-linux]
$ ruby test.rb
[#<Test:0x000000022ac400>, #<Test:0x000000022ac3d8>]

Is this documented somewhere? How can the old behavior be preserved?

omribahumi
  • 2,011
  • 1
  • 17
  • 19

3 Answers3

5

Your code:

puts [Test.new(), Test.new()].to_s

is a questionable use of Array.to_s. Instead I'd use:

puts [Test.new(), Test.new()].map(&:to_s)

While I can see that the first use makes sense, the second use makes more sense and should work in any version of Ruby.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • I figured there's a way around this, I guess there isn't. Thanks – omribahumi Dec 17 '14 at 19:30
  • 1
    I agree with this. When you want to call a method on an object inside an Enumerable I think you should have to enter into the Object and call the method internally using something like `map` in this case. I think the original implementation is a little less in congruence with OO design than the 2.0 version. – engineersmnky Dec 17 '14 at 19:30
  • 1
    Also just as a note `map(&:to_s)` is actually faster than `Array#to_s` by more than a marginal amount. Although this simple implementation is inconsequential mass implementation could show as much as 60% difference in performance. Althouhg please note the difference in out put `Array#to_s` in this case will be `"[hi,hi]"` where as `map(&:to_s)` will be `["hi","hi"]` – engineersmnky Dec 17 '14 at 20:16
1

On ruby 2.1.5:

class Test
  def to_s
    "hi"
  end

  alias inspect to_s # add this line
end

puts [Test.new, Test.new].to_s
#=> [hi, hi]

This seems like a bug to me. If it is intended behavior, that is really annoying.

Adrian
  • 14,931
  • 9
  • 45
  • 70
0

You don't need to_s. puts does the work for you

puts [Test.new(), Test.new()]
# hi
# hi

If you want the brackets, that's what inspect is for (in which case it makes sense that you would need to define Test#inspect).

Max
  • 21,123
  • 5
  • 49
  • 71