2016-12-06 91 views
0

我已经在设计之上使用Google,Linkedin,DropboxGithub设置了更简单的社交用户认证。

的Dropbox认证不起作用,而是给出了回调URL
http://localhost:3000/users/auth/dropbox/callback)的错误:Rails 4:用户身份验证 - NoMethodError

NoMethodError in Users::OmniauthCallbacksController#dropbox 
undefined method `first' for nil:NilClass 

问题:用户模型(8号线)


我的代码:

回调控制器:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 

    def all 
     user = User.from_omniauth(env['omniauth.auth'], current_user) 
     if user.persisted? 
      sign_in user 
      flash[:notice] = t('devise.omniauth_callbacks.success', :kind => User::SOCIALS[params[:action].to_sym]) 
      if user.sign_in_count == 1 
       redirect_to edit_user_registration_path 
      else 
       redirect_to root_path 
      end 
     else 
      session['devise.user_attributes'] = user.attributes 
      redirect_to new_user_registration_url 
     end 
    end 

    User::SOCIALS.each do |k, _| 
     alias_method k, :all 
    end 

end 

用户模型:

# omniauth Gem 
def self.from_omniauth(auth, current_user) 
    authorization = Authorization.where(:provider => auth.provider, :uid => auth.uid.to_s, 
             :token => auth.credentials.token, 
             :secret => auth.credentials.secret).first_or_initialize 
    authorization.profile_page = auth.info.urls.first.last unless authorization.persisted? 
    if authorization.user.blank? 
     user = current_user.nil? ? User.where('email = ?', auth['info']['email']).first : current_user 
     if user.blank? 
      user = User.new 
      user.skip_confirmation! 
      user.password = Devise.friendly_token[0, 20] 
      user.fetch_details(auth) 
      user.save 
     end 
     authorization.user = user 
     authorization.save 
    end 
    authorization.user 
end 

def fetch_details(auth) 
    self.email = auth.info.email 
    self.username = auth.info.name 
    self.avatar = URI.parse(auth.info.image) 
end 

我感谢每个帮助!提前致谢。

回答

1

要直接回答您的问题: undefined method "first" for nil::NilClass正在发生,因为您正试图在空的或零对象上调用方法first

这可能是在您的用户模型中,您试图从current_user中找到用户。现在

if authorization.user.blank? user = current_user.nil? ? User.where('email = ?', auth['info']['email']).first : current_user #This will cause the error that you are describing if both the current_user is nil and there is no User whose email is auth['info']['email']

,有几件事情错。如果他们试图登录到你的应用程序,那么在这个阶段的current_user应该是未设置的。

你可以试试这个更改为

user = User.where(email: auth['info']['email']).first_or_create

这将创造用户的新实例,如果不与授权提供的电子邮件存在。 然后你就可以继续

user.persisted? 其现有用户返回true,false为用户的新实例

+0

我认为这个问题是在用户模式的第5行,因为错误仍然存​​在后我结合了你的建议。它似乎为Dropbox它以某种方式无法找到一个网址。 – jonhue

+0

所以,同样的原则适用。你在'auth.info.urls'上调用'.first',这意味着它是空的或者不存在。在这一行之前使用pry或byebug来调试使用pry或byebug来停止你的程序并检查auth是否实际返回,然后相应地调整你的代码。 –