4
votes

I am new in Rails and web development...

I have created a User model, and I am now trying to give the user the ability to add a profile picture, using Paperclip.

From my user show page, a user can click on a link to open an 'edit' page, from which he can see a form to browse and choose an image to upload. When clicking on the button, it calls the 'update' action and redirect to the user show page, but the image is not saved in any folder, and the image attributes (filename, contenttype, filesize) are still set to NIL in the database.

  • I have installed and tested ImageMagick
  • I have added the :multipart => true in the form
  • I have put attr_accessible :avatar
  • I have set the paperclip options to look for '/usr/bin/' where convert is located
  • I have run the migration
  • I have set :url and :path

-in the controller, my update action is:

def update
  @user = User.find(params[:id])
  @title = "Update profile picture"
  response_to do |format|
  if @user.update_attributes(params[:user])
    format.html {redirect_to(@user, :notice => 'Profile picture loaded')}
  else
    format.html {render :action => "edit", :notice => 'Unable to load pic")}
  end
  end
 end

My model code is:

class User < ActiveRecord::Base
  attr_accessor :password
  attr_accessible :name, :email, :number_of_positive_reco, :confidence_percent, :password,
                  :password_confirmation, :avatar, :avatar_file_name, :avatar_content_file, :avatar_file_size

  has_attached_file :avatar , :styles => { :medium => "300x300>", :thumb => "100x100>"},
                    :url => "/images/profiles/:attachment/:id_:style.:extension",
                    :path => ":rails_root/public/images/profiles/:attachment/:id_:style.:extension"
                   # :default_url => "/images/Default_profile_picture.png"

  email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name, :presence => true,
  :length => { :maximum => 20}
  validates :email, :presence => true,
  :format => { :with => email_regex},
  :uniqueness => {:case_sensitive => false}
  validates :password, :presence => true,
  :confirmation => true,
  :length => { :within => 6..40 }
  validates :number_of_positive_reco, :numericality => {:only_integer => true, :greater_than_or_equal_to => 0}
  validates :confidence_percent, :numericality => { :greater_than_or_equal_to => 0.0, :less_than_or_equal_to => 1.0}

  before_save :encrypt_password
  # Return true if the user's password matches the submitted password.
  def has_password?(submitted_password)
    encrypted_password == encrypt(submitted_password)
  end

  def self.authenticate(email, submitted_password)
    user = find_by_email(email)
    return nil if user.nil?
    return user if user.has_password?(submitted_password)
  end

  def self.authenticate_with_salt(id, cookie_salt)
    user = find_by_id(id)
    (user && user.salt == cookie_salt) ? user : nil
  end

  private

  def encrypt_password
    self.salt = make_salt if new_record?
    self.encrypted_password = encrypt(password)
  end

  def encrypt(string)
    secure_hash("#{salt}--#{string}")
  end

  def make_salt
    secure_hash("#{Time.now.utc}--#{password}")
  end

  def secure_hash(string)
    Digest::SHA2.hexdigest(string)
  end

end

The form is located in edit.html.erb:

<h1>
    Ajouter une photo au profil
</h1>

<%= form_for @user, :html => { :multipart => true} do |f| %>
<div class="field">  
  <%= f.label :avatar, "Upload ta photo" %>
  <br />
  <%= f.file_field :avatar %>
</div>

<div class="actions">
    <%= f.submit "Upload" %>
</div>
<% end %>

And I printed the debug information into the browser. After clicking Upload, I got this:

{"commit"=>"Upload", "authenticity_token"=>"+ExcuQOSv1bxIyAoM5+N4TCSmYI8JYeh5Yb8P5W4VU0=", "_method"=>"put", "utf8"=>"โœ“", "action"=>"update", "id"=>"8", "controller"=>"users", "user"=>{"avatar"=>#<ActionDispatch::Http::UploadedFile:0xb6d63fec @content_type="image/jpeg", @original_filename="Paperclip-Railway.jpg", @tempfile=#<File:/tmp/RackMultipart20111208-1681-3h3ps4-0>, @headers="Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"Paperclip-Railway.jpg\"\r\nContent-Type: image/jpeg\r\n">}}

So, in the log, I see that the 'paperclip's fields' are filled with image name, image type, etc...but there is no "INSERT into TABLE", all the user fields are still NIL, the system directory where user's image should be stored is not created, there is no "Paperclip attachment save", nor any mention of paperclip in the log...

In console mode, I can create a new user, setting the avatar attributes as :

`User.create(:avatar => File.new(Rails.root + "public/images/an_image.png")ยด

and it works just fine! ... I also tested the creation of a new folder, without admin rights, and it works all fine ... I am desesperate :-(

Can anyone help me ?

1
Could you post your model code? โ€“ ramblex
@ramblex : posted model, form and debug info above. Thanks for answering ! โ€“ citraL

1 Answers

2
votes

3 days to find this out: as I used password protection (password being attr_accessor), it's impossible to update a user, without adding the password field in the form.

Trying to edit the profile picture without entering the password does not work, and no error message that could have me made me think about this was generated.

So, in the edit view, don't forget to add the password field in the form to be able to update user's picture!