2012-12-18 2 views
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 

그 모델 클래스가 거의 같은 (하지 같은) 동작들 중 일부는 좀 덜 이상의 방법과 인터페이스를 가지고 있기 때문에 : 나는 다음과 같이 같은 유사한 방법을 구현하는 많은 모델 클래스가 있습니다. 모든 메서드의 이름이 다르게 지정되어 있습니다 (예 : 은 bar이고 method_2이라는 이름은 foo 임), 모두 true 또는 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 

을하지만 달성 할 수있는 적절한 방법입니다 나도 몰라 내가 찾고있는 것. 또한, 관련 장단점에 대한 확신이 없습니다 ...

+0

대신 상속을 사용하는 방법에 대해 생각해 보셨습니까? 하나의 메인 모델은'MainModel

+1

불행히도 최상의 추상화는 특정 도메인 모델에 따라 달라질 수 있으므로 도메인 모델에 대한 자세한 내용을 파악하는 데 도움이됩니다. 예를 들어,'method_1'은 항상 각 클래스에서 동일합니까? 'method_1'과'method_2'의 관계는 무엇입니까? –

+0

@ Vincent Paca - 상속이 좋지 않다고 생각합니다. – user12882

답변

1

제대로 된 것 같습니다. 당신이에 따라 코드를 고려하는 어떤 일이 일어나는지

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 방법을 수업에 고유 한 경우, 당신은 이미에서 각 ClassNameN이 상속 슈퍼 클래스에이 모듈을 구축 method_n 메소드에서,하지만 더 자세한 내용없이 말하는 것은 불가능합니다.

+1

상속에 '내 MyModule 포함'접근 방식에 비해 많은 단점이 있다고 생각합니다 (저뿐만 아니라 ...). 그것은 내가 후자의 접근법을 사용하여 코드를 리팩토링하려고 노력하고있는 것을위한 것입니다. – user12882

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 
+0

죄송 합니다만, 메소드는 * 다르게 * 이름이 붙습니다 (예를 들어,'method_1'은'bar','method_2'는'foo'로 명명 될 수 있습니다). – user12882

+0

'has_great_methods : foo, : bar'와 같이 호출 할 수 있도록'has_great_method'를'* args' 배열을 업데이트하기 만하면됩니다. 추상화가 많은 것처럼 보이지 않을 때 추상화가 줄어들 것입니다 . –

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 

그리고 당신의 모델

: MyModel

class MyModel < ActiveRecord::Base 
    include BetterCode 

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

인스턴스는 다음 foo, bar, bazquux에 모두 해당하는지 여부를 나타내는 부울 값을 great_method에 응답합니다.

+0

또는 좀 더 명확하게하기 위해'ActiveSupport :: Concern'을 사용하십시오. –

+0

내 대답을 편집하여'ActiveSupport :: Concern'을 사용했습니다. – Finbarr

관련 문제