Rails file upload (paperclip) on edit
Asked Answered
M

2

20

I made myself a simple rails blogging-type app where I use Paperclip to upload image files.I have everything working fine and dandy. I even have it hooked up to an S3 bucket, etc. Spiffy right?

But I can't figure what to do when EDITING/UPDATING a post. As is stands now, all I have is this field on my form template:

= f.file_field :image

So, say on "post/5/edit" even if there's a previously attached image, the field displays "No file chosen".

Even worse, there's no apparent way to clear out current image if I change my mind and don't want to attach an image.

How do I make this a little more user-friendly and make sure the current image -- text/url is fine -- shows up as the value in the text field and/or the user can change the current image to none.

Moreover answered 11/3, 2014 at 2:19 Comment(0)
O
22

For Rails3 here's what I do. Sorry, I haven't used Rails4 yet.

To display to the user if they have already uploaded a file, do this in your view:

<% if @blog.image.exists? %>
  <%= image_tag @blog.image.url(:thumb) %><br/>
<% end %>
<%= f.file_field :image %>

Then, to allow for the user to remove the current upload add this to your view (inside that if block):

<%= f.check_box :delete_image %>Delete Image<br/>

And you handle that checkbox in your model:

  before_validation { image.clear if @delete_image }

  def delete_image
    @delete_image ||= false
  end

  def delete_image=(value)
    @delete_image  = !value.to_i.zero?
  end

That way if the user sets the checkbox it will clear the image on the next save.

Ofelia answered 11/3, 2014 at 2:34 Comment(4)
Please, can you explain: how did "delete_image" methods were called in your code?!Uninstructed
The checkbox will set a property called :delete_image. It can be called anything you want. When you've uploaded the form, Rails will set that property in the model (that is the delete_image setter above). So, if you are deleting that will set a instance variable called @delete_image (again any name you want). Finally, when it's about to save an entry it will call the before_validation block which I have set to clear out the image if the flag is set. Then Rails will save the record. I can't recall where I read the example of the above, but I've used this pattern a lot.Ofelia
That worked. It took me a while to figure out I needed to add :delete_image to my posts controller e.g. params.require(:post).permit(:text, :image, :title, :user_id, :delete_image)Moreover
Is there a way to allow users to delete the uploaded file in the edit view without reloading the page?Zedekiah
G
0

The above method didn't work for me with multiple fields.

I'm used javascript to do this as I am also using cocoon to dynamically add multiple images, on the edit form I am displaying all images with their own delete buttons. I then count the number of image objects and hide that same amount of image file upload boxes. I currently have it set for multiple but with just a little change it could work for your case. After delete, they are redirected back where in your case, count would be 0 and it would show the upload box.

This is the nested form section

<h3 class="text-muted">Upload Images</h3>
<% @rental.property_photos.each do |i| %>
    <div class="pic">
        <%= image_tag i.avatar.url(:thumb), class:"img-responsive property-images" %>
        <%= link_to i, method: :delete, data: { confirm: 'Are you sure?' } do %>
        <i class="fa fa-times-circle delete-pic"></i>
        <% end %>
    </div>
<% end %>
<fieldset id="property_photos">
    <%= f.fields_for :property_photos do |p| %>
    <%= render 'property_photo_fields', :f => p %>
    <% end %>
</fieldset>
<div class="links">
    <%= link_to_add_association 'Add Image', f, :property_photos, class:"fa fa-plus margin-bottom-20" %>
</div>

My nested form

<div class="nested_fields">
    <div class="col-md-3 picUploader">
         <%= f.file_field :avatar %>
    </div>
</div>

My javascript

$(document).ready(function () {

     var count = $('.pic').length;

     function hideElements(x) {
         $('.picUploader').slice(0,x).hide();
     }

     hideElements(count);

})

with a little css your results then look like this... enter image description here

Gadgetry answered 28/8, 2016 at 19:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.