Adding :multipart => true throws Undefined Method “name” error-Collection of common programming errors

I’m drawing a blank on this one. Here’s my problem:

Short Version

My image#create action is failing on the image.save call and throwing Undefined method "name" for nil:NilClass. The Image model includes a file upload via paperclip gem.

The part that is throwing me:

the error only occurs when I include :multipart => true on the submitting form

When I take that out, the form works perfectly, except of course the image file doesn’t get uploaded. See the stack trace below for details on where it fails. It looks like its hitting a nil value when trying to quote something for the INSERT statement, but I can’t figure out what. My controller parameters look ok, and I checked via the logger to make sure the new Image instance is properly built just before it hits the save call.

Extra Details

I’ll try to include all the details I can think of, ordered by importance:

  • I’m using paperclip and attempting to store via S3, although this problem still occurs when I completely comment out the has_attached_file line in my Image model.

  • Image is a nested resource inside Collection, which is referenced by a slug in its to_param method.

  • I have the basics of a multi-tenant system (aka Basecamp-style user subdomains, implemented via a central user model that scopes all the components).

Parameters passed to controller

{"utf8"=>"✓",
 "authenticity_token"=>"JYCMky7851j5cW4ChSWUCCL/02iePf6i/QWAgR8q5tE=",
 "image"=>{"name"=>"My testerific image 2",
 "slug"=>"my-testerific-image-2",
 "description"=>"w",
 "collection_id"=>"2",
 "sort"=>"3",
 "picture_file_name"=>#', 
        #   :full => '800x800>' 
        #},
        :storage => :s3,
        :s3_credentials => Rails.root.join( 'config', 's3.yml' ),
        :path => ":id/:style/:filename"


  def to_param
    self.name.parameterize
  end
  private
  def create_slug
    self.slug = self.to_param
  end
end

I compared the Image instance that was built with :multipart => true vs without it, and confirmed the only difference is the file upload field, picture_file_name. Without :multipart => true, it a string with the filename (not surprising). With it, it is an instance of ActionDispatch::Http::UploadedFile. Given that the stack trace shows its failing during a to_yaml call, perhaps the problem lies with the UploadedFile instance converting to YAML?

  1. Well, I finally buckled down and traced my way through the ActiveRecord source code via logger outputs. Turns out, as I suspected, it was failing to save the UploadedFile because it couldn’t convert it to YAML.

    However, this because of a stupid mistake on my part. In my submitting form, I had:

    
    

    When it should have been:

    
    

    The paperclip gem understands that :picture is the uploaded file and works the background magic to save the file name to the proper field. I just underestimated the ease of use I guess!

    Normally, I would delete the question for something this trivial, but seeing as I made this mistake, others probably will in the future, and there was very little out there to point me to the solution. So I will keep it up to aid in the future googling of similarly dense developers!

  2. After lot of searching and debugging. The main symptom of this problem is that form with a file field are being made as multipart form and rails 3.2 is not able to save the data because it is trying to save other parameters that are not present in your database (The filed for the file object).

    Taking the appopriate values and saving them to some variable and removing the file hash from the params has seems to work around the issue!

    Here is an example of a working code to save in the database using rails 3.2

    file = params[:document][:file].tempfile.read
    params[:document].delete(:file)
    @document = Document.new(params[:document])   
    respond_to do |format|
      if @document.save
    @document.file = file
    @document.save
        format.html { redirect_to @document, notice: 'Document was successfully created.' }
        format.json { render json: @document, status: :created, location: @document }
      else
        format.html { render action: "new" }
        format.json { render json: @document.errors, status: :unprocessable_entity }
      end
    end
    
  3. You didn’t post it, but I think you should go with :html => { :multipart => true } instead of just :multipart => true in your form, like:

    form_for object, :html => { :multipart => true } do |o|
        ...
    
  4. I had spent about a week on the same error, even though I had the correct fields.

    The silliness causing all my headaches was simply the order of tags in the view.

    Caused Error

    NoMethodError in DatenightsController#create undefined methodname' for nil:NilClass:

    
    
    

    Solution for above quoted Error (Just the sequence/order matters a lot here)

    
    
    

    Since the issue took so much of my sweet time I thought it may help you.

Originally posted 2013-11-09 21:42:50.