0

我正在使用 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),所有返回truefalse,在每个类中总是相同的,它们之间没有关系。

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


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

module MyModule
  def great_method
    result_1 = self.respond_to?(:method_1) ? self.method_1 : true
    result_2 = self.respond_to?(:method_2) ? self.method_2 : true
    ...
    result_N = self.respond_to?(:method_N) ? self.method_N : true

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

但我不知道这是否是完成我正在寻找的正确方法。此外,我不确定相关的优点和缺点......

4

3 回答 3

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 方法中发生的情况,您可能还有其他方法可以分解代码,但如果没有更多细节,就不可能说出来。

于 2012-12-18T01:48:34.353 回答
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指示foo、和是否都为真。barbazquux

于 2012-12-18T05:53:04.670 回答
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
于 2012-12-18T01:56:08.720 回答