Ruby on rails Rails中的控制器间通信
我遇到的情况是在CallbackController上调用操作。我无法控制这一点,因为它是由一个框架规定的。为了响应此操作,我需要创建一个新的身份验证。我的AuthenticationController具有创建和销毁操作 我应该如何进行?在我看来,我的选择是:Ruby on rails Rails中的控制器间通信,ruby-on-rails,ruby,controller,Ruby On Rails,Ruby,Controller,我遇到的情况是在CallbackController上调用操作。我无法控制这一点,因为它是由一个框架规定的。为了响应此操作,我需要创建一个新的身份验证。我的AuthenticationController具有创建和销毁操作 我应该如何进行?在我看来,我的选择是: 将AuthenticationCOntroller的创建操作中的代码复制到我的CallbackController中(显然还远未完成) 直接从CallbackController调用create方法(这种控制器间的通信似乎不受欢迎) 将
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
authorize
end
def twitter
authorize
end
private
def authorize
omniauth_data = request.env["omniauth.auth"]
#Check to see if we have an authentication for this provider already
authentication = Authentication.find_by_provider_and_uid(omniauth_data['provider'], omniauth_data['uid'])
#If an authentication already exists, sign its User in
#Otherwise create a new authentication for the current user
if authentication
flash[:notice] = "Signed in successfully with " + omniauth_data['provider']
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create(:provider => omniauth_data['provider'], :uid => omniauth_data['uid'])
flash[:notice] = "Authentication successful"
redirect_to user_profile_url
else
user = User.new
user.apply_omniauth_data_as_authentication(omniauth_data)
if user.save
flash[:notice] = "Signed in successfully with " + omniauth_data['provider']
sign_in_and_redirect(:user, authentication.user)
else
#save the omniauth data in a session so we can add the authentication once registration is complete
session[:omniauth] = omniauth_data.except('extra')
redirect_to new_user_registration_url
end
end
end
end
class AuthenticationsController < ApplicationController
#Controller for representing Authentications provided by
def index
current_user.authentications if current_user
end
def create
end
def destroy
@authentication = Authentication.find(params[:id])
provider = @authentication.provider
@authentication.destroy
flash[:notice] = "Destroyed authentication from "+provider
redirect_to authentications_url
end
end
class Users::OmniAuthCallbackControlleromniauth\u数据['provider'],:uid=>omniauth\u数据['uid'])
flash[:注意]=“身份验证成功”
将\重定向到用户\配置文件\ url
其他的
user=user.new
用户。将\u omniauth\u数据\u应用为\u身份验证(omniauth\u数据)
如果user.save
flash[:notice]=“使用”+omniauth_数据['provider'成功登录”
登录并重定向(:user,authentication.user)
其他的
#在会话中保存omniauth数据,以便在注册完成后添加身份验证
会话[:omniauth]=omniauth_数据。除('extra')外
将\重定向到新\用户\注册\ url
结束
结束
结束
结束
和我的身份验证控制器:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
authorize
end
def twitter
authorize
end
private
def authorize
omniauth_data = request.env["omniauth.auth"]
#Check to see if we have an authentication for this provider already
authentication = Authentication.find_by_provider_and_uid(omniauth_data['provider'], omniauth_data['uid'])
#If an authentication already exists, sign its User in
#Otherwise create a new authentication for the current user
if authentication
flash[:notice] = "Signed in successfully with " + omniauth_data['provider']
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create(:provider => omniauth_data['provider'], :uid => omniauth_data['uid'])
flash[:notice] = "Authentication successful"
redirect_to user_profile_url
else
user = User.new
user.apply_omniauth_data_as_authentication(omniauth_data)
if user.save
flash[:notice] = "Signed in successfully with " + omniauth_data['provider']
sign_in_and_redirect(:user, authentication.user)
else
#save the omniauth data in a session so we can add the authentication once registration is complete
session[:omniauth] = omniauth_data.except('extra')
redirect_to new_user_registration_url
end
end
end
end
class AuthenticationsController < ApplicationController
#Controller for representing Authentications provided by
def index
current_user.authentications if current_user
end
def create
end
def destroy
@authentication = Authentication.find(params[:id])
provider = @authentication.provider
@authentication.destroy
flash[:notice] = "Destroyed authentication from "+provider
redirect_to authentications_url
end
end
类身份验证控制器
如果您同时控制CallbackController和AuthenticationController的代码(它们不是来自框架),则可以将公共代码拉入公共超类。或者把它放在模块中
并包含它
与其将整个create
和destroy
方法剪切粘贴到一个新模块中,我更倾向于找到更小、连贯的部分,并将它们放在具有有意义名称的方法中。可能CallbackController和AuthenticationController上的create
和destroy
方法都可以使用这些较小的方法在2或3行中实现
如果你将连贯的一组线拉到更小的方法中,你可以考虑将这些方法作为一个扩展添加到<代码> ActhCuult::Base< /Cord>。(也就是说,如果它们足够通用。)如果小方法在应用程序的其他部分有用,那就是一个奖励。
谢谢。这难道不违背宁静的原则吗?我需要创建身份验证,所以不应该通过AuthenticationController的创建操作来完成吗?这样看起来更干净。如果你发布相关代码,我可以给出更具体的建议。正如我所建议的,如果您可以找到一些小的、连贯的片段,这些片段可以作为新的private
方法使用,并且可以添加到超类或与模块混合使用,这将减少CallbackController和AuthenticationController之间的重复。什么不是RESTful呢?REST基本上是将URI分配给资源(控制器),并以一致和通用的方式将操作(操作)映射到HTTP谓词。在您的例子中,您试图实现的是两个不同的资源(您的控制器)共享(一部分)相同的代码库。Alex建议的不同方法非常适合这种情况,并且不违反任何REST概念。@Alex D在我的问题中添加了两个控制器的代码。我想我是从两个角度来看这个问题的:1。在我看来,创建授权应该在授权控制器中完成是有道理的。从控制器的操作应该封装与授权的交互这一意义上讲,中断此功能似乎与其他功能背道而驰。还是我过于强调控制器?2.我完全理解您所说的关于共享代码并将其分解为更小、更可重用的部分的内容,我当然不会反对这一点。@1ndivisable,我相信您可以用不同的方法重构此代码。我想到的第一件事是向身份验证模型添加一个方法,该方法处理基于OmniAuth参数创建身份验证的所有逻辑。它将使用OmniAuth散列和当前用户作为参数。重定向和设置闪光灯应保留在控制器中。如果其他人有其他建议,请在这里发布。