如何重构实现类似方法的模型类?

时间:2012-12-18 01:20:39

标签: ruby-on-rails ruby interface refactoring

我正在使用Ruby on Rails 3.2.9和Ruby 1.9.3。我有许多模型类实现类似的方法,如下所示:

class ClassName_1 < ActiveRecord::Base
  def great_method
    self.method_1
  end

  def method_1 ... end
end

class ClassName_2 < ActiveRecord::Base
  def great_method
    result_1 = self.method_1
    result_2 = self.method_2

    result_1 && result_2
  end

  def method_1 ... end
  def method_2 ... end
end

...

class ClassName_N < ActiveRecord::Base
  def great_method
    result_1 = self.method_1
    result_2 = self.method_2
    ...
    result_N = self.method_N

    result_1 && result_2 && ... && result_N
  end

  def method_1 ... end
  def method_2 ... end
  ...
  def method_N ... end      
end

这些模型类的行为几乎相同(相同),因为其中一些类型的接口具有更少或更多的方法。所有方法都有不同的名称(例如,method_1可以命名为barmethod_2可以命名为foo),所有方法都返回true或{{1}在每个类中,它们总是相同的,它们之间没有关系。

重构这些类的正确方法是什么?


注意:目前我正在考虑通过在每个模块中包含以下模块来重构类:

false

但我不知道这是否是实现我所期待的正确方法。此外,我不确定相关的优点和缺点......

3 个答案:

答案 0 :(得分:1)

看起来你走在正确的轨道上。如果method_n方法对于您的类是唯一的,那么只需将您已经拥有的模块构建到每个ClassNameN继承自的超类中:

class SuperClassName < ActiveRecord::Base
  def great_method
    #... what you have in your module
  end
end

class ClassNameN < SuperClassName
  def method_1 ... end
  def method_2 ... end
end

您可能还有其他方法可以根据method_n方法中的内容分解代码,但如果没有更多详细信息,则无法说出来。

答案 1 :(得分:1)

我会使用元编程解决方案来清理它。

module BetterCode
  extend ActiveSupport::Concern

  module ClassMethods
    def boolean_method(name, *components)
      define_method name do
        components.all? { |c| send c }
      end
    end
  end
end

在你的模特中:

class MyModel < ActiveRecord::Base
  include BetterCode

  boolean_method :great_method, :foo, :bar, :baz, :quux
end

MyModel的实例将以{布隆值}回复great_method,表示foobarbazquux都是真的。

答案 2 :(得分:0)

您可以使用以下内容抽象出great_method

require 'active_support/concern'

module Greatest
  extend ActiveSupport::Concern

  module ClassMethods
    attr_accessor :num_great_methods

    def has_great_methods(n)
      @num_great_methods = n
    end
  end

  def great_method
    (1..self.class.num_great_methods).each do |n|
      return false unless self.__send__("method_#{n}")
    end
    true
  end
end

class ClassName_3
  include Greatest

  has_great_method 3

  # stub out the "method_*" methods
  (1..3).each do |n|
    define_method "method_#{n}" do
      puts "method_#{n}"
      true
    end
  end
end

puts ClassName_1.new.greatest