0

I am very new to the Ruby language and Ruby on Rails, so I'm not entirely sure how to word my question (and will probably use incorrect terminology). The following code does not work

@user = User.find_by email: params[:session][:email] 
if @user.authenticate(params[:session][:password]) 
     # Signin @user 
else 
    # Render failed Signin 
end 

I get an error that the method authenticate is not defined for nil:Nilclass, but the following code works fine:

@user = User.find_by email: params[:session][:email] 
if @user && @user.authenticate(params[:session][:password]) 
    # Signin @user 
else 
    # Render failed Signin 
end 

I don't understand why the first code block doesn't work. When I define @user does the User.find_by method not run and set the value of @user? Or does the variables value get set only when called in the program?

EDIT: unnecessary parentheses removed.

1
  • what version of rails are you using? Commented Aug 1, 2013 at 6:39

3 Answers 3

3

Here's what I think is wrong with the first block:

In the first block, you search for a user and if not found will return nil. Then, you are trying to authenticate nil and that's why is giving you a not defined for Nil:class.

On the second block you are fixing the problem by adding the @user in your if block. Testing to see whether you actually have a retrieved user first, incase the user is not found the block will not be executed.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! This makes sense to me. I've spent the last two hours googling the issue and couldn't find anything. I tried upvoting your answer, but apparently I don't have enough reputation to do that yet.
Np, if you think this is the correct answer just mark it as such.
0

To start, here's a good breakdown of the && operator - what it does and doesn't do.

in your first block, in the second line:

if (@user.authenticate(params[:session][:password])) 

you don't need parentheses around @user -

if @user.authenticate(params[:session][:password]) 

You should also be using find_by_email as Hassan has pointed out.

2 Comments

Thanks, I have removed the unnecessary parentheses, but from what I've read is find_by preferred over find_by_email in Rails 4.0?
ah, okay, sorry didn't realize you were using rails 4.0!
0

The find_by method you used should result in a NoMethodError exception(unless you have defined that method in the User model).

You can use a dynamic finder method(http://guides.rubyonrails.org/active_record_querying.html#dynamic-finders) on any of the user's attributes like

User.find_by_email(params[:session][:email])

UPDATE: I was thinking of Rails 3 when posting the answer, Rails 4 removes dynamic finders, and the method you are using is perfectly valid.

1 Comment

before posting such answer, you'd better know what version of rails @Jason using. In Rails 4, there is find_by(*args) method

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.