0

我对 Ruby 语言和 Ruby on Rails 非常陌生,所以我不完全确定如何表达我的问题(并且可能会使用不正确的术语)。以下代码不起作用

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

我收到一个错误,即没有为 nil:Nilclass 定义方法验证,但以下代码可以正常工作:

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

我不明白为什么第一个代码块不起作用。当我定义@user 时,User.find_by 方法不会运行并设置@user 的值吗?还是只有在程序中调用时才设置变量值?

编辑:删除不必要的括号。

4

3 回答 3

3

这是我认为第一个块有问题的地方:

在第一个块中,您搜索用户,如果未找到将返回nil。然后,您正在尝试进行身份验证nil,这就是为什么给您一个not defined for Nil:class.

在第二个块中,您通过@userif block. 首先测试看看你是否真的有一个检索到的用户,以防找不到用户,块将不会被执行。

于 2013-08-01T06:51:47.333 回答
0

您使用的find_by方法应该会导致 NoMethodError 异常(除非您在 User 模型中定义了该方法)。

您可以在任何用户属性上使用动态查找器方法(http://guides.rubyonrails.org/active_record_querying.html#dynamic-finders ),例如

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

更新:发布答案时我在考虑 Rails 3,Rails 4 删除了动态查找器,并且您使用的方法完全有效。

于 2013-08-01T06:38:22.337 回答
0

首先,这里是对操作符的一个很好的细分&&——它做什么和不做什么。

在您的第一个块中,在第二行:

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

你不需要括号@user-

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

find_by_email正如哈桑指出的那样, 您也应该使用。

于 2013-08-01T06:40:24.783 回答