I was hacking a to_hash to Object (I’m not saying this is a good idea, just an experiment). When I came across an odd issue, where IO stopped working.
#lib/object.rb
class Object
def to_hash
self.instance_variables.inject({}) { |hash,var| hash[var.to_s.delete("@")] = self.instance_variable_get(var); hash }
end
end
#run_test1.rb
require_relative 'lib/Object'
require 'FileUtils'
puts 'run test'
#run_test2.rb
require_relative 'lib/Object'
File.open('test.txt', 'w') {|f| f.write('this is a test')}
in run_test1 I get an
<internal:lib/rubygems/custom_require>:29:in `set_encoding': wrong number of arguments (0 for 1..2) (ArgumentError)
from <internal:lib/rubygems/custom_require>:29:in `require'
from <internal:lib/rubygems/custom_require>:29:in `require'
from .../run_test1.rb:2:in `<main>'
in run_test2 I get
run_test2.rb:3:in `initialize': No such file or directory - test.txt (Errno::ENOENT
from run_test2.rb:3:in `open'
from run_test2.rb:3:in `<main>'
(if the file exists it says the file is not open for writing)
While I’m not surprised it happened – just curious, What is going on here? Theoretically it should be fine, however what is the underlying cause.
The relevant info:
- ruby 1.9.2p290 (2011-07-09) [i386-mingw32]
- XP SP3 32-bit
- RUBYGEMS VERSION: 1.8.12
The
to_hashmethod is used to identify objects that coerce to Hash. In that sense, it behaves liketo_aryorto_str. The method you implemented is more liketo_aorto_s.Lots of Ruby code, including Ruby core code, checks for
to_hashto figure out whether an argument is an options hash (arg.respond_to? :to_hash) and from there on follow a different execution path. This gets even more messed up by some code checking if the object is a real hash or not (Hash === arg).You might want to name your method
to_hor something similar.