2013-08-29 13 views
9

Nagi ze mną, to będzie Długie.Praca (omniauth-facebook) i (omniauth-twitter)

Używam:

  • Ruby on Rails 4
  • Devise 3.0.3
  • omniauth (1.1.4)
  • omniauth-facebook (1.4.1)
  • omniauth -twitter (1.0.0)

Niedawno skonfigurowałem mój omniauth-facebook i wszystko działa ine. Teraz chcę dodać omniauth-twitter, ale jakoś zepsułem wszystko, całkiem źle.

1.) skonfigurować moją Omniauth-Facebook zrobiłem to (w skrócie):

gem 'omniauth' 
gem 'omniauth-facebook' 

2.) dodane kolumny "provider" i "uid" do mojego modelu użytkownika.

3.) Następnie oświadczyłem dostawcy w moim config/inicjalizatorów/devise.rb:

require "omniauth-facebook" 
config.omniauth :facebook, "App_ID", "App_Secret", 
           {:scope => 'email,offline_access', 
           :client_options => {:ssl => {:ca_file => 'lib/assets/cacert.pem'}}, 
           :strategy_class => OmniAuth::Strategies::Facebook} 

4.) edytowany moim modelu User.rb

# Facebook Settings 
def self.find_for_facebook_oauth(auth, signed_in_resource = nil) 
    user = User.where(provider: auth.provider, uid: auth.uid).first 
    if user.present? 
     user 
    else 
     user = User.create(first_name:auth.extra.raw_info.first_name, 
              last_name:auth.extra.raw_info.last_name, 
              facebook_link:auth.extra.raw_info.link, 
              user_name:auth.extra.raw_info.name, 
              provider:auth.provider, 
              uid:auth.uid, 
              email:auth.info.email, 
              password:Devise.friendly_token[0,20]) 
    end 
end 

i dodano atrybuty do opracowania:

:omniauth_providers => [:facebook] 

5.) I edycja trasy:

devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } 

KONIEC

Mimo to działało idealnie na Facebooku, próbowałem przez kilka godzin teraz, aby dostać tę pracę na Twitterze, a ja po prostu nie mogę rozwiązać.

Jeśli ktoś, kto ma doświadczenie w tym, czy po prostu wie, że rozwiązaniem mogłoby pomóc mi to skonfigurować, byłbym bardzo wdzięczny :)

Dziękujemy wam, i przepraszam za długi post.

oprócz

Twitter nie zapewnia: email Atrybut więc muszę podzielić mojego procesu rejestracji Użytkownik Chyba?

Moja Twitter akcja w moim model użytkownika

# Twitter Settings 
def self.find_for_twitter_oauth(auth, signed_in_resource=nil) 
    user = User.where(:provider => auth[:provider], :uid => auth[:uid]).first 
    unless user 
     user = User.create(:first_name => auth[:name], 
              :user_name => auth[:screen_name], 
              :provider => auth[:provider], :uid => auth[:uid], 
              :password => Devise.friendly_token[0,20] 
     ) 
    end 
    user 
end 

# build auth cookie hash for twitter 
def self.build_twitter_auth_cookie_hash data 
    { 
     :provider => data.provider, :uid => data.uid.to_i, 
     :access_token => data.credentials.token, :access_secret => data.credentials.secret, 
     :first_name => data.name, :user_name => data.screen_name, 

    } 
end 

miałem migrować POTWIERDZALNE dla użytkowników ->How To: Add :confirmable to Users

Problem moja forma jest (przynajmniej im dotarcie do tej Poing teraz :))

enter image description here

+1

To zawsze pomaga, jeśli wyjaśnić i/lub wyświetlić rzeczywiste błędy, które otrzymujesz I długi post nie stanowi problemu, im więcej informacji, tym weselej ... Twój jest w rzeczywistości krótszy niż wiele –

+0

czy umieścisz kod 'devise.rb' dla twittera –

+0

nie potrzebujesz klejnotu omniauth, jeśli masz inne – ahnbizcad

Odpowiedz

13

Aby rozwiązać problem z wiadomością e-mail, możesz ustawić fałszywą pocztę lub dodać drugi krok, w którym użytkownik dodaje swoją wiadomość e-mail.

Dummy mail:

class User < ActiveRecord::Base 

    before_create :set_dummy_mail, if self.provider == "twitter" 

    private 

    def set_dummy_mail 
    self.email = "#{self.name}[email protected]" 
    end 

end 

Albo druga opcja krok:

Modyfikowanie kontroler do przekierowania do kroku e-mail Dodaj jeżeli dostawca jest Twitter i e-mail jest pusty. Być może musisz również zmodyfikować swoje sprawdzanie poprawności, aby zezwolić na wysyłanie pustych wiadomości e-mail w przypadku, gdy dostawcą jest twitter.

