0

我開始看Ryan Bates的tutorial關於如何在設計中使用Omniauth(rails-cast 235修訂版)。我遇到了user.rb文件的問題。他顯示了他tutorial使用設計和導軌的omniauth嘰嘰喳喳寶石5

devise :omniauthable, # ... 
 

 
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 
 

 
def self.new_with_session(params, session) 
 
    if session["devise.user_attributes"] 
 
    new(session["devise.user_attributes"], without_protection: true) do |user| 
 
     user.attributes = params 
 
     user.valid? 
 
    end 
 
    else 
 
    super 
 
    end 
 
end 
 

 
def password_required? 
 
    super && provider.blank? 
 
end 
 

 
def update_with_password(params, *options) 
 
    if encrypted_password.blank? 
 
    update_attributes(params, *options) 
 
    else 
 
    super 
 
    end 
 
end

不工作對我來說,它的顯示加載ActiveModel :: ForbiddenAttributesError與這行代碼where(auth.slice(:provider, :uid)).first_or_create do |user|突出。我想他的版本不工作,因爲我使用Rails 5.反正我已經嘗試修改user.rb文件。用下面的代碼。

def self.from_omniauth(auth) 
 
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user| 
 
    \t user.email = auth.info.email 
 
    user.password = Devise.friendly_token[0,20] 
 
    user.provider = auth.provider 
 
    user.uid = auth.uid 
 
    token = auth.credentials.token, 
 
    secret = auth.credentials.secret 
 
    end 
 
end 
 

 
def self.new_with_session(params, session) 
 
    super.tap do |user| 
 
     if data = session["devise.twitter_data"] 
 
     # user.attributes = params 
 
     user.update(
 
      email: params[:email], 
 
      password: Devise.friendly_token[0,20], 
 
      provider: data["provider"], 
 
      uid: data["token"], 
 
      token: data["credentials"]["token"], 
 
      secret: data["credentials"]["secret"] 
 
     ) 
 
     end 
 
    end 
 
    end 
 

 
def password_required? 
 
    super && provider.blank? 
 
end 
 

 
def update_with_password(params, *options) 
 
    if encrypted_password.blank? 
 
    update_attributes(params, *options) 
 
    else 
 
    super 
 
    end 
 
end 
 
end

我能夠獲得Twitter的身份驗證頁面顯示了負載了大約一分鐘,然後重定向回我的用戶註冊頁面,而不登錄,也沒有顯示任何錯誤消息。順便說一下,有人知道如何使用設計與Facebook登錄。

回答

0

該問題與您傳遞給self.from_omniauth(auth)的屬性auth有關。你應該設置你的服務器日誌binding.pryputs auth所以看到這個變量的樣子..

也許當self.from_amniauth(auth)方法運行此auth.slice()它在某種程度上錯誤運行

另外,first_or_create方法可以創建用戶你可能會錯過一些東西,引發錯誤。所以嘗試使用調試顯示使用user.errors.full_messages

想法聽到的是,該方法的目的是找到User或創建它。它正在從控制器動作Users::OmniauthCallbacksController#facebook

request意味着這是從你的服務器facebooktwitter卸任request叫..

Facebook或Twitter將回復此requestAJAX response,其中將包括信息你需要認證用戶。

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 
    def facebook 
    # You need to implement the method below in your model (e.g. app/models/user.rb) 
    @user = User.from_omniauth(request.env["omniauth.auth"]) 

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

    def failure 
    redirect_to root_path 
    end, you probably saved the env variable 
end 

然後用下面的方法where(provider: auth.provider, uid: auth.uid).first_or_create你要麼在userfind它從你的數據庫創建。問題是你可能從https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

編寫這個方法錯誤或錯誤的參數調用它,或者你沒有建立api與Twitter正常工作......

這個動作有值得描述的幾個方面:

OmniAuth從Facebook檢索到的所有信息均可作爲request.env [「omniauth.auth」]的散列使用。檢查OmniAuth文檔和每個omniauth-facebook gem的README,以瞭解哪些信息正在返回。

找到有效用戶後,可以使用兩種Devise方法之一登錄:sign_in或sign_in_and_redirect。傳遞:event =>:認證是可選的。你應該這樣做,如果你想使用守望者回調。

也可以使用Devise的默認消息之一設置一個flash消息,但這取決於您。

如果用戶未被保存,我們將OmniAuth數據存儲在會話中。注意我們使用「設計」來存儲這些數據。作爲鍵名稱空間。這很有用,因爲Devise刪除了所有以「設計」開頭的數據。無論何時用戶登錄,都會從會話中清除,因此我們會自動清理會話。最後,我們將用戶重定向到我們的註冊表單。

控制器被定義之後,我們需要實現from_omniauth方法在我們的模型(例如應用程序/模型/ user.rb):

def self.from_omniauth(auth) 
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user| 
    user.email = auth.info.email 
    user.password = Devise.friendly_token[0,20] 
    user.name = auth.info.name # assuming the user model has a name 
    user.image = auth.info.image # assuming the user model has an image 
    # If you are using confirmable and the provider(s) you use validate emails, 
    # uncomment the line below to skip the confirmation emails. 
    # user.skip_confirmation! 
    end 
end 

這種方法試圖找到現有用戶由提供者和uid字段。如果找不到用戶,則使用隨機密碼和一些額外信息創建一個新用戶。請注意,first_or_create方法在創建新用戶時自動設置提供者和uid字段。 first_or_create!方法的操作方式相似,只是如果用戶記錄未通過驗證,它將引發異常。