我正在关注Ryan的Omniauth with Devise railscast。代码的一部分是:
class User < ActiveRecord::Base
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.username = auth.info.nickname
end
end
end
我正在摸着哪个()。first_or_create。这段代码究竟做了什么?
我的猜测是where()语句应用于类User。但是Rails如何知道它等同于User.where(:provider => "provider_id passed by auth", :uid => "uid passed by auth")
?
我的猜测是它产生一个集合,然后如果集合为空,则创建一个新实例user
并分配新属性。否则选择第一个实例并重新分配属性。
我的猜测是否正确?
答案 0 :(得分:9)
让我们把它分成几部分。
auth.slice(:provider,:uid)
auth是一个包含:provider和:uid键的哈希。调用.slice到auth会返回一个只有这些键作为键的新哈希。即
auth = { provider: 'foo', uid: 'bar', some_other_key: 'blah' }
new_hash = auth.slice(:provider, :uid) # { provider: 'foo', uid: 'bar' }
<强> first_or_create 强>
相当于find_or_create_by
。您可以阅读documentation并查看它是否搜索与传递给where
的选项相匹配的任何记录。如果没有找到记录,它会尝试创建一个记录,并将这些选项作为属性。
块传递
user.provider = auth.provider
user.uid = auth.uid
user.username = auth.info.nickname
实际上只需要最后一行。前两行是冗余的,因为它位于where选项中。