Paperclip & Rails 4

I have recently upgraded an app I’m building to Rails 4, and am having an issue with Paperclip saving files to the db. I’d be super appreciative of any help here, as I’ve been running round in circles for a couple of hours now : )

I have an attached file on a model (PurchaseListingOffer model) that is nested within another model, the PurchaseListing model. The form includes a bunch of other attributes, so I have stripped these out from the code details below to keep things clean… I believe all of the relevant parts of my app are included below:

Gemfile:

gem "paperclip", :git => 'git://github.com/thoughtbot/paperclip.git', :branch => 'rails-4'

PurchaseListingOfferModel

       class PurchaseListingOffer < ActiveRecord::Base
         has_attached_file :ploffer_proposal
         validates_attachment :ploffer_proposal, :size => { less_than: 4.megabytes }
       end

PurchaseListingOffer#new View

<%= form_for([@purchase_listing, @purchase_listing_offer]) do |f| %>
.
.
<%= f.file_field :ploffer_proposal %>

The form element is correctly showing:

enctype="multipart/form-data"

I am using Strong Parameters, in conjunction with CanCan. The relevant parts of my PurchaseListingOffer controller looks like the following…

   PurchaseListingOffersController < Application Controller
      before_action :load_purchase_listing, except: :index
      before_action :new_purchase_listing_offer, only: :create
      load_and_authorize_resource
    
      def new
        @purchase_listing_offer = @purchase_listing.purchase_listing_offers.build
      end

  def create
    @purchase_listing_offer.publisher_id = current_user.id
    if @purchase_listing_offer.save
      PurchaserMailer.new_offer_on_listing(@purchase_listing_offer, @purchase_listing_offer.purchase_listing.purchaser, @purchase_listing_offer.publisher).deliver
      flash[:success] = "Your Proposal has been successfuly created!"
      redirect_to purchase_listing_purchase_listing_offer_path(@purchase_listing_offer.purchase_listing, @purchase_listing_offer)
    else
      gon.purchase_listing_offer = @purchase_listing_offer
      render 'new'
    end
  end
    
      private
    
        def load_purchase_listing
          @purchase_listing = PurchaseListing.find(params[:purchase_listing_id])
        end
    
        def new_purchase_listing_offer
          @purchase_listing_offer = @purchase_listing.purchase_listing_offers.create(purchase_listing_offer_params)
        end

Discourse has been having a fit and displaying the above code segment in a bizarre fashion, so I’ve had to move the strong parameters params method after this paragraph…

  def purchase_listing_offer_params
      params.require(:purchase_listing_offer).permit( *....other params....*,  :ploffer_proposal => [:ploffer_proposal_file_name, :ploffer_proposal_content_type, :ploffer_proposal_file_size, :ploffer_proposal_updated_at])
    end

In the controller I am creating a new PurchaseListingOffer in a before filter because CanCan will automatically go ahead and create an object in each restful action, unless you explicitly override this behaviour by creating an object prior to calling load_and_authorize_resource. In this case, CanCan would create a PurchaseListingOffer object and not build it correctly through the PurchaseListing association, and it therefore has to be overridden.

The permitted params I changed from ( :ploffer_proposal ), to ( :ploffer_proposal => ) , as I was getting an error ‘wrong number of arguments (2 for 1)’. Changing the params in this fashion fixed this error.

When I submit the form, the params hash includes the details of the attached file, as shown here:

Started POST "/purchase_listings/3/purchase_listing_offers" for 127.0.0.1 at 2013-08-03 15:28:32 -0700
Processing by PurchaseListingOffersController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"qAhQAu+tlEqdxWURJr4S+Hrdph1QC6RZYV1imAEl7TU=", "purchase_listing_offer"=>{"....other params here....* "ploffer_proposal"=>#<ActionDispatch::Http::UploadedFile:0x007fbbde8f2a68 @tempfile=#<Tempfile:/var/folders/1m/t1tfqrj94z31ksvyrwntbjfh0000gn/T/RackMultipart20130803-5859-dglyh9>, @original_filename="2371949.pdf", @content_type="application/pdf", @headers="Content-Disposition: form-data; name=\"purchase_listing_offer[ploffer_proposal]\"; filename=\"2371949.pdf\"\r\nContent-Type: application/pdf\r\n">}, "commit"=>"Submit your Listing !", "purchase_listing_id"=>"3"}

The SQL returned does not include any of the file attachment details:

SQL (0.9ms)  INSERT INTO "purchase_listing_offers" ("..other attributes here...*)
[paperclip] Saving attachments.

I cannot remember if the SQL ever included these details, so I’m not sure if this is correct or incorrect behaviour. After this, no file attachment is saved to the db, all of the fields are blank. The create action runs its course, and renders the show action of the newly created PurchaseListingOffer resource. I’m running pg locally and in production. Prior to upgrading to Rails 4, uploads were working correctly both locally and in production. The only changes I have made to the application, with respect to Paperclip, are the following:

  • Use the rails-4 branch of the git repo.
  • Edit the permitted params from ( :ploffer_proposal ) , to ( :ploffer_proposal => ). Here I have tried entering the four file attributes into the array, and leaving the array empty. I have the same result in both situations.

Please let me know if I can clarify anything else… and I will be very grateful for any ideas or thoughts on what is going on : )

thanks, and happy Saturday,

Ash