下面显示的代码通常用于将rubygems,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
答案 0 :(得分:1)
from_omniauth
是一个类方法,因此其中没有显式接收器的任何方法(例如a.b
都有一个显式接收器a
)使用隐式接收器(self
) - 对于类方法self
指的是类本身。因此,在User类上调用where
,并由ActiveRecord Query接口定义。因此,where()
可以像User.where()
一样轻松地编写,但它是惯用的,可以省去不需要的显式接收器(因为它可以更轻松地重构类名,等等)。 )。
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
来查找与这些属性匹配的User对象或初始化一个新对象(不保存)。
最后,在结果对象上调用tap
,并设置块范围方法user
,等于对象(并在块的末尾返回用户)。基本上,这取代了创建局部变量user
。那么,实际上,它会在找到或初始化的User对象上设置块中的所有属性,然后save!
是用户。