【问题标题】:Rails 4: User Authentication - NoMethodErrorRails 4:用户身份验证 - NoMethodError
【发布时间】:2017-04-21 15:44:19
【问题描述】:

我使用 Google、Linkedin、DropboxGithub 在设计之上设置了一个更简单的社交用户身份验证。

Dropbox 身份验证不起作用,而是在回调 URL
(http://localhost:3000/users/auth/dropbox/callback) 上显示该错误:

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

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

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 authentication devise


    【解决方案1】:

    直接回答您的问题: undefined method "first" for nil::NilClass 正在发生,因为您试图在空对象或 nil 对象上调用方法 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,对于新的 User 实例返回 false

    【讨论】:

    • 我认为问题出在 User 模型的第 5 行,因为在我采纳您的建议后错误仍然存​​在。似乎对于 Dropbox,它以某种方式找不到 url。
    • 所以,同样的原则也适用。您在auth.info.urls 上调用.first,这意味着它要么是空的,要么不存在。使用 pry 或 byebug 在此行之前停止您的程序并检查 auth 实际返回的内容,然后相应地调整您的代码。
    猜你喜欢
    • 2016-04-12
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 2013-09-11
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多