UPDATE: Zrobiłem to jak następuje:

Gemfile:

gem "devise" 
gem "omniauth" 
gem "omniauth-facebook" 
gem "omniauth-twitter" 

użyłem:

  • wersja Devise 2.2.3
  • omniauth 1.1.4
  • omniauth-facebook 1.3.0
  • omniauth-twitter 0.0.17

Jeśli używasz różnych wersji, być może trzeba zmienić kilka rzeczy ..

routes.rb:

devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } 

devise_scope :user do 
    post "account/create" => "users/accounts#create" 
end 

app/models/user.rb

class User < ActiveRecord::Base 

    # allow email blank for first create 
    validates_format_of :email, :with => Devise.email_regexp, :allow_blank => true, :if => :email_changed? 

    # facebook find method 
    def self.find_for_facebook_oauth(auth, signed_in_resource=nil) 
    user = User.where(:provider => auth.provider, :uid => auth.uid).first 
    unless user 
     user = User.create(:first_name => auth.extra.raw_info.first_name, 
         :last_name => auth.extra.raw_info.last_name, 
         :facebook_link => auth.extra.raw_info.link, 
         :user_name => auth.extra.raw_info.name 
         :provider => auth.provider, 
         :uid => auth.uid, :email => auth.info.email, 
         :password => Devise.friendly_token[0,20] 
         ) 
     user.confirm! 
    end 
    user 
    end 

    # twitter find method 
    def self.find_for_twitter_oauth(auth, signed_in_resource=nil) 
    user = User.where(:provider => auth[:provider], :uid => auth[:uid]).first 
    unless user 
     user = User.create(:first_name => auth[:first_name], :user_name => auth[:user_name], 
         :provider => auth[:provider], :uid => auth[:uid], 
         :password => Devise.friendly_token[0,20] 
         ) 
    end 
    user 
    end 

    # build auth cookie hash for twitter 
    def self.build_twitter_auth_cookie_hash data 
    { 
     :provider => data.provider, :uid => data.uid.to_i, 
     :access_token => data.credentials.token, :access_secret => data.credentials.secret, 
     :first_name => data.screen_name, :user_name => data.name, 

    } 
    end 

end 

app/controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 

    # callback action for facebook auth 
    def facebook 
    @user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user) 

    if @user.persisted? 
     sign_in_and_redirect @user, :event => :authentication 
     set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format? 
    else 
     session["devise.facebook_data"] = request.env["omniauth.auth"] 
     redirect_to new_user_registration_url 
    end 
    end 

    # callback action for twitter auth 
    def twitter 
    data = session["devise.omniauth_data"] = User.build_twitter_auth_cookie_hash(request.env["omniauth.auth"]) 

    user = User.find_for_twitter_oauth(data) 
    if user.confirmed? # already registered, login automatically 
     flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Twitter" 
     sign_in_and_redirect user, :event => :authentication 
    elsif !user.email? 
     flash[:error] = "You must add an email to complete your registration." 
     @user = user 
     render :add_email 
    else 
     flash[:notice] = "Please confirm your email first to continue." 
     redirect_to new_user_confirmation_path 
    end 
    end 

end 

app/views/users/omniauth_callbacks/add_email.html.erb

<%= form_for(@user, :as => "user", :url => account_create_path, :html => {:class => "form-inline"}) do |f| %> 
    <%= f.email_field :email, :placeholder => User.human_attribute_name(:email), :class => "input-medium" %> 
    <%= f.submit "Finish registration", :class => "btn btn-small" %> 
<% end %> 

app/controllers/users/accounts_controller.rb

class Users::AccountsController < ApplicationController 

    def create 
    data = session["devise.omniauth_data"] 
    data[:email] = params[:user][:email] 
    user = User.find_for_twitter_oauth(data) 
    user.email = data[:email] 

    if user.save 
     flash[:notice] = I18n.t "devise.registrations.signed_up_but_unconfirmed" 
     redirect_to root_path 
    else 
     flash[:error] = I18n.t "devise.omniauth_callbacks.failure", :kind => data[:provider].titleize, :reason => user.errors.full_messages.first 
     render "users/omniauth_callbacks/add_email" 
    end 
    end 

end 

Może trzeba zmodyfikować jeden lub innej części mojego rozwiązania .. możesz również refaktoryzować dwie metody w modelu użytkownika (find_for_facebook_auth, find_for_twitter_auth), aby pracować z jedną dynamiczną metodą. Wypróbuj go i daj mi znać, jeśli nadal masz problemy. Jeśli znajdziesz jakąkolwiek literówkę, daj mi znać. Powinieneś też napisać testy, aby sprawdzić wszystko w twoim systemie.

+0

