0

下面显示的代码通常在将 ruby​​gems、Omniauth 和 Omniauth-Facebook 集成到 rails 应用程序时使用。我需要逐行解释这段代码。

class User < ActiveRecord::Base
  def self.from_omniauth(auth)
    where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
      user.provider = auth.provider
      user.uid = auth.uid
      user.name = auth.info.name
      user.oauth_token = auth.credentials.token
      user.oauth_expires_at = Time.at(auth.credentials.expires_at)
      user.save!
    end
  end
end
4

1 回答 1

1

from_omniauth是一个类方法,因此它内部的任何没有显式接收器(例如a.b具有显式接收器a)的方法都使用隐式接收器(self)——对于一个类方法来说self,它指的是类本身。因此,where在 User 类上被调用并由 ActiveRecord Query 接口定义。所以where()可以像 一样容易地编写User.where(),但是省略不需要的显式接收器是惯用的(因为它使重构类名更容易,等等)。

to 的参数where是语句的结果auth.slice(:provder, :uid)。在这里,auth基本上是一个哈希。(它实际上是一个hashie对象,它是一个具有附加功能的散列。)auth.slice最终调用Hash#slice也是如此——它只会返回一个新的 Hash,其中只包含传入的键/值,给slice你留下{ provider: "facebook", uid: "THE_UID_HERE" }. 所以总体结果是执行User.where(provider: "facebook", uid: "THE_UID_HERE")

然后first_or_initialize调用它来查找与这些属性匹配的用户对象或初始化一个新对象(不保存它)。

最后,tap在结果对象上调用并设置块范围方法user,等于该对象(并在块的末尾返回用户)。基本上,这代替了创建局部变量user。因此,有效地,它将块中的所有属性设置在找到或初始化的用户对象上,然后save!是用户。

于 2014-08-24T15:51:39.627 回答