将通用逻辑与控制器分开的最佳方法是什么?

时间:2017-04-10 12:05:07

标签: ruby-on-rails

我在下面有这个逻辑。两个控制器的动作内部具有相同的逻辑。 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制作方法并继承它。 但我认为这种方式可以用于胖的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

第二种方法是将逻辑分离到辅助模块并包含它。但我认为帮助是将逻辑从视图中分离出来。

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

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

1 个答案:

答案 0 :(得分: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