为什么方法 authenticate 不接受一个包含一个对象的数组?

Why doesn't the method authenticate take in an array with one object in it?

使用 Rails 5.0。

我正在通过教程学习如何进行身份验证,但想知道为什么如果您 return 使用 Model.where(:somequery => some parameter) 进行查询,为什么方法 .authenticate 不接受结果, 这是一个只有 object/record 的数组?在教程中,他们用 .first 这个词来消除数组。

即:

access_controller.rb 的一部分(我的应用程序中的控制器):

  def attempt_login
    if params[:username].present? && params[:password].present?
      found_user = AdminUser.where(:username => params[:username]).first
    #The above line .first removes the array given by .where

      if found_user
        authorized_user = found_user.authenticate(params[:password])
      end
    end


   if authorized_user
      session[:user_id] = authorized_user.id
      flash[:notice] = "You are now logged in."
      redirect_to(admin_path)
    else
      flash.now[:notice] = "Invalid username/password combination."
      render('login')
    end

  end

为什么 found_user 不能使用其中包含单个对象的数组(没有 .first)?是不是array = [object] equal to array = object,如果数组中只有一个对象?

Model.where碰巧生成一个只有一个元素的数组,但有时它会有更多元素。

由于 authenticate 方法仅适用于单个记录,因此最好设计为将单个记录传递给它。活动记录查询(即 where 结果)和实例具有完全不同的方法集,因此您不能只传递查询并期望它像记录一样工作。魔术只能到此为止。

更重要的问题是:为什么要?仅仅因为您的期望没有得到满足并不意味着它是错误的。

什么 where returns 是作用域,尽管在许多情况下它 的行为 类似于数组。从技术上讲,它不是一个,但在必要时它会尽最大努力看起来是一个,例如当您对其调用 first 时,或者请求 lengthany? 之类的东西时

在作用域上调用 authenticate 没有任何意义,这不是一种受支持的方法。在单个模型实例上调用 authenticate 确实 有意义,这就是你应该做的。

此处最简单的解决方法是,如果您想要一条记录,则请求一条记录:

if found = AdminUser.find_by(username: params[:username])
  authorized_user = found.authenticate(params[:password])
end

您也可以使用 find_by! 这样做,如果找不到符合这些条件的用户,则会抛出异常。这允许您链接事物:

def login
  @authorized = AdminUser.find_by!(username: params[:username]).authenticate(params[:password])

rescue ActiveRecord::RecordNotFound
  # No such user
end