I got a method where I use Dir.chdir(File.dirname(__FILE__))
inside. I am using it so that I can run the ruby file from anywhere and not get this error: No such file or directory @ rb_sysopen - 'filename' (Errno::ENOENT)
.
Using the method for the first time works fine but using it for the second time throws an error. See method and exact error below.
def meth(string)
Dir.chdir(File.dirname(__FILE__))
hash = JSON.parse(File.read("file.json"))
# do something with hash and string
# return some value
end
meth("first string") # this returns what is expected
meth("second string") # this second usage of the method throws the error
Error sample pinpointing the line where I used Dir.chdir(File.dirname(__FILE__))
:
dir/decoder.rb:44:in `chdir': No such file or directory @ dir_s_chdir - lib (Errno::ENOENT)
Not sure if OS plays a role here, I am using an m1 BigSur on version 11.2.3.
- Why is this happening?
- What needs to be done so that the method` can be used as much as needed without running into the error?
CodePudding user response:
Your problem here seems to be that __FILE__
is a relative path like dir/decoder.rb
and that path becomes invalid after the first time Dir.chdir
is used, because that command changes the working directory of your entire Ruby process. I think the solution would be to do something like this in your decoder.rb
file:
DecoderDir = File.realpath(File.dirname(__FILE__))
def meth
Dir.chdir(DecoderDir)
# ...
end
I'm guessing that the first time the Ruby interpreter processes the file, that is early enough that the relative path in __FILE__
still refers to the right place. So, at that time, we generate an absolute path for future use.
By the way, a well-behaved library should not run Dir.chdir
because it will affect all use of relative paths throughout your entire Ruby process. I pretty much only run Dir.chdir
once and I run it near the beginning of my top-level script. If you're making a reusable library, you might want to do something like this to calculate the absolute path of the file you want to open:
DecoderJson = File.join(DecoderDir, 'file.json')