Question

I have a form in my project for a model Artworks where I am using fields_for for a resource Photo where Artworks has_many :photos.

The Photo model uses paperclip to attach images.

All my forms are AJAX based, meaning the page should never be reloaded, and I shouldn't be using redirect_to anywhere in my controllers (and I'm not).

When I include the fields_for in my form with the paperclip file_field, if I create or update the photo when I submit the form, I get the following error:

Template is missing

Missing template artworks/show, application/show with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in: * "/home/david/rails/piml_artwork/app/views" * "/home/david/.rvm/gems/ruby-1.9.3-p194/gems/devise-2.1.2/app/views"

The destroy image checkbox functions as expected. Updating the rest of the details on the form and submitting it functions as expected, just returning an AJAX response and filling out the page.

My artworks controller is as follows:

  class ArtworksController < ApplicationController
    before_filter :load

    authorize_resource

    respond_to :html, :json, :js

    def load
    end

    def show
      @artwork = Artwork.find(params[:id])
    end

    def index
      @artworks = Artwork.all
    end

    def new
      @artwork = Artwork.new
      @artwork.photos.build unless @artwork.photos.count > 0
    end

    def create
      @artwork = Artwork.new(params[:artwork])
      if @artwork.save
        flash[:notice] = "Artwork saved"
        @artworks = Artwork.all
        respond_with @artwork
      end
    end

    def edit
      @artwork = Artwork.find(params[:id])
      @artwork.photos.build unless @artwork.photos.count > 0
    end

    def update
      @artwork = Artwork.find(params[:id])
      if @artwork.update_attributes(params[:artwork])
        flash[:notice] = "Artwork updated"
        @artworks = Artwork.all
        respond_with @artwork
      end
    end

    def destroy
      @artwork = Artwork.find(params[:id])
      @artwork.destroy
      flash[:notice] = "Artwork destroyed"
      @artworks = Artwork.all
    end
  end

The form causing the strife is this:

<%= form_for( @artwork, remote: true, mutlipart: true ) do |f| %>
    <%= render 'layouts/error_messages', object: f.object %>
    <div id="artwork-title">TITLE: <%= f.text_field :title %></div>
    <div id="artwork-title-underline"></div>
    <div id="artwork-show-picture"><%= image_tag @artwork.photos.first.photo.url(:medium) unless @artwork.photos.first.new_record? %>
        <div id="artwork-picture-upload">
            <%= f.fields_for :photos, remote: true, multipart: true do |p| %>
                <% if p.object.new_record? %>
                    UPLOAD PHOTO
                    <%= p.file_field :photo, value: 'Upload Image' %>
                <% else %>
                    REPLACE PHOTO
                    <%= p.file_field :photo, value: 'Replace Image' %>
                    <br />
                    <br />
                    <%= p.check_box :_destroy %>
                    <%= p.label :_destroy, 'Delete Image' %>
                <% end %>
            <% end %> 
        </div>
    </div>
    <div id="artwork-public">
        ARTIST<br />
        <%= f.select :artist_id, Artist.select_list, include_blank: "SELECT ARTIST" %><br />
        <br />
        DATE OF WORK <br />
        <%= f.text_field :date_of_work %><br />
        <br />
    <div id="artwork-modify-buttons">
        <%= f.submit %>
    </div>
<% end %>

My JS file for update is:

    <% if !@artwork.errors.any? %>
      $("#facebox .content").html("<%= escape_javascript(render(partial: "/artworks/show")) %>");
      $("#artworks-col").html(" <%= escape_javascript(render(partial: "/admin/artworks_list" )) %>")
    <% else %>
      $("#facebox .content").html("<%= escape_javascript(render(partial: "/artworks/form")) %>");
    <% end %>
Was it helpful?

Solution

As it turns out, the issue I was having is that by design, you cannot upload files through AJAX.

After a few days of toiling with this, I found a gem that fixes it all incredibly easily; Remotipart

The entirety of what I had to do to fix it was:

  • Add remotipart to my gem file gem 'remotipart'
  • Add //= require jquery.remotipart to my app/assets/javascripts/application.js file
  • bundle install

That fixed it. Images are now uploading with what 'looks like' AJAX, but is actually using an iframe to do the work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top