Reputation: 3
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.
Upvotes: 0
Views: 121
Reputation: 464
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.
Upvotes: 0
Reputation: 2469
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.
Upvotes: 3
Reputation: 11007
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.
Upvotes: 0