Weird File.open behavior when using different types of closure in Ruby

I started to learn chefs to manage our servers, and I came across a very strange (in my opinion) behavior in Ruby. I do not know Ruby, so it may just be a misunderstanding on my part.

The error I received was

`delete': Permission denied - [some path]/metadata.json (Errno::EACCES) 

Since I knew for sure that this is not just about permissions, the next logical task is to check file locks. After digging through the appropriate code, I found that there is a method that creates a checksum for each file.

 def checksum_file(file, digest) File.open(file, 'rb') { |f| checksum_io(f, digest) } end def checksum_io(io, digest) while chunk = io.read(1024 * 8) digest.update(chunk) end digest.hexdigest end 

Having found this, I searched a bit and found an answer about closing files in Ruby, and it seemed that the code was really beautiful ... but it wasn’t, I tried to change the method to “block format” and it worked without errors:

 def checksum_file(file, digest) File.open(file, 'rb') do |f| checksum_io(f, digest) end end 

Can someone explain the difference between the two versions of the code?

- Change -

It seems that this problem only occurs on Windows and possibly only when using ruby ​​provided by ChefDK 0.3.0:

ruby 2.0.0p451 (2014-02-24) [i386-mingw32]

+7
windows ruby
source share
1 answer

The answer to your question

Can someone explain the difference between the two versions of the code?

  • The block always returns something, so do end and and { ... } dose is really important. This is just a preference for programming staff.

  • There are two different agreements with the block, which I’m going to get around to you now, and to you, which religion you want to subscribe to.

The first religion says that

when you have single line or single line block , you should use curly braces. If you have multi line block , you should use do and end .

 words.each { |word| puts word } # single line or single line block words.each do |word| # multi line block puts word p 1 end 

The second religion says that

If your block just has a side effect, and you don’t care about the return value that you could do, and end

 words.each do |word| puts word end 

where, as if you care about the return value, you should use {...}

 back_words = words.map{ |word| word.reverse } 

I hope that I will answer your question !!!

0
source share

All Articles