2010-05-29 4 views
3

내가 나를루비 메타 프로그래밍

Policy.name do 
author "Foo" 
reviewed_by "Bar" 
end 

은 다음 코드는 거의 처리 할 수 ​​있습니다 할 수있는 DSL 작성하려고 해요 :

class Policy 
    include Singleton 
    def self.method_missing(name,&block) 
     puts name 
     puts "#{yield}" 
    end 
    def self.author(name) 
    puts name 
    end 
    def self.reviewed_by(name) 
    puts name 
    end 
end 

클래스 메소드로 내 방법을 정의를 (self.method_name) 다음 구문을 사용하여 액세스 할 수 있습니다.

Policy.name do 
Policy.author "Foo" 
Policy.reviewed_by "Bar" 
end 

메서드 이름에서 "self"를 제거하고 원하는 구문을 사용하면 모듈 "Kernel"까지 내 함수를 찾을 수 없으므로 "Method not Found"오류가 Main에 나타납니다. 그 ok, 나는 그 오류를 이해한다. 하지만 어떻게 해결할 수 있습니까? 클래스를 수정하여 원하는 구문으로 작동하도록하려면 어떻게해야합니까?

답변

4

self이 (authorself.author으로 바뀌므로) 어떤 범위에 속하는지 제어하려면 instance_eval을 사용할 수 있습니다.

class Policy 
    def self.name(&block) 
    PolicyNameScope.new(block) 
    end 

    class PolicyNameScope 
    def initialize(block) 
     instance_eval(&block)  
    end 

    def author(author) 
     @author = author 
    end 

    def reviewed_by(reviewed_by) 
     @reviewed_by = reviewed_by 
    end 
    end 
end 

policy = Policy.name do 
    author "Dawg" 
    reviewed_by "Dude" 
end 

p policy 
# => #<Policy::PolicyNameScope:0x7fb81ef9f910 @reviewed_by="Dude", @author="Dawg"> 

PolicyNameScope 클래스 name 블록에서 허용되는 인스턴스 메소드를 갖는다. 이는 Policy의 메소드를 블록 내부에서 사용할 수 없기 때문에 DSL을 훨씬 더 엄격하게 만듭니다.

예제가 문맥에 어긋나므로 더 이상 당신을 도울 수 없으므로이 코드는 그다지 유용하지 않습니다.

+0

안녕하세요, 저는 8 월에 루비 메타 프로그래밍을 사용하고 있는데 예제와 설명이 도움이되었습니다. StackOverflow 규칙! –

1

8 월에 제안 된 위의 대답은 정확하지만 다른 목적으로 생성자를 사용하려는 경우 위의 방법이 실패합니다. 따라서이 경우 위에서 설명한 이외의 다른 방법을 사용해야합니다. 다음은 클래스 생성자를 사용하지 않고 준비한 솔루션입니다.

class Policy 

    def self.method_missing(name,&block) 
    self.class_eval(&block) 
    end 
    def self.author(name) 
    p name 
    end 
    def self.reviewed_by(name) 
    p name 
    end 

end 

Policy.name do 
    author "Foo" 
    reviewed_by "Bar" 
end 

이것은 최적화 된 솔루션이 아니며 명시된 문제에 대한 해결책입니다.

관련 문제