Rails 中的控制器间通信
我遇到过在 CallbackController 上调用操作的情况。我无法控制它,因为它是由框架规定的。为了响应此操作,我需要创建一个新的身份验证。我的 AuthenticationController 有创建和销毁操作。
我应该如何进行?在我看来,我的选择是:
- 将 AuthenticationCOntroller 的创建操作中的代码复制到我的 CallbackController 中(显然离 DRY 很远)
- 直接从 CallbackController 调用创建方法(这种控制器间通信似乎不受欢迎)
- 打破代码从 AuthenticationController 的创建操作到在两个控制器之间共享的帮助器类,
这些似乎都不是正确的答案。那么有人可以建议更好的方法吗?
我的回调控制器:
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
I have a situation where an action is called on a CallbackController. I have no control over this as it is prescribed by a framework. In response to this action I need to create a new Authentication. My AuthenticationController has create and a destroy actions.
How should I proceed? It seems to me my options are:
- Duplicate the code from AuthenticationCOntroller's create action into my CallbackController (Obviously far from DRY)
- Call the create method directly from the CallbackController (This kind of inter-controller-communication seems to be frowned on)
- Break the code from the AuthenticationController's create action out into a helper class which is shared between the two controllers
None of these seem like the correct answer. So can anyone suggest a better approach?
My callbacks controller:
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
and my authentications controller:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您控制 CallbackController 和 AuthenticationController 的代码(它们不是来自框架),您可以将公共代码提取到公共超类中。或者只是将其放入
模块
中并包含
它。我不会将整个
create
和destroy
方法剪切并粘贴到新模块中,而是倾向于找到更小、连贯的部分,并将它们放入具有有意义名称的方法中。使用这些较小的方法,CallbackController 和 AuthenticationController 上的create
和destroy
方法可能只需 2 或 3 行即可实现。如果您将连贯的行组拉出到更小的方法中,如果合适的话,您可以考虑将这些方法添加为
ActionController::Base
的扩展。 (即,如果它们足够通用。)如果这些小方法在应用程序的其他部分有用,那就是一个好处。If you control the code for both CallbackController and AuthenticationController (they're not coming from the framework), you could pull the common code out into a common superclass. Or just put it in a
module
andinclude
it.Rather than cut-and-pasting the entire
create
anddestroy
methods into a new Module, I would be inclined to find smaller, coherent parts and put them in methods with meaningful names. It may be that thecreate
anddestroy
methods on both CallbackController and AuthenticationController can be implemented in just 2 or 3 lines using those smaller methods.If you pull coherent groups of lines out into smaller methods, you could consider adding those methods as an extension to
ActionController::Base
if it seems appropriate. (i.e. if they are general enough.) If the small methods are useful in other parts of the application, that's a bonus.