Posted 23 days ago. Visible to the public.

Prefer using Dir.mktmpdir when dealing with temporary directories in Ruby

Ruby's standard library includes a class for creating temporary directories. Similar to Tempfile Archive it creates a unique directory name.

Note:

  • You need to use a block or take care of the cleanup manually
  • You can create a prefix and suffix e.g. Dir.mktmpdir(['foo', 'bar']) => /tmp/foo20220912-14561-3g93n1bar
  • You can choose a different base directory than Dir.tmpdir e.g. Dir.mktmpdir('foo', Rails.root.join('tmp')) => /home/user/rails_example/tmp/foo20220912-14561-pyr8qd. This might be necessary when your tests are running on CI. For this you might also want to commit tmp/.gitkeep to git so the tmp dir inside your project is present.

Example

Copy
Dir.mktmpdir('exports') => "/tmp/exports20220912-14561-pobh0a"

Improving your parallel tests with Dir.mktmpdir

When creating directories in parallel tests manually, you normally need to handle these issues:

  1. When multiple processes read and write to a directory with the same name e.g. tmp/some-test-folder you might end up in flaky specs.
  2. There is no guarantee that a folder is always removed e.g. in case your test run crashes. Following tests might see outdated files from a previous test run.

#mktmpdir solves these. However, you should still remove them after you're done. Here are three options:

Option 1: Using a block

Copy
it 'does something with a temporary directory' do Dir.mktmpdir('exports') do |export_folder_path| # ... end end

Option 2: Ensuring the removal of the folder

Copy
it 'does something with a temporary directory' do export_path = Dir.mktmpdir('exports') # ... ensure FileUtils.remove_entry(export_path) end

Option 3: Using a before/after block

Copy
before { @export_path = Dir.mktmpdir('exports') } after do if @export_path.present? FileUtils.remove_entry(@export_path) end end it 'does something with a temporary directory' do # ... end

Option 4: Without Dir.mktmpdir

Use something like "#{Rails.env}#{ENV['TEST_ENV_NUMBER']}" in you directory path when using Dir.mkdir.


Further reading:

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for unsupported versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2).

Owner of this card:

Avatar
Emanuel De
Last edit:
16 days ago
by Dominik Schöler
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Emanuel De to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more