Dmitri
Dmitri

Reputation: 2748

Understanding a Boolean conjunction statement in Rails method

This might be a trivial point, but I don't understand it and it bothers me. Going through the Ruby on Rails Tutorial by Michael Hartl, there is this method definition :

 def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in user
      redirect_to user
    else
      flash.now[:danger] = "Invalid email/password combination"
      render 'new'
    end
  end

What I don't understand is why the conjunction

user && user.authenticate(params[:session][:password])   

is neccessary. Surely, there is no case in which user.authenticate will return "true" if the user object is empty, and hence, nil. Is this just a matter of style, or does 'user &&' do something subtle in this expression?

Upvotes: 0

Views: 136

Answers (3)

Jörg W Mittag
Jörg W Mittag

Reputation: 369623

Why don't you just ask Ruby herself about the difference?

user = nil

if user && user.authenticate(nil) then end

if user user.authenticate(nil) then end
# NoMethodError: undefined method `authenticate' for nil:NilClass

As you can see, nil doesn't have an authenticate method (why would it), so trying to call authenticate on nil will raise a NoMethodError.

Boolean operators are evaluated lazily from left to right (sometimes known as "short-circuiting") only as far as is needed to determine the result. Since user is nil, it is already known that the result of the entire conditional must be falsy, no matter what the right operand is, and so the right operand is never evaluated, and therefore, the non-existing method is never called.


Note: I'm not trying to be glib here, I'm trying to show you a powerful learning tool: if you are wondering "what happens if I do XYZ", just do XYZ and see what happens! Contrary, to, say, chemistry, experimenting is completely safe in programming. (Well … you could delete your harddrive, if you're really stupid, but if you do your experiments in a sandboxed environment, you'll be fine. Accidentally deleting valuable data is highly unlikely unless you are toying around with the File or FileUtils classes.)

Upvotes: 1

pauloancheta
pauloancheta

Reputation: 369

if user would be the same as if user.present?. So if its nil, it goes to the else statement, if its true, then it runs the second statement being user.authenticate(params[:session][:password])

Upvotes: 2

aspencer8111
aspencer8111

Reputation: 786

Trying to do this part: user.authenticate(params[:session][:password]) without first knowing if the object exists will throw an error. So you need to make sure you have the user object before you try to run .authenticate on it. Does that make sense?

Upvotes: 1

Related Questions