在Rails中创建一个对象时,我想自动从资源目录中为它分配一个库存图像,以后可以被用户覆盖。
因此,我在创建对象时执行以下私有方法:
def save_stock_image
image_path = Dir.glob(<list-of-images-from-directory>).sample
File.open(image_path) do |file|
self.image = file
self.save!
end
end
然而,经过6次RSpec测试后,我开始收到以下错误:
Failure/Error: let(:object) { create(:object) }
Errno::EMFILE:
Too many open files - /tmp/16020130822-36578-q8j9v9.jpg
# ./app/models/object.rb:502:in `block in save_stock_image'
# ./app/models/object.rb:501:in `open'
# ./app/models/object.rb:501:in `save_stock_image'
# ./spec/controllers/object_controller_spec.rb:318:in `block (3 levels) in <top (required)>'
# ./spec/controllers/object_controller_spec.rb:344:in `block (4 levels) in <top (required)>'
上述错误在60次测试中约有40次。我已经看了几个SO问题,以及https://github.com/thoughtbot/paperclip/issues/1122和https://github.com/thoughtbot/paperclip/issues/1000。我能找到的最接近的答案是确保文件描述符正在关闭。在我在块中使用File.open
之前,我使用file.close
明确关闭了文件 - 这也不起作用。
明显我做错了吗?有没有更好的方法来完成我想要做的事情?
更新
看起来它与Paperclip上传到S3之前创建的临时文件有关。关闭那些我错过的临时文件有什么东西吗?
答案 0 :(得分:1)
我自己也碰到了这个。看起来主分支有一个修复。请在此处查看我的评论:
https://github.com/thoughtbot/paperclip/issues/1326?source=cc
答案 1 :(得分:0)
如果这是一个开发/测试环境,您需要快速解决。
尝试识别resque进程ID,终止它并重新启动resque服务器。
此外,您可以尝试以下
Redis.current.client.reconnect
$redis = Redis.current
答案 2 :(得分:0)
刚碰到这个,最新的代码对我没有帮助。因此,我通过生成子进程将关闭这些临时文件的工作委托给操作系统:
def save_stock_image
ActiveRecord::Base.connection.disconnect!
Proces.fork do
image_path = Dir.glob(<list-of-images-from-directory>).sample
File.open(image_path) do |file|
self.image = file
self.save!
end
end
Process.wait
ActiveRecord::Base.establish_connection
end
另外,请考虑在Process.wait上设置超时,如下所示:Waiting for Ruby child pid to exit