I have an Artwork model with an image attribute where Carrierwave is mounted. While writing controller specs I realized that the image field stays blank, even when I thought I was passing in a file object.
My debug info tells me that the problem is with the image attribute I have CarrierWave mounted on, and not something else. I don't think I'm passing in the information it needs, but I don't know what to try.
Here's the the controller action, with some debug information to identify the problem:
def create
@artwork = @imageable.artworks.new(params[:artwork])
logger.debug "Artwork should be valid: #{@artwork.valid?}"
logger.debug "Errors: #{@artwork.errors.full_messages}"
if @artwork.save
flash[:success] = "Artwork created."
redirect_to [@imageable, :artworks]
else
flash[:error] = "Artwork not created."
render :new
end
end
In the test log I see this after running my specs:
Processing by ArtworksController#create as HTML
Parameters: {"artwork"=>{"image"=>"#<File:0x4515480>", "title"=>"Portrait","year"=>"2012", "surface_type"=>"canvas", "size"=>"10 x 10", "price"=>"100.0", "for_sale"=>false, "prints_available"=>false, "notes"=>"extra notes"}, "file"=>"#<File:0x46c6938>", "originals_gallery_id"=>"1"}
[1m[36mOriginalsGallery Load (0.0ms)[0m [1mSELECT "originals_galleries".* FROM "originals_galleries" WHERE "originals_galleries"."id" = ? LIMIT 1[0m [["id", "1"]]
Artwork should be valid: false
Errors: ["Image can't be blank"]
Any thoughts, please? Is there a controller param I'm forgetting to set?
My problem was a more general one: during my tests (with Rspec and FactoryGirl) I was passing in the wrong kind of file object to the controller action. This is the kind of object I was defining for my image attribute:
FactoryGirl.define do
factory :artwork do
image { File.open(File.join(Rails.root, 'spec', 'support', 'sample.gif')) }
...other attributes omitted
end
end
The above is the setup that Carrierwave docs recommended for FactoryGirl test fixtures. It worked for testing the model and most controller actions, but not for the create action.
My test logs were telling me that my image attribute was blank, despite passing in this File object. After some searching I found out that you could pass in an instance of Rack::Test::UploadedFile (I think that ActionDispatch::Http::UploadedFile is what's submitted through the browser(?)).
So instead of the image
attribute being set to File.open(...)
in the factory, I set it to Rack::Test::UploadedFile.new(Rails.root.join("spec/support/sample.gif"))
. My controller specs passed and the file upload was saved to the database.
I think this helps explain why a lot of people witness successful file uploads in the browser, but not in their tests or validations.
This post about testing file attachments in Rails 3 really helped.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With