3

I am working with a library which uses strings as ids throughout. I want to make a class which can be used in place of these ids, but looks like a string to the existing code. E.g. I have an existing test which looks like this:

require 'test/unit'
class IdString < Hash
  def initialize(id)
    @id = id
  end

  def to_s
    @id
  end
end

class TestGet < Test::Unit::TestCase
  def test_that_id_is_1234
    id = IdString.new('1234')

    assert_match(/1234/, id)
  end
end

Unfortunately this fails with:

TypeError: can't convert IdString to String

Is there a way to fix this without changing all the existing code which expects ids to be strings?

Stefan
  • 8,819
  • 10
  • 42
  • 68

2 Answers2

7

You should implement to_str method, which is used for implicit conversions:

def to_str
  @id
end
Marek Lipka
  • 50,622
  • 7
  • 87
  • 91
  • It seems to me that `#to_s` and `#to_str` are both used, in different situations. Where can I found document of such situations? – Jokester Jun 13 '13 at 10:22
  • 1
    That does seem to fix the issue, and is nice and simple. It appears that to_s vs to_str is very complicated: http://briancarper.net/blog/98/ – Stefan Jun 13 '13 at 10:24
  • 1
    More info on the "to_s vs to_str" topic: http://stackoverflow.com/questions/11182052/ruby-to-s-vs-to-str – toro2k Jun 13 '13 at 11:15
0

Your issue is arising because you're inheriting from Hash. Why do you need to this if what you're really after is a string?

If you want to encapsulate the ID into its own separate object (which you should probably think twice about), just do this:

require 'test/unit'

class IdString < Hash
  def initialize(id)
    @id = id
  end

  def to_str
    @id
  end
end

class TestGet < Test::Unit::TestCase
  def test_that_id_is_1234
    id = IdString.new('1234')

    assert_match(/1234/, id)
  end
end
alexpls
  • 1,914
  • 20
  • 29
  • No, even if I remove the inheritance from Hash, I get the same issue. Also, I need to inherit from Hash for the other functionality of the class. – Stefan Jun 13 '13 at 10:20
  • For what you're after Marek's answer is right. I've edited the code in mine to use `to_str` as well. – alexpls Jun 13 '13 at 10:24