Rails中的控制器间通信

时间:2012-01-25 15:41:56

标签: ruby-on-rails ruby controller

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

我该怎么办?在我看来,我的选择是:

  1. 将AuthenticationCOntroller的create action中的代码复制到我的CallbackController中(显然远离DRY)
  2. 直接从CallbackController调用create方法(这种控制器之间的通信似乎不受欢迎)
  3. 将AuthenticationController的create action中的代码分解为两个控制器共享的辅助类
  4. 这些似乎都不是正确的答案。那么有人可以提出更好的方法吗?

    我的回调控制器:

    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
    

1 个答案:

答案 0 :(得分:2)

如果您控制CallbackController和AuthenticationController的代码(它们不是来自框架),您可以将公共代码拉出到一个公共超类中。或者只是将其放在moduleinclude中。

我不是将整个createdestroy方法剪切并粘贴到一个新模块中,而是倾向于找到更小,连贯的部分并将它们放在具有有意义名称的方法中。可能是CallbackController和AuthenticationController上的createdestroy方法可以使用那些较小的方法在2行或3行中实现。

如果将相关的线组拉出到较小的方法中,您可以考虑将这些方法添加为ActionController::Base的扩展名(如果合适的话)。 (即如果它们足够通用。)如果小方法在应用程序的其他部分有用,那就是奖励。