Question

My model:

class User < Sequel::Model
self.raise_on_save_failure = false
plugin :validation_helpers
def validate
    super
    validates_format /@/, :email
    validates_presence [:email, :password]
    validates_unique :email
end

def before_save
    super
    self[:password] = BCrypt::Password.create(self[:password])
end

end

But when i update user, my password hash twice. I know it is because of before_save hook, but i want to keep sequel validating (validates_presence) real password, not result of bcrypt hash (cause BCrypt::Password.create('') is not empty)

So i need somehow do next:

  1. check if password changed
  2. validate real password by sequel
  3. save bcrypt hash of my password
Was it helpful?

Solution

I think you should reconsider your work flow. If you want an invalid input to be only caught when trying to update the DB, why not go for something like this:

post '/update' do
  ...

  if params[:password] == nil || params[:password].empty?
    password = nil
  else
    password = BCrypt::Password.create(params[:password])
  end

  # I have no idea how this line should really look like in your code
  User.find(param[:id]).set(:password, password)

  ...
end

So basically, give it nil if the password field was not sent or empty.

As stated very clearly by iain in the comments:

[...] you should only be using Sequel to validate data that is or will be held by the database. The real password should be validated by the business logic layer, which is what is happening in this answer.

OTHER TIPS

You can check it in class method like this:

  if user.password_digest != expected_password
    user = nil
  end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top