Rails: получение изображения из Facebook после входа в Omniauth через Devise - PullRequest
17 голосов
/ 24 марта 2012

Я настраиваю вход в Facebook с помощью Devise и omniauth с помощью этих инструкций https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

Вики Devise дают некоторые инструкции для получения информации Facebook из хэша, хранящегося в этой переменной request.env['omniauth.auth'] См. Дно для хэша.1005 *

Например, в вики Devise есть эти два метода для User.rb модели

def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
  data = access_token.extra.raw_info
  if user = User.where(:email => data.email).first
    user
  else # Create a user with a stub password. 
    User.create!(:email => data.email, :password => Devise.friendly_token[0,20]) 
  end
end

def self.new_with_session(params, session)
    super.tap do |user|
      if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
        user.email = data["email"]

      end
    end
  end

Итак, используя приведенный ниже хеш, я добавил следующее к этим двум методам, чтобы получить имя и изображение

def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
  data = access_token.extra.raw_info
  if user = User.where(:email => data.email).first
    user
  else # Create a user with a stub password. 
    User.create!(:email => data.email, :password => Devise.friendly_token[0,20], :name => data.name, :image => access_token.info.image) #I added access_token.info.image based on first answer
  end
end

def self.new_with_session(params, session)
    super.tap do |user|
      if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
        user.email = data["email"]
        user.name = data["name"]
        user.image = access_token.info.image  #i changed this based on first answer below

      end
    end
  end

Затем, на мой взгляд, я добавил следующее, чтобы показать имя пользователя и изображение

<p>Name:<%= user.name %></p>
 <p>Image: <%= image_tag user.image %>

Однако отображается только имя.Нет изображения.

В моей базе данных есть столбец name и image.Имя из Facebook сохраняется, но в столбце изображения указано «nil»

Есть идеи, как заставить изображение работать?

Хеш хранится в request.env['omniauth.auth'] https://github.com/mkdynamic/omniauth-facebook/blob/master/lib/omniauth/strategies/facebook.rb#L31-47

   info do
        prune!({
          'nickname' => raw_info['username'],
          'email' => raw_info['email'],
          'name' => raw_info['name'],
          'first_name' => raw_info['first_name'],
          'last_name' => raw_info['last_name'],
          'image' => "#{options[:secure_image_url] ? 'https' : 'http'}://graph.facebook.com/#{uid}/picture?type=square",
          'description' => raw_info['bio'],
          'urls' => {
            'Facebook' => raw_info['link'],
            'Website' => raw_info['website']
          },
          'location' => (raw_info['location'] || {})['name'],
          'verified' => raw_info['verified']
        })
      end

1 Ответ

13 голосов
/ 24 марта 2012

Изображение можно найти на env["omniauth.auth"]["info"]["image"].Так что в вашем случае, access_token.info.image.

Если вы хотите внимательно посмотреть на возвращенный хеш вложенных хешей и убедиться, где все, поместите это в качестве первой строки вашего контроллера обратного вызова:

render :text => "<pre>" + env["omniauth.auth"].to_yaml and return

РЕДАКТИРОВАТЬ: Хорошо, вот что вам нужно сделать:

def self.find_for_facebook_oauth(omniauth)
  if user = User.find_by_email(omniauth.info.email)
    if omniauth.info.image.present?
      user.update_attribute(:image, omniauth.info.image)
    end
    user
  else # Create a user with a stub password. 
    User.create!(:email => omniauth.info.email,
                 :name => omniauth.info.name,
                 :image => omniauth.info.image,
                 :password => Devise.friendly_token[0,20])
  end
end

Что касается другого метода, если я не ошибаюсь, он должен выглядеть так:

def self.new_with_session(params, session)
  super.tap do |user|
    if omniauth = session["devise.facebook_data"]
      user.email = omniauth.info.email
      user.name = omniauth.info.name
      user.image = omniauth.info.image
    end
  end
end

Но когда этот метод используется?Он используется Devise, когда что-то идет не так при создании вашего пользователя.Представьте, что провайдер аутентификации не дает вам электронную почту (например, это делает Twitter), что вы можете сделать?Ну, вы можете перенаправить пользователя на свою страницу регистрации, где он может завершить процесс регистрации.Но если вы перенаправите пользователя, вы потеряете данные, полученные oauth.Решение состоит в том, чтобы поместить эти данные в сеанс.

Итак, в вашем контроллере должно быть что-то вроде:

if user.save
  sign_in_and_redirect user, :event => :authentication
else
  session["devise.facebook_data"] = env["omniauth.auth"]
  redirect_to new_user_registration_url
end

Однако другая проблема заключается в том, что в большинстве случаеввозвращенный провайдером аутентификации слишком большой, чтобы поместиться в сеансе, поэтому мы должны точно выбрать, что мы хотим поместить в сеанс.Поскольку вы получаете только имя и изображение, вы можете обрезать дополнительную информацию следующим образом:

session["devise.facebook_data"] = env["omniauth.auth"].except('extra')
...