I'm working on upgrading from attachment_fu to carrierwave, since attachment_fu is broken in rails 3.
None of the tests are able to run, because we have invalid fixtures that were using the syntax from attachment_fu for attachment files.
For example, we have a Post model that has one PostAttachment. Here's what the data in the PostAttachment fixture looks like:
a_image:
post_id: 1
attachment_file: <%= Rails.root>/test/files/test.png
And this is the error I'm getting:
ActiveRecord::StatementInvalid: PGError: ERROR: column "attachment_file" of relation "post_attachments" does not exist
LINE 1: INSERT INTO "post_attachments" ("post_id", "attachment_file"...
attachment_file
would have been picked up by attachment_fu, and it would have taken care of all the 开发者_开发百科processing to create the attachment_fu attachment for the model.
Is there a way to have image attachments in the fixtures, but with using CarrierWave instead?
The only way I've managed to get this to work is to use a storage provider specifically for testing that doesn't actually save/read files.
In your config/initializers/carrier_wave.rb
Add a NullStorage class that implements the minimum interface for a storage provider.
# NullStorage provider for CarrierWave for use in tests. Doesn't actually
# upload or store files but allows test to pass as if files were stored and
# the use of fixtures.
class NullStorage
attr_reader :uploader
def initialize(uploader)
@uploader = uploader
end
def identifier
uploader.filename
end
def store!(_file)
true
end
def retrieve!(_identifier)
true
end
end
Then when initializing CarrierWave add a clause for the test environment, e.g.,
if Rails.env.test?
config.storage NullStorage
end
Here is a gist of my complete carrier_wave.rb for reference. It also includes how to setup S3 for uploads in staging/production and local storage for development so you can see how to configure CarrierWave in context.
Once CarrierWave is configured you can simply put any string in the fixtures column to simulate an uploaded file.
Try passing a file instead of a String.
a_image:
post_id: 1
attachment_file: File.open(Rails.root.join("test/files/test.png"))
This works for me using FactoryGirl
Note: Edit thanks to @dkobozev
config/initializers/carrier_wave.rb
In Rails 4
# class NullStorage is defined here before the following block
if Rails.env.test?
CarrierWave.configure do |config|
config.storage NullStorage
end
end
& in fixtures:
a_image:
post_id: 1
attachment_file: <%= File.open(Rails.root.join("test/files/test.png")) %>
To be able to use fixtures that have uploaded files as well as doing uploads in the tests, I've played around with CarrierWave for a bit lately. I've written an article about how I'd do it.
I know it is old but, for some that uses Rails 5 + RSpec + CarrierWave + Fixtures:
Edit test configs:
# config/initializers/carrierwave.rb
if Rails.env.test?
class NullStorage < CarrierWave::Storage::Abstract
def store!(_file)
_file
end
def retrieve!(identifier)
file = Rails.root.join('spec', 'fixtures', 'files', identifier)
tmp = Rails.root.join('tmp', 'blank_tmp.jpg')
FileUtils.cp(file, tmp)
CarrierWave::SanitizedFile.new(tmp)
end
end
CarrierWave.configure do |config|
config.storage = NullStorage
config.enable_processing = false
end
end
Create a folder and a file, for example spec/fixtures/files/some-user-photo.jpg
and, create some fixtures, for example:
first_user:
avatar: "some-user-photo.jpg"
name: "First User Name"
about: "First User About Long Text..."
lat: 0.001
lng: 0.001
created_at: <%= Time.current - 3.days %>
updated_at: <%= Time.current - 3.days %>
That is enough to make the test understand that this user has an avatar
We have just removed the fixtures all together, the system seeds this files for each test. Ask yourself... do you need al these fixtures here for this test? No probably not. And Fixtures dont BANG! so we just use Model.create!( ... )
with specific data for the test
精彩评论