在Ruby中使用不同的闭包类型时奇怪的File.open行为

时间:2014-10-10 11:12:23

标签: ruby windows

我开始学习Chef来管理我们的服务器,我在Ruby中偶然发现了一个非常奇怪的(在我看来)行为。我不认识Ruby,所以这可能只是我的一个误解。

我得到的error

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

因为我确定它实际上并不是关于权限的,所以下一个合乎逻辑的事情是检查文件锁定。在通过相关代码挖掘了一下之后,我发现有一种方法可以为每个文件生成校验和。

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

找到了,我搜索了一下,发现了一个关于在Ruby中关闭文件的answer,似乎代码实际上很好......但事实并非如此。我试图将方法改为 “块格式”,它没有错误地工作:

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

有人可以解释两个版本的代码之间的区别吗?

- 编辑 -

似乎只在Windows中出现此问题,并且可能仅在使用ChefDK 0.3.0提供的ruby时才会出现:

  

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

1 个答案:

答案 0 :(得分:0)

回答你的问题

  

有人可以解释两个版本的代码之间的区别吗?

  • 阻止总是返回一些内容do结束and{ ... }非常重要这只是人事编程偏好。

  • 块i有两种不同的约定 现在就告诉你,你想要订阅哪种宗教信仰。

第一宗教说

当你有single line or single line block时你会使用花括号如果你有multi line block,你可以使用doend

words.each { |word| puts word }  # single line or single line block

words.each do |word|  # multi line block
  puts word
  p 1
end

第二宗教说

如果你的块只是做了一些有副作用的东西,你不关心你可能会做的返回值并结束

words.each do |word|
  puts word
end

如果您关心返回值,那么您将使用{...}

back_words = words.map{ |word| word.reverse }
希望我回答你的问题!!!