2011-07-28 4 views
5

[루비 1.8]런타임에 인스턴스 메서드를 동적으로 만드는 방법은 무엇입니까?

내가 있다고 가정 :

dummy "string" do 
    puts "thing" 
end 

지금,이 입력 인수로 한 문자열과 하나 개의 블록을 보유하는 방법을 호출한다. 좋은.

이제는 비슷한 호출 (다른 메서드 이름, 동일한 인수)을 많이 가질 수 있다고 가정합니다. 예 :

otherdummy "string" do 
    puts "thing" 
end 

이제는 동일한 작업을 수행하고 수백 가지 일 수 있기 때문에 원하는 클래스에서 각 인스턴스에 대해 인스턴스 메서드를 만들지는 않습니다. 차라리 일반적인 규칙에 따라 런타임에 동적으로 메서드를 정의하는 현명한 방법을 찾고 싶습니다.

그럴 수 있습니까? 어떤 기술이 일반적으로 사용됩니까?

감사

답변

8

당신이 사용하고자하는 코드는 다양한 메소드 호출에 걸쳐 매우 비슷합니다 특히, method_missing를 사용하여 특히 좋아입니다.

class ActiveRecord::Base 
    def method_missing(meth, *args, &block) 
    if meth.to_s =~ /^find_by_(.+)$/ 
     run_find_by_method($1, *args, &block) 
    else 
     super # You *must* call super if you don't handle the 
      # method, otherwise you'll mess up Ruby's method 
      # lookup. 
    end 
    end 

    def run_find_by_method(attrs, *args, &block) 
    # Make an array of attribute names 
    attrs = attrs.split('_and_') 

    # #transpose will zip the two arrays together like so: 
    # [[:a, :b, :c], [1, 2, 3]].transpose 
    # # => [[:a, 1], [:b, 2], [:c, 3]] 
    attrs_with_args = [attrs, args].transpose 

    # Hash[] will take the passed associative array and turn it 
    # into a hash like so: 
    # Hash[[[:a, 2], [:b, 4]]] # => { :a => 2, :b => 4 } 
    conditions = Hash[attrs_with_args] 

    # #where and #all are new AREL goodness that will find all 
    # records matching our conditions 
    where(conditions).all 
    end 
end 

define_method 작동하는 것처럼도 보이는 : 누군가가 method_missing이 boo에, boo으로 인수라고, x.booboo이 존재하지 않는 호출 (선택 사항) 블록마다 - 여기이 site의 예입니다 당신을 위해, 그러나 나는 그것에 관한 경험이 method_missing보다 적습니다. 동일한 링크의 예는 다음과 같습니다.

%w(user email food).each do |meth| 
    define_method(meth) { @data[meth.to_sym] } 
end 
+0

감사합니다. 나는'method_missing'으로 선험적으로 알지 못하는 메소드가 될 것입니다. –

6

예, 몇 가지 옵션이 있습니다.

첫 번째는 method_missing입니다. 첫 번째 인수는 호출 된 메서드 인 기호이며 나머지 인수는 사용 된 인수입니다.

class MyClass 
    def method_missing(meth, *args, &block) 
    # handle the method dispatch as you want; 
    # call super if you cannot resolve it 
    end 
end 

다른 옵션은 필요한 메소드가 무엇인지 미리 아는 경우 런타임에 인스턴스 메소드를 동적으로 작성하는 것입니다. 이것은 클래스에서 수행하고, 하나의 예는 다음과 같다되어야한다

class MyClass 
    1.upto(1000) do |n| 
    define_method :"method_#{n}" do 
     puts "I am method #{n}!" 
    end 
    end 
end 

런타임에 새로운 인스턴스 메소드를 만들 필요가있는 클래스 메서드 호출 define_method을하는 일반적인 패턴이다.

+0

나는 그것이'puts "일 것이라고 생각한다. 나는 방법 # {n}이다!"'. 어쨌든, 좋은 대답! –

+0

고쳐 주셔서 감사합니다! –

+0

감사합니다. 매우 감사. –

3

사용 define_method :

class Bar 
end 

bar_obj = Bar.new 

class << bar_obj 
define_method :new_dynamic_method do 
    puts "content goes here" 
end 
end 

bar_obj.new_dynamic_method 

출력 : 유용한 예 (나는 그런 식으로 메소드 이름을 관리하는 것이 필요)에 대한

content goes here 
관련 문제