Подтвердить что ты не робот

Rails: получение изображения из Facebook после входа в Omniauth с помощью Devise

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

В вики-разработке Devision содержатся некоторые инструкции по получению информации в facebook из хэша, хранящегося в этой переменной request.env['omniauth.auth'] См. снизу для хэша.

Например, Devile wiki имеет эти два метода для модели 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
4b9b3361

Ответ 1

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

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

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

EDIT: Хорошо, вот что вам нужно сделать:

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')