3

私は Devise railscast で Ryan のOmniauth をフォローしています。コードの一部は次のとおりです。

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

where().first_or_create do で頭を悩ませています。このコードは正確に何をしますか?

私の推測では、where() ステートメントがクラス User に適用されます。しかし、Rails はそれが と同等であることをどうやって判断するのUser.where(:provider => "provider_id passed by auth", :uid => "uid passed by auth")でしょうか?

私の推測では、コレクションが生成され、コレクションが空の場合は、新しいインスタンスを作成してuser新しい属性を割り当てます。それ以外の場合は、最初のインスタンスを選択して属性を再割り当てします。

私の推測は正しいですか?

4

1 に答える 1

9

これをパーツに分解してみましょう。

auth.slice(:プロバイダ, :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ドキュメントを読むと、に渡されたオプションに一致するレコードが検索されることがわかりますwhere。レコードが見つからない場合、それらのオプションを属性として使用してレコードを作成しようとします。

ブロックが通りました

user.provider = auth.provider
user.uid = auth.uid
user.username = auth.info.nickname

実際には最後の行だけが必要です。最初の 2 行は where オプションにあるため冗長です。

于 2013-02-22T04:07:33.537 に答える