¿Cuál es la mejor manera de obtener un directorio temporal sin nada usando Ruby on Rails? Necesito que la API sea compatible multiplataforma. Stdlib tmpdir no funcionará.¿Cuál es la mejor manera de obtener un directorio temporal vacío en Ruby on Rails?
Respuesta
La función Dir#tmpdir
en el núcleo Ruby (no stdlib con la que se vinculó) debe ser multiplataforma.
Para usar esta función necesita require 'tmpdir'
.
Empecé a hacer frente a esto mediante el secuestro Tempfile, ver a continuación. Debería limpiarse a sí mismo como lo hace Tempfile, pero no siempre ... Todavía tiene que eliminar archivos en el tempdir. De todos modos, comparto esto aquí, podría ser útil como punto de partida.
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
Esto se puede utilizar de la misma manera como archivo temporal, por ejemplo:
Tempdir.new('foo')
Todos los métodos de archivo temporal, y, a su vez, del archivo debería funcionar. Solo lo probé brevemente, entonces no hay garantías.
Mira la librería Ruby stemp: http://ruby-stemp.rubyforge.org/rdoc/
Si haces algo como esto:
dirname = STemp.mkdtemp("#{Dir.tmpdir}/directory-name-template-XXXXXXXX")
nombredir será una cadena que apunta a un directorio que está garantizado que no existía previamente. Puedes definir para qué quieres que empiece el nombre del directorio. Las X se reemplazan con caracteres aleatorios.
EDITAR: alguien mencionó que esto no funcionó para ellos en 1.9, entonces YMMV.
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)
Trabaja para mí.
te refieres a trabajos con cierta probabilidad :) – Alexey
Un general aprox estoy usando ahora:
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
Así que en su código puede:
in_tmpdir do |tmpdir|
puts "My tmp dir: #{tmpdir}"
# work with files in the dir
end
El directorio temporal se eliminará automáticamente cuando el método terminará.
Muy buen enfoque, +1 – klaffenboeck
Acabo de descubrir que este comportamiento ya está implementado en [Dir.mktmpdir] (http://ruby-doc.org/stdlib-1.9.3/libdoc/ tmpdir/rdoc/Dir.html # method-c-mktmpdir) – fguillen
Para mí, el nombre 'in_tmpdir' sugiere que' pwd' cambia en el contexto del bloque. Sugeriría usar 'Dir.chdir (ruta, & bloque)' en lugar de simplemente ceder la ruta. – tfischbach
Actualización: gem install files
, entonces
require "files"
dir = Files do
file "hello.txt", "stuff"
end
ver más abajo para más ejemplos.
Aquí hay otra solución, inspirada en algunas otras respuestas. Este es adecuado para su inclusión en una prueba (por ejemplo, rspec o spec_helper.rb). Crea un directorio temporal basado en el nombre del archivo incluido, lo almacena en una variable de instancia para que persista durante la prueba (pero no se comparte entre las pruebas), y lo elimina al salir (u opcionalmente no, si desea verificar su contenido después de la prueba).
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
(También es posible usar Dir.mktmpdir (que ha estado presente desde Rubí 1.8.7) en lugar de Dir.mkdir pero encuentro la API de ese método confuso, por no mencionar el algoritmo de nombres.)
Uso ejemplo (y otro método de prueba útil):
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
actualización: he utilizado este código de dar un impulso a una joya que estoy llamando files
WHI ch tiene la intención de que sea super fácil crear directorios y archivos de forma temporal (p. prueba unitaria) uso. Ver https://github.com/alexch/files y https://rubygems.org/gems/files. Por ejemplo:
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
El objeto Dir
tiene un método mktmpdir que crea un directorio temporal:
require 'tmpdir' # Not needed if you are using rails.
Dir.mktmpdir do |dir|
puts "My new temp dir: #{dir}"
end
El directorio temporal se eliminará después de la ejecución del bloque.
Aunque supongo que esto requiere que puedas caber tu código en un bloque ... Me gusta :) – rogerdpack
de [ruby-doc.org] (http://ruby-doc.org/stdlib-2.0.0 /libdoc/tmpdir/rdoc/Dir.html#method-c-mktmpdir) _Si no se proporciona un bloque, se devuelve la ruta del directorio. En este caso, :: mktmpdir no elimina el directorio._ – thinkOfaNumber
¿Cómo no puedes colocar tu código en un bloque? Si es demasiado grande crea una clase/método/etc. y luego llámalo desde el bloque –
Ruby tiene Dir # mktmpdir, así que simplemente úselo.
require 'tempfile'
Dir.mktmpdir('prefix_unique_to_your_program') do
### your work here ###
end
Ver http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tmpdir/rdoc/Dir.html
o construir su propio uso de archivo temporal archivo temporal es de procesos y subprocesos único, por lo que sólo tiene que utilizar para construir una rápida 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
Ver http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tempfile/rdoc/Tempfile.html para las opciones sufijo/prefijo opcional.
Puede usar Dir.mktmpdir
.
El uso de un bloque eliminará el directorio temporal cuando se cierre.
Dir.mktmpdir do |dir|
File.open("#{dir}/foo", 'w') { |f| f.write('foo') }
end
O si necesita varios directorios temporales de existir al mismo tiempo, por ejemplo
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.mktmpdir
crea un directorio temporal en virtud Dir.tmpdir
(Tendrá que require 'tmpdir'
para ver lo que se evalúe como)
Si desea utilizar su propia ruta, Dir.mktmpdir
toma un segundo argumento opcional tmpdir si se proporciona un valor nulo. P.ej.
Dir.mktmpdir(nil, "/var/tmp") { |dir| "dir is '/var/tmp/d...'" }
- 1. Ruby on Rails: ¿la mejor manera de comparar dos fechas?
- 2. ¿Cuál es la mejor manera de agregar categorías a las publicaciones? Blog de Ruby on Rails
- 3. mejor ruby on rails cms
- 4. Ámbito vacío con Ruby on Rails
- 5. ¿Cuál es la diferencia entre Ruby y Ruby on Rails?
- 6. ¿Cuál es la manera correcta de anular un método setter en Ruby on Rails?
- 7. ¿Cuál es la mejor manera de vaciar un directorio?
- 8. ¿Cuál es la mejor manera de usar SOAP con Ruby?
- 9. ¿Cuál es el mejor entorno de Ruby on Rails para un usuario de Visual Studio?
- 10. ¿Cuál es la mejor opción para buscar en Ruby on Rails?
- 11. Mejor herramienta Ruby on Rails WebSocket
- 12. ¿Cuál es la mejor WYSIWYG para carriles - Ruby on Rails Blog
- 13. ¿Cuál es la diferencia entre Ruby on Rails y Grails?
- 14. Mejor ubicación IP para Ruby on Rails
- 15. ¿Cuál es la mejor manera de programar una tarea de envío de correo electrónico con Ruby on Rails?
- 16. La mejor solución para la autenticación en Ruby on Rails
- 17. JRuby on Rails vs. Ruby on Rails, ¿cuál es la diferencia?
- 18. Ruby On Rails con Windows Vista - ¿La mejor configuración?
- 19. Acceso al módulo en el directorio lib (Ruby on rails)
- 20. Ruby vs. Ruby on Rails
- 21. ¿Cuál es el mejor lugar para definir una constante en una aplicación de Ruby on Rails?
- 22. ¿Cuál es el mejor servidor web para la aplicación Ruby on Rails?
- 23. ¿Cuál es el mejor servidor de CI para las aplicaciones web de Ruby on Rails?
- 24. Ruby on Rails: la mejor manera de probar una llamada fallida a una API de terceros
- 25. La mejor manera de desinfectar los campos en ruby on rails
- 26. Leer archivos en el directorio en ruby on rails
- 27. Dispositivos móviles compatibles en Ruby on Rails
- 28. ¿Qué es MVC en Ruby on Rails?
- 29. Mejor marco de redes sociales de Ruby on Rails
- 30. ¿Cómo probar la aplicación de chat en Ruby on Rails?
Eso le da a la ruta temporal global del sistema operativo, pero no a la propia ruta dedicada y vacía de su aplicación. – Mike
De acuerdo con Mike, no creo que esta sea una respuesta correcta a la pregunta anterior. Lo que necesitamos es similar a Tempfile (http://ruby-doc.org/stdlib/libdoc/tempfile/rdoc/files/tempfile_rb.html), pero para los dirs; idealmente los archivos temporales de soporte de archivos temporales. – inger
sí, esta respuesta es falsa. Otros son más correctos, p. el mío en http://stackoverflow.com/questions/1139265/what-is-the-best-way-to-get-a-temporary-directory-in-ruby-on-rails/8823618#8823618 – AlexChaffee