Rails异常声明:where()。first_or_create()

时间:2013-02-22 04:01:41

标签: ruby-on-rails

我正在关注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并分配新属性。否则选择第一个实例并重新分配属性。

我的猜测是否正确?

1 个答案:

答案 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选项中。