Rails 中的控制器间通信

发布于 2024-12-28 16:50:30 字数 2427 浏览 0 评论 0原文

我遇到过在 CallbackController 上调用操作的情况。我无法控制它,因为它是由框架规定的。为了响应此操作,我需要创建一个新的身份验证。我的 AuthenticationController 有创建和销毁操作。

我应该如何进行?在我看来,我的选择是:

  1. 将 AuthenticationCOntroller 的创建操作中的代码复制到我的 CallbackController 中(显然离 DRY 很远)
  2. 直接从 CallbackController 调用创建方法(这种控制器间通信似乎不受欢迎)
  3. 打破代码从 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:

  1. Duplicate the code from AuthenticationCOntroller's create action into my CallbackController (Obviously far from DRY)
  2. Call the create method directly from the CallbackController (This kind of inter-controller-communication seems to be frowned on)
  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

末蓝 2025-01-04 16:50:30

如果您控制 CallbackController 和 AuthenticationController 的代码(它们不是来自框架),您可以将公共代码提取到公共超类中。或者只是将其放入模块中并包含它。

我不会将整个 createdestroy 方法剪切并粘贴到新模块中,而是倾向于找到更小、连贯的部分,并将它们放入具有有意义名称的方法中。使用这些较小的方法,CallbackController 和 AuthenticationController 上的 createdestroy 方法可能只需 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 and include it.

Rather than cut-and-pasting the entire create and destroy 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 the create and destroy 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文