设置一个等于函数和if语句的变量

时间:2013-08-01 06:31:26

标签: ruby-on-rails-4

我是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的值?或者变量值是否仅在程序中调用时才设置?

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

3 个答案:

答案 0 :(得分:3)

这是我认为第一个块的错误:

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

在第二个区块中,您通过在@user中添加if block来解决问题。测试以确定您是否确实首先拥有检索到的用户,但未找到该用户的块将不会被执行。

答案 1 :(得分: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删除了动态查找器,而且你使用的方法完全有效。

答案 2 :(得分:0)

首先,here&&运算符的良好细分 - 它的作用和不作用。

在你的第一个街区,第二行:

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

@user -

周围不需要括号
if @user.authenticate(params[:session][:password]) 

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