0

The code shown below is commonly utilized when integrating the rubygems, Omniauth and Omniauth-Facebook, into a rails app. I need an explanation of this piece of code, line by line.

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
Denzel Pressey
  • 117
  • 1
  • 5

1 Answers1

1

from_omniauth is a class method, so any method inside of it that doesn't have an explicit receiver (e.g. a.b has an explicit receiver a) uses the implicit receiver (self) -- and for a class method self refers to the class itself. Therefore, where is being called on the User class and is defined by the ActiveRecord Query interface. So where() could just as easily be written as User.where(), but it's idiomatic to leave off explicit receivers that aren't needed (because it makes refactoring the class name easier, etc.).

The argument to where is the result of the statement auth.slice(:provder, :uid). Here, auth is basically a Hash. (It's actually a hashie object which is a hash with additional functionality.) So auth.slice is ultimately calling Hash#slice -- which will just return a new Hash containing only the keys/values that were passed in to slice, leaving you with { provider: "facebook", uid: "THE_UID_HERE" }. So the overall result is performing User.where(provider: "facebook", uid: "THE_UID_HERE").

Then first_or_initialize is called to either find a User object that matches these attributes or initialize a new one (without saving it).

Finally, tap is called on the resulting object and sets a block-scope method, user, equal to the object (and returns the user at the end of the block). Basically, this is in place of creating a local variable user. So, then, effectively, it sets all the attributes in the block on the found or initialized User object and then save!s the user.

pdobb
  • 17,688
  • 5
  • 59
  • 74