【问题标题】:Ruby - Moving rails 'business logic' into service modulesRuby - 将 rails 的“业务逻辑”移动到服务模块中
【发布时间】:2015-07-25 21:26:18
【问题描述】:

我想按照正确的 OOP 协议将一些 Rails 业务逻辑移动到服务中。我按照这里推荐的方法:Private module methods in Ruby

最终,我想将业务逻辑从模型和控制器转移到服务中,这些服务是普通的旧 Ruby 对象。因此,模型只关心持久性、范围和验证。

这是制作服务模块的正确方法吗?

版本 2:

module CategorizeJobs

  def self.fetch( location, category_name )
    c = Categorizer.new( location, category_name )
    c.get_jobs
  end

  class Categorizer

    def initialize(location, category_name)
      @location = location
      @category_name = category_name
    end

    def get_jobs
      job_ids = get_correct_jobs
      Category.includes(:jobs).where( jobs: { id:  job_ids } )
    end

    private

      def get_correct_jobs
        jobs = filter_by_location
        jobs = filter_by_category(jobs)

        jobs.collect(&:id)
      end

      def filter_by_category(jobs)
        return jobs unless @category_name.present?

        category = Category.where(name: @category_name).first
        if category
          jobs = jobs.where(category: category)
        end

        jobs
      end

      def filter_by_location
        if @location.present?
          jobs = get_jobs_at_location
        else
          jobs = Job.open
        end
      end

      def get_jobs_at_location(location)
        Job.joins(:location).within(20, origin: @location).open
      end

  end

end

版本 1:

 module CategorizeJobs

  def self.fetch( location, category_name )
    c = Categorizer.new
    c.perform( location, category_name )
  end


  class Categorizer

    def perform( location, category_name )
      job_ids = get_correct_jobs(location, category_name)
      Category.includes(:jobs).where( jobs: { id:  job_ids } )
    end

    private

      def get_correct_jobs(location, category_name)
        jobs = filter_by_location(location)
        jobs = filter_by_category(jobs, category_name)

        jobs.collect(&:id)
      end

      def filter_by_category(jobs, category_name)
        return jobs unless category_name

        category = Category.where(name: category_name).first
        if category
          jobs = jobs.where(category: category)
        end

        jobs
      end

      def filter_by_location(location)
        if location
          jobs = get_jobs_at_location(location)
        else
          jobs = Job.open
        end
      end

      def get_jobs_at_location(location)
        Job.joins(:location).within(20, origin: location).open
      end

  end

end

【问题讨论】:

  • 你在问什么?
  • 糟糕 - 不小心删除了! “这是制作服务模块的正确方法吗?”
  • 您总是在传递位置和类别名称。为什么不创建一个初始化程序并将它们存储在变量中,这样你就不需要传递它们了?
  • 好主意!我将它们移到初始化程序中。

标签: ruby-on-rails ruby


【解决方案1】:

有一个名为 Aldous 的 gem,可以帮助您在 Rails 应用程序中实现基于服务对象的架构。看看吧。

如果您在如何使用它和构建您的应用程序方面需要更多帮助,您可以查看thisthis 以获得更多帮助。

【讨论】:

  • 谢谢!通读了-好主意。我不认为我想完全重新构建我的应用程序,我不知道这将如何与我正在使用的其他 gem 一起工作 - 我必须培训我在 Aldous 项目中引入的任何开发人员
  • @WillTaylor 无需重新设计您的应用程序或采用学习曲线来实现 gem。只需了解如何通过这些资源实现服务对象并破解您的项目。
猜你喜欢
  • 1970-01-01
  • 2012-05-06
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 2011-01-26
相关资源
最近更新 更多