在 Ruby on Rails 中获取空临时目录的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1139265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to get an empty temporary directory in Ruby on Rails?
提问by Mike
采纳答案by slillibri
The Dir#tmpdirfunction in the Ruby core (not stdlib that you linked to) should be cross-platform.
Dir#tmpdirRuby 核心中的函数(不是您链接的 stdlib)应该是跨平台的。
To use this function you need to require 'tmpdir'.
要使用此功能,您需要require 'tmpdir'.
回答by Justin Tanner
回答by fguillen
A general aprox I'm using now:
我现在使用的一般 aprox:
def in_tmpdir
path = File.expand_path "#{Dir.tmpdir}/#{Time.now.to_i}#{rand(1000)}/"
FileUtils.mkdir_p path
yield path
ensure
FileUtils.rm_rf( path ) if File.exists?( path )
end
So in your code you can:
所以在你的代码中你可以:
in_tmpdir do |tmpdir|
puts "My tmp dir: #{tmpdir}"
# work with files in the dir
end
The temporary dir will be removedautomatically when your method will finish.
当您的方法完成时,临时目录将自动删除。
回答by ijcd
Ruby has Dir#mktmpdir, so just use that.
Ruby 有 Dir#mktmpdir,所以只需使用它。
require 'tempfile'
Dir.mktmpdir('prefix_unique_to_your_program') do |dir|
### your work here ###
end
See http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tmpdir/rdoc/Dir.html
见http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tmpdir/rdoc/Dir.html
Or build your own using Tempfile tempfile that is process and thread unique, so just use that to build a quick Tempdir.
或者使用进程和线程唯一的 Tempfile 临时文件构建您自己的临时文件,因此只需使用它来构建快速 Tempdir。
require 'tempfile'
Tempfile.open('prefix_unique_to_your_program') do |tmp|
tmp_dir = tmp.path + "_dir"
begin
FileUtils.mkdir_p(tmp_dir)
### your work here ###
ensure
FileUtils.rm_rf(tmp_dir)
end
end
See http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tempfile/rdoc/Tempfile.htmlfor optional suffix/prefix options.
有关可选的后缀/前缀选项,请参阅http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tempfile/rdoc/Tempfile.html。
回答by fguillen
require 'tmpdir' # not needed if you are loading Rails
tmp_dir = File.join(Dir::tmpdir, "my_app_#{Time.now.to_i}_#{rand(100)}")
Dir.mkdir(tmp_dir)
Works for me.
对我来说有效。
回答by Dennis
You can use Dir.mktmpdir.
您可以使用Dir.mktmpdir.
Using a block will get rid of the temporary directory when it closes.
使用块将在关闭时摆脱临时目录。
Dir.mktmpdir do |dir|
File.open("#{dir}/foo", 'w') { |f| f.write('foo') }
end
Or if you need multiple temp directories to exist at the same time, for example
或者,如果您需要同时存在多个临时目录,例如
context 'when there are duplicate tasks' do
it 'raises an DuplicateTask error' do
begin
tmp_dir1 = Dir.mktmpdir('foo')
tmp_dir2 = Dir.mktmpdir('bar')
File.new("#{tmp_dir1}/task_name", 'w+')
File.new("#{tmp_dir2}/task_name", 'w+')
expect { subject.filepath('task_name') }.to raise_error(TaskFinder::DuplicateTask)
ensure
FileUtils.remove_entry tmp_dir1
FileUtils.remove_entry tmp_dir2
end
end
end
Dir.mktmpdircreates a temporary directory under Dir.tmpdir(you'll need to require 'tmpdir'to see what that evaluates to).
Dir.mktmpdir在Dir.tmpdir(您需要require 'tmpdir'查看其评估结果)下创建一个临时目录。
If you want to use your own path, Dir.mktmpdirtakes an optional second argument tmpdirif non-nil value is given. E.g.
如果您想使用自己的路径,如果给出非 nil 值,Dir.mktmpdir则采用可选的第二个参数tmpdir。例如
Dir.mktmpdir(nil, "/var/tmp") { |dir| "dir is '/var/tmp/d...'" }
回答by AlexChaffee
Update: gem install files, then
更新:gem install files,然后
require "files"
dir = Files do
file "hello.txt", "stuff"
end
See below for more examples.
有关更多示例,请参见下文。
Here's another solution, inspired by a few other answers. This one is suitable for inclusion in a test (e.g. rspec or spec_helper.rb). It makes a temporary dir based on the name of the including file, stores it in an instance variable so it persists for the duration of the test (but is not shared between tests), and deletes it on exit (or optionally doesn't, if you want to check its contents after the test run).
这是另一个解决方案,受到其他一些答案的启发。这个适合包含在测试中(例如 rspec 或 spec_helper.rb)。它根据包含文件的名称创建一个临时目录,将其存储在一个实例变量中,以便它在测试期间持续存在(但不在测试之间共享),并在退出时将其删除(或可选地不删除,如果您想在测试运行后检查其内容)。
def temp_dir options = {:remove => true}
@temp_dir ||= begin
require 'tmpdir'
require 'fileutils'
called_from = File.basename caller.first.split(':').first, ".rb"
path = File.join(Dir::tmpdir, "#{called_from}_#{Time.now.to_i}_#{rand(1000)}")
Dir.mkdir(path)
at_exit {FileUtils.rm_rf(path) if File.exists?(path)} if options[:remove]
File.new path
end
end
(You could also use Dir.mktmpdir(which has been around since Ruby 1.8.7) instead of Dir.mkdirbut I find the API of that method confusing, not to mention the naming algorithm.)
(您也可以使用Dir.mktmpdir(从 Ruby 1.8.7 开始就已经存在)而不是Dir.mkdir,但我发现该方法的 API 令人困惑,更不用说命名算法了。)
Usage example (and another useful test method):
使用示例(以及另一种有用的测试方法):
def write name, contents = "contents of #{name}"
path = "#{temp_dir}/#{name}"
File.open(path, "w") do |f|
f.write contents
end
File.new path
end
describe "#write" do
before do
@hello = write "hello.txt"
@goodbye = write "goodbye.txt", "farewell"
end
it "uses temp_dir" do
File.dirname(@hello).should == temp_dir
File.dirname(@goodbye).should == temp_dir
end
it "writes a default value" do
File.read(@hello).should == "contents of hello.txt"
end
it "writes a given value" do
# since write returns a File instance, we can call read on it
@goodbye.read.should == "farewell"
end
end
Update: I've used this code to kickstart a gem I'm calling fileswhich intends to make it super-easy to create directories and files for temporary (e.g. unit test) use. See https://github.com/alexch/filesand https://rubygems.org/gems/files. For example:
更新:我已经使用这段代码来启动我正在调用的 gem files,它旨在让创建临时(例如单元测试)使用的目录和文件变得超级容易。请参阅https://github.com/alexch/files和https://rubygems.org/gems/files。例如:
require "files"
files = Files do # creates a temporary directory inside Dir.tmpdir
file "hello.txt" # creates file "hello.txt" containing "contents of hello.txt"
dir "web" do # creates directory "web"
file "snippet.html", # creates file "web/snippet.html"...
"<h1>Fix this!</h1>" # ...containing "<h1>Fix this!</h1>"
dir "img" do # creates directory "web/img"
file File.new("data/hello.png") # containing a copy of hello.png
file "hi.png", File.new("data/hello.png") # and a copy of hello.png named hi.png
end
end
end # returns a string with the path to the directory
回答by inger
I started to tackle this by hiHymaning Tempfile, see below. It should clean itself up as Tempfile does, but doesn't always yet.. It's yet to delete files in the tempdir. Anyway I share this here, might be useful as a starting point.
我开始通过劫持 Tempfile 来解决这个问题,见下文。它应该像 Tempfile 一样自行清理,但并不总是如此。它尚未删除 tempdir 中的文件。无论如何,我在这里分享这个,作为一个起点可能很有用。
require 'tempfile'
class Tempdir < Tempfile
require 'tmpdir'
def initialize(basename, tmpdir = Dir::tmpdir)
super
p = self.path
File.delete(p)
Dir.mkdir(p)
end
def unlink # copied from tempfile.rb
# keep this order for thread safeness
begin
Dir.unlink(@tmpname) if File.exist?(@tmpname)
@@cleanlist.delete(@tmpname)
@data = @tmpname = nil
ObjectSpace.undefine_finalizer(self)
rescue Errno::EACCES
# may not be able to unlink on Windows; just ignore
end
end
end
This can be used the same way as Tempfile, eg:
这可以像 Tempfile 一样使用,例如:
Tempdir.new('foo')
All methods on Tempfile , and in turn, File should work. Just briefly tested it, so no guarantees.
Tempfile 上的所有方法,反过来, File 应该工作。只是简单地测试了它,所以不能保证。
回答by JT.
Check out the Ruby STemp library: http://ruby-stemp.rubyforge.org/rdoc/
查看 Ruby STemp 库:http://ruby-stemp.rubyforge.org/rdoc/
If you do something like this:
如果你做这样的事情:
dirname = STemp.mkdtemp("#{Dir.tmpdir}/directory-name-template-XXXXXXXX")
dirname will be a string that points to a directory that's guaranteed not to exist previously. You get to define what you want the directory name to start with. The X's get replaced with random characters.
dirname 将是一个字符串,指向一个保证以前不存在的目录。您可以定义您希望目录名称以什么开头。X 被替换为随机字符。
EDIT: someone mentioned this didn't work for them on 1.9, so YMMV.
编辑:有人提到这在 1.9 上对他们不起作用,所以 YMMV。

