ArgumentError: Wrong number of arguments in Google oauth callback
ArgumentError: Wrong number of arguments in Google oauth callback
我按照 this tutorial 将用户身份验证添加到我的 rails 应用程序。本教程使用 devise 和 google_oauth2.
当用户尝试使用 Google 登录时,用户在回调后遇到 ArgumentError。
错误:
用户模型和回调控制器之间出现问题,但我的滑雪板有点过头了,无法理解可能导致问题的原因。
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
devise :omniauthable, omniauth_providers: [:google_oauth2]
def self.from_google(email:, full_name:, uid:, avatar_url:)
create_with(uid: uid, full_name: full_name, avatar_url: avatar_url).find_or_create_by!(email: email)
end
end
omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
user = User.from_google(from_google_params)
if user.present?
sign_out_all_scopes
flash[:success] = t 'devise.omniauth_callbacks.success', kind: 'Google'
sign_in_and_redirect user, event: :authentication
else
flash[:alert] = t 'devise.omniauth_callbacks.failure', kind: 'Google', reason: "#{auth.info.email} is not authorized."
redirect_to new_user_session_path
end
end
protected
def after_omniauth_failure_path_for(_scope)
new_user_session_path
end
def after_sign_in_path_for(resource_or_scope)
stored_location_for(resource_or_scope) || root_path
end
private
def from_google_params
@from_google_params ||= {
uid: auth.uid,
email: auth.info.email,
full_name: auth.info.name,
avatar_url: auth.info.image
}
end
def auth
@auth ||= request.env['omniauth.auth']
end
end
我猜测 (!!) 你是 运行 最新版本的 ruby:3.0.0
,发布于2020 年 12 月,在编写该教程之后。
ruby 版本 3 中有一个重大的突破性变化:Keyword and positional arguments are now separated。
该错误非常微妙,但它的发生是因为您的代码正在执行此操作:
User.from_google(
{
uid: auth.uid,
email: auth.info.email,
full_name: auth.info.name,
avatar_url: auth.info.image
}
)
(即传递一个 Hash
给方法),而不是这个:
User.from_google(
uid: auth.uid,
email: auth.info.email,
full_name: auth.info.name,
avatar_url: auth.info.image
)
(即将 关键字参数 传递给方法。)
解决这个问题很简单:您可以使用“double-splat”运算符 (**
) 将散列转换为关键字参数:
user = User.from_google(**from_google_params)
如果您在学习这样的教程时不习惯对代码进行此类更正,那么使用较旧的 ruby 版本(例如 2.7
)应该也完全没问题。我上面显示的代码的“固定”版本将在所有 ruby 版本上正常工作。
我按照 this tutorial 将用户身份验证添加到我的 rails 应用程序。本教程使用 devise 和 google_oauth2.
当用户尝试使用 Google 登录时,用户在回调后遇到 ArgumentError。
错误:
用户模型和回调控制器之间出现问题,但我的滑雪板有点过头了,无法理解可能导致问题的原因。
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
devise :omniauthable, omniauth_providers: [:google_oauth2]
def self.from_google(email:, full_name:, uid:, avatar_url:)
create_with(uid: uid, full_name: full_name, avatar_url: avatar_url).find_or_create_by!(email: email)
end
end
omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
user = User.from_google(from_google_params)
if user.present?
sign_out_all_scopes
flash[:success] = t 'devise.omniauth_callbacks.success', kind: 'Google'
sign_in_and_redirect user, event: :authentication
else
flash[:alert] = t 'devise.omniauth_callbacks.failure', kind: 'Google', reason: "#{auth.info.email} is not authorized."
redirect_to new_user_session_path
end
end
protected
def after_omniauth_failure_path_for(_scope)
new_user_session_path
end
def after_sign_in_path_for(resource_or_scope)
stored_location_for(resource_or_scope) || root_path
end
private
def from_google_params
@from_google_params ||= {
uid: auth.uid,
email: auth.info.email,
full_name: auth.info.name,
avatar_url: auth.info.image
}
end
def auth
@auth ||= request.env['omniauth.auth']
end
end
我猜测 (!!) 你是 运行 最新版本的 ruby:3.0.0
,发布于2020 年 12 月,在编写该教程之后。
ruby 版本 3 中有一个重大的突破性变化:Keyword and positional arguments are now separated。
该错误非常微妙,但它的发生是因为您的代码正在执行此操作:
User.from_google(
{
uid: auth.uid,
email: auth.info.email,
full_name: auth.info.name,
avatar_url: auth.info.image
}
)
(即传递一个 Hash
给方法),而不是这个:
User.from_google(
uid: auth.uid,
email: auth.info.email,
full_name: auth.info.name,
avatar_url: auth.info.image
)
(即将 关键字参数 传递给方法。)
解决这个问题很简单:您可以使用“double-splat”运算符 (**
) 将散列转换为关键字参数:
user = User.from_google(**from_google_params)
如果您在学习这样的教程时不习惯对代码进行此类更正,那么使用较旧的 ruby 版本(例如 2.7
)应该也完全没问题。我上面显示的代码的“固定”版本将在所有 ruby 版本上正常工作。