Hej Mattherick, naprawdę podoba mi się twoja metoda. Zrobiłem to i zmieniłem trochę kod dla Rails 4 i mojego Devise. Ale otrzymuję zawsze NoMethodError w Użytkownicy :: OmniauthCallbacksController # twitter | niezdefiniowana metoda "dostawca". Czy możesz sprawdzić mój Gitub Repo? -> https://github.com/Theminijohn/myapp –

+0

Ich bin hier ein bisschen überfordert :) –

+0

Gdzie dokładnie pojawia się błąd? Na której linii? Czy możesz opublikować stos śledzenia pls. – Mattherick

0

Dodaj ten w pliku gem

gem 'omniauth-twitter' 

nie połączą i zrestartować serwer

po tym dodać APP_ID i tajny klucz w config/inicjator/devise.rb

require "omniauth-twitter" 
config.omniauth :twitter, "app_id", "secret_key" 

Edycja użytkownik model

:omniauth_providers => [:facebook,:twitter] 
def self.find_for_twitter_oauth(auth, signed_in_resource=nil) 

    user = User.where(:provider => auth.provider, :uid => auth.uid).first 
    unless user 
    user = User.create(name:auth.extra.raw_info.name, 
         provider:auth.provider, 
         uid:auth.uid, 
         email:auth.info.email, 
         password:Devise.friendly_token[0,20]        
         ) 

    end 
    user 
end 

Dodaj nowy plik kontrolera do

app/controller/user/omniauth_callbacks_controller.rb

def twitter 
@user = User.find_for_twitter_oauth(request.env["omniauth.auth"], current_user) 

if @user.persisted? 
    sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated 
    set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format? 
else 
    session["devise.twitter_data"] = request.env["omniauth.auth"] 
    redirect_to new_user_registration_url 
end 

koniec

Dodaj ten link w pliku widoku

<%= link_to 'sign in with twitter', user_omniauth_authorize_path(:twitter) %> 

wymaganych zmian w modelu użytkownika, jak twitter nie zwracają id e-mail użytkownika: Utwórz plik migracji w celu umożliwienia wartości puste w kolumnie e-mail użytkownika:

class ChangeEmailToNullInUser < ActiveRecord::Migration 
    def up 
     change_column :users, :email, :string, :null=>true 
    end 

    def down 
    end 
end 

po tym trzeba także zastąpić model użytkownika walidacji więc dodać to w user.rb

def email_required? 
    false 
end 

Uwaga: Przed wykonaniem tego należy stworzyć aplikację na Twitterze i podać właściwą ścieżkę zwrotną. Jest to ważne, ponieważ po uwierzytelnieniu ze strony twitter kontroler wróci na ścieżkę, którą określisz w swojej aplikacji na twitterze.

daj mi znać, jeśli masz jakiś problem.

+0

Hej Sagar, dzięki za pomoc!Wszystko konfiguruję, otrzymuję połączenie przez Twitter, ale pojawia się błąd ActionDispatch :: Pliki cookie :: CookieOverflow w Użytkownicy :: OmniauthCallbacksController # twitter –

+0

Aktualizuję moje pytanie o to, w jaki sposób uzyskuję przewagę nad Cookie Overflow. Sądzę, że jest to realistyczne Rozwiązanie, ale proszę, przyjrzyj mu się. Teraz mam te błędy atrybutu twitter :( –

+0

Hej, "The Mini John", wycofałem problem, ten sam problem, z którym miałem do czynienia wcześniejszą główną przyczyną jest to, że Twitter nie zwraca użytkownikom adresu e-mailowego id (nota bene uwaga) jego polityka Twittera api jest Zaprojektowany, aby to zrobić, w naszym opracowanym przeze mnie modelu użytkownika wymagany jest adres e-mail. Aktualizuję swoją odpowiedź zgodnie z tym, więc sprawdź to. –

0

Mattherick ma dobre rozwiązanie dla wiadomości e-mail, ale nie mogłem uzyskać before_create do pracy. Połączenie zwrotne nie działa przyjemnie z warunkowymi instrukcjami if, ponieważ wszystko za przecinkiem ma być hashem opcji. Dlatego:

before_save :set_dummy_email, if self.provider == "twitter" 

Popped me errors.

To jak naprawiłem to:

before_save :set_dummy_email 

def set_dummy_email 
    self.email ||= "#{self.name}[email protected]" 
end 

Spowoduje to ustawienie tylko e-mail, jeśli nie jest podana przez dostawcę (tj: Twitter).

A potem do bardziej „uniwersalny” sposób ustalania atrybutów (więc nie trzeba unikalną strategię:

def self.from_omniauth(auth) 
    where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user| 
    user.name = auth.info.name || auth.info.nickname 
    user.provider = auth.provider 
    user.uid = auth.uid 
    user.email = auth.info.email if auth.info.email 
    user.save 
    end 
end