简体   繁体   中英

Is there a better way to validate in Rails?

In my model I have validations that check for presence of the "password" and "password_confirmation" fields. While creating the model, the validations run fine. But during updating the model, even while updating a group of specific fields, validations seem to be called on the whole model. And as I dont pass in the "password" and "password_confirmation" fields every time, the validation fails.

At first my thought was to validate those two fields only "on :create" but I want to give the option to update the password as well. In which case the validations wont be called during update of those fields.

So, is there a way to handle this problem?

The following is my model:

    class Consumer < ActiveRecord::Base
      attr_accessor :password, :password_confirmation
      mount_uploader :image, ProfileImageUploader

      EMAIL_REGEX = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
      PASS_REGEX = /\A[a-zA-Z0-9]{8,16}\z/

      validates :email, presence: {message: "Email cannot be blank!", on: :create}, format: {with: EMAIL_REGEX, message: "Email invalid!"}
      validate :unique_email?, on: :create
      validates :password, presence: {message: "Password cannot be blank!"}, confirmation: {message: "Passwords do not match!"}, format: {with: PASS_REGEX, message: "Password invalid!"}
      validates :password_confirmation, presence: {message: "Retype password!"}
      validates :fullname, presence: {message: "Name cannot be empty!"}

before_save :encrypt_password

def authenticate pass
    new_hash = BCrypt::Engine.hash_secret pass, self.password_salt
    if  new_hash === self.password_hash
      return true
    end
    false
  end

  def encrypt_password
    if password.present?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = BCrypt::Engine.hash_secret password, password_salt
    end
  end

    end

Conditional Validations

Was going to suggest you use some sort of conditional validations , as follows (then I read the comments):

#app/models/consumer.rb
class Consumer < ActiveRecord::Base
      ...
      validates :password_confirmation, presence: {message: "Retype password!"}, if: Proc.new {|a| a.password.present? }
end

This is the best I can provide for your particular situation - I've not created a password signup / authentication procedure myself (always relied on other classes), so if you wanted to use has_secure_password etc - I'll have to update my answer to help

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM