Ruby on rails Rails中的控制器间通信

Ruby on rails Rails中的控制器间通信,ruby-on-rails,ruby,controller,Ruby On Rails,Ruby,Controller,我遇到的情况是在CallbackController上调用操作。我无法控制这一点,因为它是由一个框架规定的。为了响应此操作,我需要创建一个新的身份验证。我的AuthenticationController具有创建和销毁操作 我应该如何进行?在我看来,我的选择是: 将AuthenticationCOntroller的创建操作中的代码复制到我的CallbackController中(显然还远未完成) 直接从CallbackController调用create方法(这种控制器间的通信似乎不受欢迎) 将

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

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

  • 将AuthenticationCOntroller的创建操作中的代码复制到我的CallbackController中(显然还远未完成)
  • 直接从CallbackController调用create方法(这种控制器间的通信似乎不受欢迎)
  • 将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
    
    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散列和当前用户作为参数。重定向和设置闪光灯应保留在控制器中。如果其他人有其他建议,请在这里发布。