Search code examples
paperclipactiveadminformtastic

How to call an `f.action` to a custom :delete callback in an Active Admin form


In order to remove (paperclip) images from my objects, I have a custom callback (and route) defined:

ActiveAdmin.register Camping do
  #...
  member_action :destroy_image, :method => :delete do
    camping = Camping.find(params[:id])
    camping.image.destroy
    redirect_to({:action => :show}, :notice => "Image deleted")
  end
end

This works as expected; trough a named route destroy_image_admin_camping => /admin/campings/:id/destroy_image.

The problem is that I cannot find how to add this to the form:

ActiveAdmin.register Camping do
  form do |f|
    f.inputs "Camping" do
      f.input :name
      f.input :image
      f.action :delete_image, :url => destroy_image_admin_camping_path(@camping.id), :button_html => { :method => :delete }
      f.input :description
    end

    f.actions
  end
  #...
 end

More detailed: I don't know how to pass the "id of the current item we are editing" into destroy_image_admin_camping_path; @camping is nil, f.camping not defined and so I don't know how to pass the item in there.

Is this the right approach? I prefer this "ajax-ish" interface over a more common checkbox-that-deletes-images-on-update, but I am not sure if this will work at all.


Solution

  • There's a few questions here, I'll try to address them all.

    How to access the "id of the current item we are editing"

    You are pretty close in looking for f.camping. What you want is f.object, so:

    destroy_image_admin_camping_path(f.object.id).

    NOTE: f.object.id will be nil when it's a new form (as opposed to an edit form), you'll want to check for that with unless f.object.new_record?

    "Is this the right approach?"

    I'm not sure, really. To me it seems like making requests without actually saving the currently rendered form could create complications, but it might turn out to be a better interface. Anyway, if you want to do the checkbox-that-deletes-images-on-update, this should help you out: Rails Paperclip how to delete attachment?.

    However, if you want the ajax-ish approach I think you'll want an <a> tag styled as a button. The problem with actually using a button is that you don't want to submit the form.

    Here's an example:

    f.inputs do
      link_to 'Delete Image', delete_image_admin_camping_path(f.object.id), class: 'button', remote: true, method: :delete
    end
    

    remote: true will make it an ajax request and ActiveAdmin gives you a pretty reasonable button class for <a> tags. Updating the interface based on success / failure is left as an exercise to the reader.

    Also, you'll probably want to use erb templates for this instead of the Active Admin DSL (see http://activeadmin.info/docs/5-forms.html at the bottom).

    Like this:

    # app/views/admin/campings/_form.html.erb
    
    <%= semantic_form_for [:admin, @post] do |f| %>
      <%= f.inputs do %>
        <%= f.input :name %>
        <%= f.input :image %>
        <%# Actually, you might want to check for presence of the image, I don't know Paperclip well enough to demonstrate that though %>
        <% unless f.object.new_record? %>
          <%= image_tag f.object.image_url %>
          <%= link_to 'Delete Image', delete_image_admin_camping_path(f.object.id), class: 'button', remote: true, method: :delete %>
        <% end %>
    
        ...
    
      <% end %>
    
      <%= f.actions %>
    <% end %>