mirror of
https://github.com/github/rails.git
synced 2026-02-01 09:44:56 -05:00
Add File.atomic_write to prevent users from seeing half written files. Useful for situations like Page Caching and the like. [Koz]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6262 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
*SVN*
|
||||
|
||||
* Add File.atomic_write, allows you to write large files in an atomic manner, preventing users from seeing half written files. [Koz]
|
||||
|
||||
* Allow users to provide custom formatters to Logger. [aeden]
|
||||
|
||||
* Hash#to_query CGI-escapes its keys. [Jeremy Kemper]
|
||||
|
||||
21
activesupport/lib/active_support/core_ext/file.rb
Normal file
21
activesupport/lib/active_support/core_ext/file.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
require 'tempfile'
|
||||
|
||||
# Write to a file atomically. Useful for situations where you don't
|
||||
# want other processes or threads to see half-written files.
|
||||
#
|
||||
# File.atomic_write("important.file") do |file|
|
||||
# file.write("hello")
|
||||
# end
|
||||
#
|
||||
# If your temp directory is not on the same filesystem as the file you're
|
||||
# trying to write, you can provide a different temporary directory.
|
||||
#
|
||||
# File.atomic_write("/data/something.imporant", "/data/tmp") do |f|
|
||||
# file.write("hello")
|
||||
# end
|
||||
def File.atomic_write(file_name, temp_dir = Dir.tmpdir)
|
||||
temp_file = Tempfile.new(File.basename(file_name), temp_dir)
|
||||
yield temp_file
|
||||
temp_file.close
|
||||
File.rename(temp_file.path, file_name)
|
||||
end
|
||||
29
activesupport/test/core_ext/file_test.rb
Normal file
29
activesupport/test/core_ext/file_test.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
require File.dirname(__FILE__) + '/../abstract_unit'
|
||||
|
||||
class AtomicWriteTest < Test::Unit::TestCase
|
||||
|
||||
def test_atomic_write_without_errors
|
||||
contents = "Atomic Text"
|
||||
File.atomic_write(file_name) do |file|
|
||||
file.write(contents)
|
||||
assert !File.exists?(file_name)
|
||||
end
|
||||
assert File.exists?(file_name)
|
||||
assert_equal contents, File.read(file_name)
|
||||
ensure
|
||||
File.unlink(file_name)
|
||||
end
|
||||
|
||||
def test_atomic_write_doesnt_write_when_block_raises
|
||||
File.atomic_write(file_name) do |file|
|
||||
file.write("testing")
|
||||
raise "something bad"
|
||||
end
|
||||
rescue
|
||||
assert !File.exists?(file_name)
|
||||
end
|
||||
|
||||
def file_name
|
||||
"atomic.file"
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user