3

I've recently installed the paperclip gem to my Rails 3 app. I am trying to allow users to upload an avatar to their profile. I followed the install instructions and here is what my models/views look like:

My 'user.rb' model has the following code:

has_attached_file :avatar, 
                  :styles => { :small => "70x70>"},
                  :url  => "/users/:attachment/:id/:style/:basename.:extension",
                  :path => ":rails_root/public/users/:attachment/:id/:style/:basename.:extension"

validates_attachment_size :avatar, :less_than => 1.megabytes
validates_attachment_content_type :avatar, :content_type => ['image/jpeg', 'image/png']

I have added the following to the edit form html (I'm using HAML btw):

= form_for (@user || User.new), :html => { :multipart => true } do |f|
...
.profile_picture.text_field
  = image_tag current_profile.avatar.url(:small)
  %br
  = f.file_field :avatar

When I upload a picture (jpeg or png) that is under 1mb everything works smoothly; the image is uploaded, and there are no errors. If I try to upload any other type of file (MP3, txt, whatever) or the file/image is greater than 1mb rails gives me the following error:

TypeError in UsersController#update

can't dump File

Request

Parameters:

{"utf8"=>"✓",
 "_method"=>"put",
 "authenticity_token"=>"LaiYjEEfgsE8JzzLsfkzk6TK8D4uxzIo5ASlu6ax2rY=",
 "user"=>{"avatar"=>#<ActionDispatch::Http::UploadedFile:0x000001053f0bf0 @original_filename="GT1_22HS_1_std.jpg",
 @content_type="image/jpeg",
 @headers="Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"GT1_22HS_1_std.jpg\"\r\nContent-Type: image/jpeg\r\n",
 @tempfile=#<File:/var/folders/Ud/Udv4OlryEzWrHedR8pIe1E+++TI/-Tmp-/RackMultipart20110817-17075-1ikqcc0>>,
 "first_name"=>"First",
 "last_name"=>"Last",
 "country"=>"United States",
 "state"=>"California",
 "city"=>"City",
 "date_of_birth(1i)"=>"2011",
 "date_of_birth(2i)"=>"7",
 "date_of_birth(3i)"=>"12",
 "account_attributes"=>{"email"=>"email@email.com",
 "id"=>"6",
 "password"=>"[FILTERED]",
 "password_confirmation"=>"[FILTERED]"},
 "commit"=>"Save & Continue",
 "id"=>"2"}

I apologize if all of that was not required, but the error is a little non-descriptive, so I figured it's better to post in just in case.

I would like to know what I'm doing wrong with my validations that errors are not being generated, and the application is breaking. Any help on this matter would be greatly appreciated. I sincerely thank everyone who took the time to read this, and I kindly appreciate any help! Thanks!

UPDATE:

update method form user_controller.rb:

  def update
    session[:user_params] ||= {}
    session[:user_params].deep_merge!(params[:user]) if params[:user].present?

    @user.attributes = session[:user_params]

    respond_to do |format|
      if @user.save
        session[:user_params] = nil
        sign_in(@user.account, :bypass => true)
        format.html { redirect_to(root_url, :notice => 'User was successfully updated.') }
        format.xml  { render :xml => @user, :status => :created, :location => @user }
      else
        format.html { render :action => "edit", :layout => "userhome" }
        format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
      end
    end
  end
slovak_100
  • 782
  • 2
  • 10
  • 33
  • It should work, are you using the latest version of Paperclip? (2.3.16 at the moment) – Joost Baaij Aug 17 '11 at 08:13
  • yes I am... is it possible that it simply not functioning on localhost but once deployed it'll work? – slovak_100 Aug 17 '11 at 14:21
  • Yes it's possible. If you're using the (built-in) WebRick server it might cut off larger files unexpectedly. Try using passenger or thin and see if that helps, as these two are often used in production. To install and use passenger in development: "gem install passenger" and then "passenger start". It will use the same http://localhost:3000/ address. – Joost Baaij Aug 17 '11 at 21:27
  • that did not seem to do the trick... i deployed it and it would still display errors if the uploaded file falls outside of validations. – slovak_100 Aug 19 '11 at 18:16

3 Answers3

2

can't dump File is the error Ruby raises when it is asked to dump a File object using Marshal.dump.

Marshal.dump(File.new(".gemrc")) # => TypeError: can't dump File

So the problem lies probably in what you do when the validation fails. If you're putting the params (which contains a File object) in the session or the flash objects (which are dumped by Rails), this is your problem.

Trip
  • 26,756
  • 46
  • 158
  • 277
Michaël Witrant
  • 7,525
  • 40
  • 44
  • I suspect that this might indeed be the case. How can I check if i'm putting the params in the session? Sorry, I know this is probably a pretty basic question, but I'm pretty new to ror, so I apologize in advance. – slovak_100 Aug 21 '11 at 23:35
  • Can you add to your question the code of the `update` method of your `UsersController`? – Michaël Witrant Aug 22 '11 at 08:06
  • @ Michael, thanks you so much for your help thus far. I apologize for the late response. I've attache the update method for user_controller. Please let me know if there is anything else that you may need. – slovak_100 Aug 25 '11 at 18:51
  • This command puts the File in the session: `session[:user_params].deep_merge!(params[:user])`. It's reset if the model is valid, that's why it doesn't happen in this case. I don't know why you're doing this merge, but you should avoid it. – Michaël Witrant Aug 26 '11 at 09:58
0

The problem in my case that clearing out the paperclip attachment with Attachment#clear was not enough because it still wanted to save some File.

I've found out that the problem was with the @queued_for_write attribute in Attachment which still contained the data.

So the following two lines solved my problem:

unless @model.valid?
  @model.image.clear
  @model.image.queued_for_write.clear
end

This was a paperclip bug and was corrected in this commit.

KARASZI István
  • 30,900
  • 8
  • 101
  • 128
-1

Did you try

@user.attachment.destroy

before assigning @user.errors in your response?

ZX12R
  • 4,760
  • 8
  • 38
  • 53