mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -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:
parent
df7ca38d7d
commit
203932ec88
3 changed files with 52 additions and 0 deletions
|
@ -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
|
Loading…
Reference in a new issue