跨两个Ruby模块继承/共享代码

时间:2018-01-09 07:05:41

标签: ruby-on-rails ruby class module dry

Noob在这里,寻求帮助干掉这个。我们假设module DoAThing看起来像这样:

module DoAThing
  class ExportNames
    def initialize(names, limit = 1000)
      @names = names
      @limit = limit
    end

    def perform
      awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
      awesome.generate_export(::ClassAwesome::EXPORT_DEFAULTS)
    end
  end
end

然后我想添加一个完全相同的模块,除了生成报告之外,我想传递一个不同的常量,所以像这样:

module DoASlightDifferentThing
  class ExportNames
    def initialize(names, limit = 1000)
      @names = names
      @limit = limit
    end

    def perform
      awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
      awesome.generate_export(::ClassAwesome::DIFFERENT_EXPORT_DEFAULTS)
    end
  end
end

我怎样才能优雅地干这个?字面上,我需要做的就是传递一个不同的常量,即我想交换EXPORT_DEFAULTS DIFFERENT_EXPORT_DEFAULTS

3 个答案:

答案 0 :(得分:4)

这通常被称为“依赖注入”,互联网上有很多关于这个主题的文章。主要方法是在调用#perform方法中接受一个参数:

module DoManyDifferentThings
  class ExportNames
    def initialize(names, limit = 1000)
      @names = names
      @limit = limit
    end

    def perform(report)
      awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
      awesome.generate_export(report)
    end
  end
end

并称之为:

DoManyDifferentThings::ExportNames.perform(
  ::ClassAwesome::EXPORT_DEFAULTS
)

报告方法是否应该具有预定义的签名,可以使用类继承:

module DoManyDifferentThings
  class ExportNames
    def initialize(names, limit = 1000)
      @names = names
      @limit = limit
    end

    def perform
      awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
      awesome.generate_export(self.class.constant_get('REPORT'))
    end
  end

  class ExportNames1 < ExportNames
    REPORT = ::ClassAwesome::EXPORT_DEFAULTS_1
  end

  class ExportNames1 < ExportNames
    REPORT = ::ClassAwesome::EXPORT_DEFAULTS_2
  end
end

或者,作为替代方案,可以声明一个方法在后代中被覆盖:

module DoManyDifferentThings
  class ExportNames
    def initialize(names, limit = 1000)
      @names = names
      @limit = limit
    end

    def perform
      awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
      awesome.generate_export(report)
    end

    protected

    def report
      raise "DO NOT CALL ME DIRECTLY"
    end
  end

  class ExportNames1 < ExportNames
    def report
      ::ClassAwesome::EXPORT_DEFAULTS_1
    end
  end

  class ExportNames2 < ExportNames
    def report
      ::ClassAwesome::EXPORT_DEFAULTS_2
    end
  end
end

答案 1 :(得分:2)

您可以将此常量作为参数移动,也可以使用ihneritance。

提供默认值作为参数

module DoAThing
  class ExportNames
    def initialize(names, limit = 1000, defaults = ::ClassAwesome::EXPORT_DEFAULTS)
      @names = names
      @limit = limit
      @defaults = defaults
    end

    def perform
      awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
      awesome.generate_export(@defaults)
    end
  end
end

不是调用DoASlightDifferentThing :: ExportNames,而是执行:

DoAThing::ExportNames.perform_now(names, 1000, ::ClassAwesome::DIFFERENT_EXPORT_DEFAULTS)

<强> Ihneritance

或者您可以使用ihneritance添加一个将被覆盖的默认方法:

module DoAThing
  class ExportNames
    def initialize(names, limit = 1000)
      @names = names
      @limit = limit
    end

    def perform
      awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
      awesome.generate_export(defaults)
    end

    def defaults
      ::ClassAwesome::EXPORT_DEFAULTS
    end
  end
end

module DoASlightDifferentThing
  class ExportNames < DoAThing::ExportNames
    def defaults
      ::ClassAwesome::DIFFERENT_EXPORT_DEFAULTS
    end
  end
end

答案 2 :(得分:0)

如果两个类的命名空间可以相同,那么通过重写这样的代码来清理代码

module DoAThing
  class ExportNames
    def initialize(names, limit = 1000)
      @names = names
      @limit = limit
    end

    def perform(value)
      awesome = ::ClassAwesome.sort_names(names, per_page: @limit)
      awesome.generate_export(value)
    end
  end
end 

现在我打电话给

DoAThing::ExportNames.new('your names').perform(::ClassAwesome::EXPORT_DEFAULTS)
DoAThing::ExportNames.new('your names').perform(::ClassAwesome::DIFFERENT_EXPORT_DEFAULTS)
相关问题