Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails validate only on user create or update

I have a validates_confirmation_of :password in my User model. The problem is I also run @comment.user.save! when a comment is created to update some attributes on the user account.

I get an error when creating a comment Validation failed: Password confirmation can't be blank. I can't add :on => "save" to my validation because my comments controller is also calling the save function.

I've read this thread Rails model validation on create and update only, but it doesn't answer my specific issue.

UPDATE User model snippet:

class User < ActiveRecord::Base

  attr_accessor :password

  # validations
  validates_presence_of :username
  validates_length_of :username, :within => 6..25
  validates_uniqueness_of :username
  validates_presence_of :email
  validates_length_of :email, :maximum => 100
  validates_format_of :email, :with => EMAIL_REGEX
  validates_confirmation_of :password, :if => :password_changed?
  validates_presence_of :password_confirmation
  validates_length_of :password, :within => 4..25, :on => :create

  before_save :create_hashed_password
  after_save :clear_password

  private

  def clear_password
    self.password = nil
  end

end
like image 605
Tony Beninate Avatar asked Dec 16 '22 10:12

Tony Beninate


2 Answers

According to this validates_confirmation_of the model should be valid if the password_confirmation field is nil. Are you storing it to DDBB? Or maybe something is wrong with your validation, could you paste your user model here?

Either way you can try something like this:

validates_presence_of :password_confirmation, if: -> { password.present? }
validates_confirmation_of :password, if: -> { password.present? }
like image 174
cicloon Avatar answered Feb 24 '23 07:02

cicloon


Why exactly do you run @comment.user.save!? Touching (e.g. updating timestamps) and increasing comments count can be done via built-in mechanisms.


Edit: I'd suggest something similar to:

class Comment < ActiveRecord::Base
  after_save :rank_user

  def rank_user
    # calculate rank
    user.update_attribute(:rank, rank)
  end
end

Benefits of this approach:

  1. Your controller and models will be clean and rank_user will be called automatically, without an explicit call of @comment.user.save!.
  2. According to the update_attribute documentation, validations will be skipped which then results in no password-confirmation errors.
like image 32
Mario Uher Avatar answered Feb 24 '23 08:02

Mario Uher