7
votes

I have a rails app which originally used Paperclip for file uploads, however, as I saw that CarrierWave apparently had a 'persistant upload' type feature over form redisplays, I decided to give that a try.

In my view I have the following:

= f.input :attachment
= f.hidden_field :attachment_cache

Which correctly caches the file if the form fails validation and is redisplayed, however when I correct the validation errors and resubmit, the attachment is not processed.

Started POST "/section/model" for 127.0.0.1 at 2012-03-20 08:51:56 +0000
  Processing by Client::WishesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"zkdPQBsAnsNzx555rkwZ5+clfnLaXg+NtL+GdFei188=", "model"=>{"title"=>"Sample", "content"=>"Sample content", "contact_name"=>"Mr Sample", "contact_email"=>"[email protected]", "attachment_cache"=>"20120320-0851-42559-1644/SampleAttachment.pdf"}, "commit"=>"Create Wish"}
  Client Load (0.3ms)  SELECT `clients`.* FROM `clients` WHERE `clients`.`id` = 1 LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.4ms)  INSERT INTO `models` (`attachment`, `client_id`, `contact_email`, `contact_name`, `content`, `created_at`, `status`, `title`, `updated_at`, `upload_content_type`, `upload_file_name`, `upload_file_size`, `upload_updated_at`) VALUES (NULL, 1, '[email protected]', 'Mr Sample', 'Sample content', '2012-03-20 08:51:56', 'Unresolved', 'Sample', '2012-03-20 08:51:56', NULL, NULL, NULL, NULL)

It appears to be correctly passing the attachment via the attachment_cache in the params, but it isn't then saving the attachment as it doesn't have a params[:model][:attachment] field.

It doesn't say any further steps on the carrierwave section for making uploads work across form redisplays on the CarrierWave GitHub.

6
It works if I create/update with mass-assignment, and set the separate variables, but I was wondering if there was a way to do it without mass-assignment?HaaR
Consider opening a ticket for this.Nash Bridges
did you find an answer for this?user749798
You also have to add the field name to strong paramterBernie Chiu

6 Answers

3
votes

It's a bit of an old question, but it worked for me after I added the strong parameter to the controller, like this:

#controller
def object_params
  params.require(:object).permit(:attachment, :attachment_cache)
end

#view
<%= f.file_field :attachment %>
<%= f.hidden_field :attachment_cache %>
2
votes

Try populating the value of avatar_cache so that when validation fails, it will be pre-populated in the form:

= f.hidden_field :attachment_cache, :value => @model.attachment_cache

Where @model is the name of your model

This seems to work for me when the same form is reloaded multiple times (i.e. when validation fails multiple times). I think they left this out of the documentation.

2
votes

This will solve your issue 100%

Please have a look at

accepts_nested_attributes_for :avatars, allow_destroy: true, 
 reject_if: lambda { |avatar| avatar[:avatar].blank? and avatar[:avatar_cache].blank?}

Here we will reject avatar when both avatar[:avatar] and avatar[:avatar_cache] are blank

0
votes

The cause is the 'changed?' check, when validation error, we pass the cached file in #{model}_cache field which is not a database table column, so it doesn't save the object because nothing is changed in the AR's point of view.

I did a hack to make this work by creating a method in the model that containing the file: "data" is the the column name

def data_cache=(text)
  @changed_attributes.merge!("data" => nil)
  super
end

Hope this helps.

0
votes

For me, the issue was that I had

accepts_nested_attributes_for :avatars, allow_destroy: true, reject_if: lambda { |avatar| avatar[:file].blank? }

So I was rejecting the file because the file wasn't there

It is important to note that the file itself does not persist, but just the file cache. That is why the carrierwave docs suggest:

It might be a good idea to show the user that a file has been uploaded, in the case of images, a small thumbnail would be a good indicator:

0
votes

To add on to @marko's answer:

If you are using Active Admin, you'll need to add the cached file to the permit_params line.

permit_params: :title, :file, :file_cache