I started learning Chef to manage our servers and I stumbled in a very weird (in my opinion) behavior in Ruby. I do not know Ruby so this might be just a misunderstanding from my part.
The error I was getting was
`delete': Permission denied - [some path]/metadata.json (Errno::EACCES)
Since I knew for sure that it was not actually about permissions, the next logical thing was to check for file locking. After digging a bit through the relevant code, I discovered that there is a method that produces 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 that, I searched a bit and found an answer about closing files in Ruby and it seemed that the code was actually fine... but it was not. I tried to change the method to the "block format" and it worked without error:
def checksum_file(file, digest)
File.open(file, 'rb') do |f|
checksum_io(f, digest)
end
end
Can someone please explain the difference between the two versions of the code?
-- Edit --
It seems that this problem occurs only in Windows and maybe only when using the ruby provided by ChefDK 0.3.0 :
ruby 2.0.0p451 (2014-02-24) [i386-mingw32]
Answer of your question
Can someone please explain the difference between the two versions of the code?
Block always return something so do
end and
and { ... }
dose't really matter This is just personnel programming preference.
There are two different convention with block i'm going to dispense to you now and it up to you which religion you want to subscribe to.
First religion says that
when you have a single line or single line block
you would use the curly braces And if you have a multi line block
you would 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
Second religion says that
If your block simply does something has side effect and you dont care about the return value you might put do and end
words.each do |word|
puts word
end
where as if you do care about return value you would use { ... }
back_words = words.map{ |word| word.reverse }
hope I answere your question !!!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With