解决Devise集成Omniauth时Rails视图中路径的NameError问题
问题描述
在Rails(结合Spree)应用中实现Omniauth认证时,遇到NameError,提示视图中的Omniauth路径方法未定义。相关代码如下:
视图代码
<div class="social_login"> <div class=""> <%= link_to "Sign in with Facebook", user_facebook_omniauth_authorize_path, type: "button", class: "social_box fb" %> <%= link_to "Sign in with Google", user_google_oauth2_omniauth_authorize_path, type: "button", class: "social_box google" %> </div> </div>
routes.rb配置
devise_for(:user, { class_name: 'Spree::User', singular: :spree_user, controllers: { sessions: 'user_sessions', registrations: 'user_registrations', passwords: 'user_passwords', confirmations: 'user_confirmations', omniauth_callbacks: 'users/omniauth_callbacks' },
omniauth_controller.rb代码
class OmniauthController < ApplicationController def facebook @user = Spree::User.create_from_provider_data(request.env['omniauth.auth']) if @user.persisted? sign_in_and_redirect @user else flash[:error] = 'There was a problem signing you in through Facebook. Please register or try signing in later.' redirect_to new_spree_user_registration_url end end def google_oauth2 @user = Spree::User.create_from_provider_data(request.env['omniauth.auth']) if @user.persisted? sign_in_and_redirect @user else flash[:error] = 'There was a problem signing you in through Google. Please register or try signing in later.' redirect_to new_spree_user_registration_url end end def failure flash[:error] = 'There was an error signing you in. Please try again.' redirect_to root_path end end
需要解决:如何正确引用视图中的Omniauth路径?正确路径是什么?如何确保路径被正确定义?
解决方案
1. 修正视图中的路径名称
因为你在devise_for配置里指定了singular: :spree_user,所以Omniauth路由的前缀是spree_user而非user。视图中的路径需要修改为:
<%= link_to "Sign in with Facebook", spree_user_facebook_omniauth_authorize_path, type: "button", class: "social_box fb" %> <%= link_to "Sign in with Google", spree_user_google_oauth2_omniauth_authorize_path, type: "button", class: "social_box google" %>
2. 确认路由是否正确生成
运行以下命令查看实际生成的Omniauth路由:
rails routes | grep omniauth
输出结果中应该包含类似这样的路由:
spree_user_facebook_omniauth_authorize GET|POST /users/auth/facebook(.:format) users/omniauth_callbacks#passthru spree_user_facebook_omniauth_callback GET|POST /users/auth/facebook/callback(.:format) users/omniauth_callbacks#facebook spree_user_google_oauth2_omniauth_authorize GET|POST /users/auth/google_oauth2(.:format) users/omniauth_callbacks#passthru spree_user_google_oauth2_omniauth_callback GET|POST /users/auth/google_oauth2/callback(.:format) users/omniauth_callbacks#google_oauth2
如果没有这些路由,说明Omniauth配置不完整。
3. 补全并修正路由配置
你提供的routes.rb代码末尾缺少闭合的}和end,先补全:
devise_for(:user, { class_name: 'Spree::User', singular: :spree_user, controllers: { sessions: 'user_sessions', registrations: 'user_registrations', passwords: 'user_passwords', confirmations: 'user_confirmations', omniauth_callbacks: 'users/omniauth_callbacks' } })
4. 修正控制器命名与路径
你的路由指定了omniauth_callbacks: 'users/omniauth_callbacks',这意味着控制器需要:
- 文件路径:
app/controllers/users/omniauth_callbacks_controller.rb - 类名:
Users::OmniauthCallbacksController
修改控制器代码如下:
class Users::OmniauthCallbacksController < ApplicationController def facebook @user = Spree::User.create_from_provider_data(request.env['omniauth.auth']) if @user.persisted? sign_in_and_redirect @user else flash[:error] = 'There was a problem signing you in through Facebook. Please register or try signing in later.' redirect_to new_spree_user_registration_url end end def google_oauth2 @user = Spree::User.create_from_provider_data(request.env['omniauth.auth']) if @user.persisted? sign_in_and_redirect @user else flash[:error] = 'There was a problem signing you in through Google. Please register or try signing in later.' redirect_to new_spree_user_registration_url end end def failure flash[:error] = 'There was an error signing you in. Please try again.' redirect_to root_path end end
5. 确保Devise Omniauth初始化配置
在config/initializers/devise.rb中添加Omniauth provider配置(替换为你的实际密钥):
config.omniauth :facebook, 'YOUR_FACEBOOK_APP_ID', 'YOUR_FACEBOOK_APP_SECRET' config.omniauth :google_oauth2, 'YOUR_GOOGLE_CLIENT_ID', 'YOUR_GOOGLE_CLIENT_SECRET'
只有添加了这些配置,Devise才会自动生成对应的Omniauth路由。
内容的提问来源于stack exchange,提问作者Afaq Shahid Khan
相关产品推荐
相关产品推荐

