So, I have a user model with a login, email address, password, password confirmation, name, avatar (picture), etc. There are validations on the first 5, mainly because all 5 must exist in order to create a new model.
However, this causes problems for me when updates happen.
I have an edit page where the user can edit only his name and avatar. Currently, I am not going to change their username, and I want to change the email address and password from another page.
So, the editing form looks like this:
<% form_for @user, :html => { :multipart => true } do |u| %> <p> <label>Name:</label> <%= u.text_field :name %> </p> <p> <label>Avatar:</label> <%= display_user_avatar %> <%= u.file_field :avatar%> </p> <p> <%= submit_tag %> </p> <% end %>
If I try to execute @user.update_attributes(params[:user]) , then since only 2 parameters are name and avatar , the update does not work, because things like password, password confirmation, email, etc. are required to verify the record. d. and they simply do not exist in this form.
I can get around this by doing @user.update_attribute(:name, params[:user][:name]) , but then I worry about whether to avoid checking if this is Good Thing β’ or not. Especially in relation to something like password updates where I need to check the new password.
Is there another way?
And if I were to do this, simply using update_attribute for :name and :avatar , how would I do it?
Will this work?
params[:user].each do |attribute| @user.update_attribute(attribute, params[:user][attribute]) end
Is this an acceptable way to do this ...?
- edit as a continuation -Okie, I tried, as you suggested, and did
def update @user = User.find_by_login(params[:id]) if @user.update_attributes!(params[:user]) redirect_to edit_user_path(@user) else flash[:notice] = @user.errors redirect_to edit_user_path(@user) end end
So this makes the version ! , and the exception caught and displayed in the browser:
Validation failed: Password is too short (minimum is 5 characters)
Information in the server log:
Processing UsersController#update (for 127.0.0.1 at 2010-07-18 11:56:59) [PUT] Parameters: {"user"=>{"name"=>"testeeeeee"}, "commit"=>"Save changes", "action"=>"update", "_method"=>"put", "authenticity_token"=>"BMEGRW/pmIJVs1zlVH2TtZX2TQW8soeCXmMx4kquzMA=", "id"=>"tester", "controller"=>"users"}
Urm. Looking at this, I just realized that it was sending "id"=>"tester" . Now I have my routes installed, so it shows the username for users, not user_id ... Maybe that's why? It tries to find the user update with user_id == tester , but since it does not exist, is it trying to create it instead? Is this really what I am doing wrong due to the route?
Hmmm ... rake routes tells me that the route:
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"} PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
And I set this route in user.rb file:
def to_param "
but it definitely displayed login instead of id all this time. But I also do it right at the beginning of the update action, @user = User.find_by_login(params[:id]) , and then update this @user .
I am very confused ..> & L;
Second update:My user.rb stuff is as follows:
validates_length_of :login, :within => 3..20 validates_length_of :password, :within => 5..20 validates_presence_of :login, :email, :password, :password_confirmation, :salt, :name, :on => :create validates_uniqueness_of :login, :case_sensitive => false validates_confirmation_of :password validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[az]{2,})$/i, :message => "format is invalid." attr_accessor :password, :password_confirmation
And the hashed_password section is here:
def password=(pass) @password = pass self.salt = User.random_string(10) if !self.salt? self.hashed_password = User.encrypt(@password, self.salt) end
u.attributes gives me
>> u.attributes => {"salt"=>"NHpH5glxsU", "name"=>"test er", "avatar_updated_at"=>nil, "updated_at"=>Sat Jul 17 07:04:24 UTC 2010, "avatar_file_size"=>nil, "avatar_file_name"=>nil, "hashed_password"=>"84f8675c1ed43ef7f8645a375ea9f867c9a25c83", "id"=>1, "avatar_content_type"=>nil, "login"=>"tester", "email"=>"tester@tester.com", "created_at"=>Fri May 07 10:09:37 UTC 2010}
Urmmm ... Okay, so you said that the virtual password attribute does not actually exist ... So, how do I get around this? Bugger, here I thought I was smartly driving my own authentication code ...
How easy is it to change one of these authentication plugins? Do I need to create a new user model? Or can the plugin work with my current one?
Thanks for all the help so far, by the way !: D