【问题标题】:What is the best way to separate common logic from Controllers将通用逻辑与控制器分离的最佳方法是什么
【发布时间】:2017-04-10 12:05:06
【问题描述】:

我在下面有这个逻辑。两个控制器的动作内部具有相同的逻辑。 common_logic1 common_logic2 common_logic3,我想分离通用逻辑但不知道该怎么做。

class ServicesController < ApplicationController
  ...
  def download
    some_logic_for_services
    common_logic1
    common_logic2
    common_logic3
  end
  ...
end

class PackagesController < ApplicationController
  ...
  def download
    some_logic_for_packages
    common_logic1
    common_logic2
    common_logic3
  end
  ...
end

第一种方法是为 ApplicationController 创建方法并继承它。 但我认为这种方式走到了fat applicationController的尽头。

class ApplicationController < ActionController::Base
  ...
  def common_logic
    common_logic1
    common_logic2
    common_logic3
  end
  ...
end

class ServicesController < ApplicationController
  ...
  def download
    some_logic_for_services
    common_logic
  end
  ...
end

class PackagesController < ApplicationController
  ...
  def download
    some_logic_for_packages
    common_logic
  end
  ...
end

第二种方法是将逻辑分离到辅助模块并包含它。但我认为 helper 是用于将逻辑与视图分离。

module CommonHelper
  ...
  def common_logic
    common_logic1
    common_logic2
    common_logic3
  end
  ...
end

class ServicesController < ApplicationController
  include CommonHelper
  ...
  def download
    some_logic_for_services
    common_logic
  end
  ...
end

class PackagesController < ApplicationController
  include CommonHelper
  ...
  def download
    some_logic_for_packages
    common_logic
  end
  ...
end

将逻辑分离到 ActiveSupport::Concern 的第三种方式,我认为这种选择在这种情况下是最好的。

module Commonable
  extend ActiveSupport::Concern
  ...
  def common_logic
    common_logic1
    common_logic2
    common_logic3
  end
  ...
end

class ServicesController < ApplicationController
  include Commonable
  ...
  def download
    some_logic_for_services
    common_logic
  end
  ...
end

class PackagesController < ApplicationController
  include Commonable
  ...
  def download
    some_logic_for_packages
    common_logic
  end
  ...
end

谁能告诉我这三种方法的优缺点。或者如果有更好的解决方法,请教我。谢谢。

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    Rails 方式是ActiveSupport::Concern。您也可以将其添加到ApplicationController

    在某些情况下,您可以使用服务方式 - 如果您的逻辑只做一件事,您可以将其移至单独的类。 例如,我们共享了检查用户余额并通知是否为负数的代码。

    如果希望将所有服务保留在app/services 文件夹中,则需要添加到 application.rb 中的 autoload_path

    config.autoload_paths += %W(#{config.root}/lib #{config.root}/app/services)

    创建类CheckUserBalance

    class CheckUserBalance
      def initialization(user)
        @user = user
      end
    
      def call
        unless @user.balance < 0
          #notify about negative balance and change user's status
        end
      end
    end
    

    在控制器中,我们称之为服务。

    CheckUserBalance.new(current_user).call
    

    【讨论】:

    • 谢谢。什么情况下使用 ActiveSupport::Concern 和 Service Layer。如何区分它们?
    • 服务层用于业务逻辑。服务类可用于控制器、模型或 rake 任务。当代码具有与控制器相关的方法(重定向、参数...)时,使用 ActiveSupport::Concern。
    猜你喜欢
    • 1970-01-01
    • 2019-01-22
    • 2013-07-08
    • 1970-01-01
    • 2015-05-15
    • 2010-11-04
    • 2020-04-26
    • 1970-01-01
    • 2010-09-28
    相关资源
    最近更新 更多