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)。すべての returntrueまたはfalseは、各クラスで常に同じであり、それらの間に関係はありません。

これらのクラスをリファクタリングする適切な方法は何ですか?


:現時点では、各クラスに次のモジュールを含めることでクラスをリファクタリングすることを考えています。

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

I would use a metaprogramming solution to clean this up somewhat.

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

And in your models:

class MyModel < ActiveRecord::Base
  include BetterCode

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

Instances of MyModel will then respond to great_method with a boolean value indicating whether or not foo, bar, baz and quux are all true.

于 2012-12-18T05:53:04.670 に答える
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 に答える
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 に答える