hello, i am writing a simple user login system. when registering a user account, i have two field: password password_confirmation which are validated using validates_presence_of validates_confirmation_of and these are then used to generate a password hash which is stored in my database when i want to update the record (without changing the password and entering new values for password and password_confirmation), using the update_attributes method, i am getting errors thrown up by this validation. i want to be able to update the record, even if the user does not specify a new password thanks -- Posted via http://www.ruby-forum.com/.
maybe my post wasn''t too clear. basically, what i am after is a way of selectively validating certain fields of the model, i.e. when creating a new object and saving it to the database, i want to validate the presence of username, password and password_confirmation, and validate confirmation of password but, when updating the user''s profile (name, address etc) i want to ignore the password validation (i''ll have a seperare form for changing password) hope that''s clearer -- Posted via http://www.ruby-forum.com/.
Jon Hewer wrote:> maybe my post wasn''t too clear. > > basically, what i am after is a way of selectively validating certain > fields of the model, i.e. > > when creating a new object and saving it to the database, i want to > validate the presence of username, password and password_confirmation, > and validate confirmation of password > > but, when updating the user''s profile (name, address etc) i want to > ignore the password validation (i''ll have a seperare form for changing > password) > > hope that''s clearerCould you post the code that you are trying that throws errors? Post the code where you try to update fields and save the query. Also, post a few segments on the password stuff from the model. -Ben Lisbakken -- Posted via http://www.ruby-forum.com/.
Ben Lisbakken wrote:> Jon Hewer wrote: >> maybe my post wasn''t too clear. >> >> basically, what i am after is a way of selectively validating certain >> fields of the model, i.e. >> >> when creating a new object and saving it to the database, i want to >> validate the presence of username, password and password_confirmation, >> and validate confirmation of password >> >> but, when updating the user''s profile (name, address etc) i want to >> ignore the password validation (i''ll have a seperare form for changing >> password) >> >> hope that''s clearer > > Could you post the code that you are trying that throws errors? > > Post the code where you try to update fields and save the query. Also, > post a few segments on the password stuff from the model. > > -Ben LisbakkenI''m running the same scheme, and here''s how I update the name of a user: @thisUser = User.find_by_id(session[:user_id]) @thisUser[0].name = "new name!!!" @thisUser[0].update() @thisUser[0].save An easier way to do this would be User.update(session[:user_id], {:name => ''new name!!!''}) it shouldn''t throw any errors about passwords, unless you have it rigged so it checks the password each time you try to update the entry. -- Posted via http://www.ruby-forum.com/.
hi ben i have tried your method of updating, and it''s throwing up the password validation problems again. i probably haven''t rigged up the validation correctly for what i am trying to do. here is the relevant code from my user model: class User < ActiveRecord::Base attr_accessor :password, :password_confirmation attr_protected :admin, :enabled, :password_salt, :password_hash validates_uniqueness_of :username validates_presence_of :username, :email, :password, :password_confirmation validates_confirmation_of :password def before_create salt = [Array.new(6){rand(256).chr}.join].pack("m").chomp self.password_salt = salt self.password_hash = User.hash_password(self.password, salt) end def after_create @password = nil @password_confirmation = nil end ... end and then in my user management controller here is the update method: def update @user = User.find(params[:id]) if @user.update_attributes(params[:user]) flash[:notice] = ''User was successfully updated.'' redirect_to :action => ''show'', :id => @user else render :action => ''edit'' end end my understanding of update_attributes was to update and validate only those supplied in params[:user] which afaik comes from my update form, and therefore does not have the password and password_confirmation fields thanks -- Posted via http://www.ruby-forum.com/.
Jon Hewer wrote:> hi ben > > i have tried your method of updating, and it''s throwing up the password > validation problems again. i probably haven''t rigged up the validation > correctly for what i am trying to do. > > here is the relevant code from my user model: > > class User < ActiveRecord::Base > attr_accessor :password, :password_confirmation > attr_protected :admin, :enabled, :password_salt, :password_hash > validates_uniqueness_of :username > validates_presence_of :username, :email, :password, > :password_confirmation > validates_confirmation_of :password > > def before_create > salt = [Array.new(6){rand(256).chr}.join].pack("m").chomp > self.password_salt = salt > self.password_hash = User.hash_password(self.password, salt) > end > > def after_create > @password = nil > @password_confirmation = nil > end > > ... > > end > > and then in my user management controller here is the update method: > > def update > @user = User.find(params[:id]) > if @user.update_attributes(params[:user]) > flash[:notice] = ''User was successfully updated.'' > redirect_to :action => ''show'', :id => @user > else > render :action => ''edit'' > end > end > > my understanding of update_attributes was to update and validate only > those supplied in params[:user] which afaik comes from my update form, > and therefore does not have the password and password_confirmation > fields > > thanksthe first thing that jumps out at me is:> validates_presence_of :username, :email, :password, > :password_confirmationthen you have> def after_create > @password = nil > @password_confirmation = nil > endSo when you create, it validates that there''s a password. After you have created your user with a password, it sets the password to nil. Once you try to update a field, it does the validation methods again, and sure enough validates_presence of :password and :password_confirmation fail. I think that''s what it is - lemme know. -Ben Lisbakken -- Posted via http://www.ruby-forum.com/.
i don''t actually have password and password_confirmation fields in my database, since i''m just storing the hash and salt obviously. so when i load the record from the database using find() given the user id, these are set to nil anyway. the code i am using is based on that given in the ''agile web development with ruby'' book, and it sets the plaintext password to nil to prevent it from being stored in session data (when i get round to that) any suggestions? -- Posted via http://www.ruby-forum.com/.
> def update > @user = User.find(params[:id]) > if @user.update_attributes(params[:user]) > flash[:notice] = ''User was successfully updated.'' > redirect_to :action => ''show'', :id => @user > else > render :action => ''edit'' > end > endchange to: def update def update @user = User.find(params[:id]) add these three lines @user.name = params[:user].name <--- note down below @user.update() if @user.save or this line if User.update(params[:id], {:name => params[:user].name}) Note: that line is assuming your form contains this <%= text_field ''user'', ''name'' %> -Ben Lisbakken -- Posted via http://www.ruby-forum.com/.
Ben Lisbakken wrote:>> def update >> @user = User.find(params[:id]) >> if @user.update_attributes(params[:user]) >> flash[:notice] = ''User was successfully updated.'' >> redirect_to :action => ''show'', :id => @user >> else >> render :action => ''edit'' >> end >> end > > change to: > def update > def update > @user = User.find(params[:id]) > > add these three lines > @user.name = params[:user].name <--- note down below > @user.update() > if @user.save > > or this line > if User.update(params[:id], {:name => params[:user].name}) > > > Note: that line is assuming your form contains this > <%= text_field ''user'', ''name'' %> > > -Ben Lisbakkenthe problem is that you''re using update_attributes vs. update_attribute. update_attribues "Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will fail and false will be returned." that params[:user] you''re passing it obviously only has this field: <%= text_field ''user'', ''name'' %> if it had: <%= text_field ''user'', ''name'' %> <%= text_field ''user'', ''password'' %> <%= text_field ''user'', ''password_confirmation'' %> then that syntax would have been fine, because it would have done update_attribues and it would have passed all of the validates requirements. if you''re delving into agile, you should keep http://api.rubyonrails.com/ handy. it''s important to know how to use it - it can really save you time. I have a copy of it downloaded through Web Devil (for OSX) so I can program and get any syntax help I need without the internet. -- Posted via http://www.ruby-forum.com/.
the problem with update_attribute is that, however, the attribute updated is not subjest to any validation. so, for example, it would be easy to make the mistake of updating the ''username'' to either nil or perhaps another username whihc already exists. i guess what i''m trying to do if update a subset of fields, performing validation on only those fields. thanks -- Posted via http://www.ruby-forum.com/.
Jon Hewer wrote:> the problem with update_attribute is that, however, the attribute > updated is not subjest to any validation. so, for example, it would be > easy to make the mistake of updating the ''username'' to either nil or > perhaps another username whihc already exists. > > i guess what i''m trying to do if update a subset of fields, performing > validation on only those fields. > > thanksthen just use update_attribute not update_attributes - that should be exactly what you need. -- Posted via http://www.ruby-forum.com/.
On 7/18/06, Ben Lisbakken <lisbakke@gmail.com> wrote:> > Jon Hewer wrote: > > the problem with update_attribute is that, however, the attribute > > updated is not subjest to any validation. so, for example, it would be > > easy to make the mistake of updating the ''username'' to either nil or > > perhaps another username whihc already exists. > > > > i guess what i''m trying to do if update a subset of fields, performing > > validation on only those fields. > > > > thanks > > then just use update_attribute not update_attributes - that should be > exactly what you need. > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >You can restrict the validation to occur only on create. That way, when the user is updated it won''t trip the validation trip switch. validate_presence_of :password, :on => :create validates_confirmation_of :password, :on => :create Alternatively, if you need more control use the :if option to point to a proc or a method to test if validation should occur. validate_presence_of :password, :if => Proc.new{ |model| model.something =a_condition } or validate_presence_of :password, :if => :some_method_that_evaluates_to_true_or_false -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060718/3eddab05/attachment.html
Ben Lisbakken wrote:> then just use update_attribute not update_attributes - that should be > exactly what you need.i have tried this, but validation checks are not performed on the attribute being updated. for example i can update the username to either nil or to another existing username -- Posted via http://www.ruby-forum.com/.
Daniel ----- wrote:> You can restrict the validation to occur only on create. That way, when > the > user is updated it won''t trip the validation trip switch. > > validate_presence_of :password, :on => :create > validates_confirmation_of :password, :on => :create > > Alternatively, if you need more control use the :if option to point to a > proc or a method to test if validation should occur. > > validate_presence_of :password, :if => Proc.new{ |model| model.something > => a_condition } > or > validate_presence_of :password, :if => > :some_method_that_evaluates_to_true_or_falseok i''ll give that kinda thing a try. thanks :) -- Posted via http://www.ruby-forum.com/.
Jon Hewer wrote:> when i want to update the record (without changing the password and > entering new values for password and password_confirmation), using the > update_attributes method, i am getting errors thrown up by this > validation.I think adding :on => :create to the end of your validates_* lines will restrict the validation to occur only on create, not update. Alan -- Posted via http://www.ruby-forum.com/.
Alan Francis wrote:> Jon Hewer wrote: > >> when i want to update the record (without changing the password and >> entering new values for password and password_confirmation), using the >> update_attributes method, i am getting errors thrown up by this >> validation. > > I think adding > > :on => :create > > to the end of your validates_* lines will restrict the validation to > occur only on create, not update. > > Alanyeah, that should do it for now - but i think when i come to create a form allowing the user to update their password, then i''ll need that password validation to kick in. i think i need to use :if => *something* -- Posted via http://www.ruby-forum.com/.
Daniel ----- wrote:> You can restrict the validation to occur only on create. That way, when > the > user is updated it won''t trip the validation trip switch. > > validate_presence_of :password, :on => :create > validates_confirmation_of :password, :on => :create > > Alternatively, if you need more control use the :if option to point to a > proc or a method to test if validation should occur. > > validate_presence_of :password, :if => Proc.new{ |model| model.something > => a_condition } > or > validate_presence_of :password, :if => > :some_method_that_evaluates_to_true_or_falseso, is the best way of doing this to have a couple of flags in my user model updating_profile updating_password for example, which are set by the update methods in my controller, and to use validation in my user model something like? validates_presence_of :password, :password_confirmation :if => updating_password == true sorry, you can probably tell this is my first time using ruby on rails! is it possible to control whether the validates_* statements are executed directly depending on the method in the controller through which the model fields are being updated? -- Posted via http://www.ruby-forum.com/.
On 7/19/06, Jon Hewer <jonhewer@gmail.com> wrote:> > Daniel ----- wrote: > > You can restrict the validation to occur only on create. That way, when > > the > > user is updated it won''t trip the validation trip switch. > > > > validate_presence_of :password, :on => :create > > validates_confirmation_of :password, :on => :create > > > > Alternatively, if you need more control use the :if option to point to a > > proc or a method to test if validation should occur. > > > > validate_presence_of :password, :if => Proc.new{ |model| model.something > > => > a_condition } > > or > > validate_presence_of :password, :if => > > :some_method_that_evaluates_to_true_or_false > > so, is the best way of doing this to have a couple of flags in my user > model > > updating_profile > updating_password > > for example, which are set by the update methods in my controller, and > to use validation in my user model something like? > > validates_presence_of :password, :password_confirmation :if => > updating_password == true > > sorry, you can probably tell this is my first time using ruby on rails! > > is it possible to control whether the validates_* statements are > executed directly depending on the method in the controller through > which the model fields are being updated? > > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/railsOne really good place to have a look at this kind of code is techno-weenies acts_as_authenticated. It really is a good plugin for this. Very small and light weight. Doesn''t get in your way. http://svn.techno-weenie.net/projects/plugins/acts_as_authenticated/generators/authenticated/templates/model.rb He uses a method password_required? A quick extract of the pertinent bits of the user model # Virtual attribute for the unencrypted password attr_accessor :password validates_presence_of :password, :if => :password_required? validates_presence_of :password_confirmation, :if => :password_required? validates_length_of :password, :within => 4..40, :if => :password_required? validates_confirmation_of :password, :if => :password_required? before_save :encrypt_password # Encrypts some data with the salt. def self.encrypt(password, salt) Digest::SHA1.hexdigest("--#{salt}--#{password}--") end # Encrypts the password with the user salt def encrypt(password) self.class.encrypt(password, salt) end protected # before filter def encrypt_password return if password.blank? self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record? self.crypted_password = encrypt(password) end def password_required? crypted_password.blank? || !password.blank? end Hope that gets you started. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060718/739e8e02/attachment.html
On Mon, Jul 17, 2006 at 06:47:59PM +0200, Jon Hewer wrote:> hello, > > i am writing a simple user login system.did you try the LoginGenerator (or any of the alternative login systems available) ? see http://wiki.rubyonrails.org/rails/pages/HowToQuicklyDoAuthenticationWithLoginGenerator and http://wiki.rubyonrails.org/rails/pages/LoginGenerator Even if none of the solutions mentioned there does fit your needs, they might provide a good starting point. Jens> > when registering a user account, i have two field: > > password > password_confirmation > > which are validated using > > validates_presence_of > validates_confirmation_of > > and these are then used to generate a password hash which is stored in > my database > > when i want to update the record (without changing the password and > entering new values for password and password_confirmation), using the > update_attributes method, i am getting errors thrown up by this > validation. > > i want to be able to update the record, even if the user does not > specify a new password > > thanks > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Jens Kr?mer jk@jkraemer.net
Daniel ----- wrote:> One really good place to have a look at this kind of code is > techno-weenies > acts_as_authenticated. It really is a good plugin for this. Very small > and > light weight. Doesn''t get in your way.thanks Daniel, i''ll give those technique''s a try -- Posted via http://www.ruby-forum.com/.