So when running the specs we also create a lot of fake attachments, but they are never cleaned up. Which is probably obvious, because we never actually destroy
the models (containing the attachments), but truncate the database or rollback the transactions.
So I tried to find a way to 1) automatically/more easily clean up those dummy attachments, and 2) make sure it works when using parallel:specs
. And over my different projects, where in some I use different gems to manage my attachments.
In one project, I am using paperclip
and there I took the following approach. In the initializer config/initializers/paperclip.rb
I wrote
Paperclip::UriAdapter.register
if Rails.env.production?
Paperclip::Attachment.default_options.merge!(
hash_secret: ENV.fetch('SECRET_KEY_BASE'),
s3_protocol: :https,
url: ':s3_domain_url',
path: "/:class/:attachment/:id/:style/:hash.:extension",
storage: :s3,
s3_credentials: { .. }
)
elsif Rails.env.development?
Paperclip::Attachment.default_options.merge!(
url: "/system/:class/:attachment/:id/:style/:hash.:extension",
hash_secret: Rails.application.credentials.secret_key_base
)
elsif Rails.env.test? || Rails.env.cucumber?
Paperclip::Attachment.default_options.merge!(
url: "/spec_#{ENV['TEST_ENV_NUMBER']}/:class/:attachment/:id/:style/:hash.:extension",
hash_secret: Rails.application.credentials.secret_key_base
)
end
and then in rspec rails_helper.rb
I can add the following piece of code
config.after(:suite) do
FileUtils.remove_dir(File.join(Rails.root, 'public', "spec_#{ENV['TEST_ENV_NUMBER']}"), true)
end
In another projects I am using carrier_wave and there it is a little more difficult, but it amounts to the same approach. In CarrierWave
we create different uploaders, and each have their own configuration. In my project I first iterate over all uploaders in my own code-base, and explicitly require one uploader from our own shared gem (between different projects). So we add an initializer config/carrierwave_clean_spec_attachments.rb
(or whatever name you prefer) to override the path when in test mode:
if Rails.env.test? || Rails.env.cucumber?
Dir["#{Rails.root}/app/uploaders/*.rb"].each { |file| require file }
require 'document_uploader'
CarrierWave::Uploader::Base.descendants.each do |klass|
next if klass.anonymous?
klass.class_eval do
def cache_dir
"#{Rails.root}/spec/support/uploads_#{ENV['TEST_ENV_NUMBER']}/tmp"
end
def store_dir
"#{Rails.root}/spec/support/uploads_#{ENV['TEST_ENV_NUMBER']}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end
end
and then in my rails_helper.rb
I can then add the following statement:
config.after(:suite) do
FileUtils.rm_rf(Dir["#{Rails.root}/spec/support/uploads_#{ENV['TEST_ENV_NUMBER']}"])
end
How do you do this? Do you use another gem for storage/attachments and how do you solve it? E.g. when using ActiveStorage
?
Comments
Add comment