2013-03-22 2 views
4

내 기능은 다음과 같습니다Ruby에서이 작은 DSL을 만드는 방법은 무엇입니까?

def hello(str) 
    puts "hello #{str}" 
end 

def hello_scope(scope, &block) 
    # ??? 
end 

나는 일시적으로 내 방법의 블록 내에서 기능을 증대하고 싶습니다.

hello_scope에서 나는 원래 hello 방법으로 전달하기 전에 str 문자열 앞에 scope 문자열을 추가하기 만하면됩니다. 여기에 예제가 있습니다 :

hello 'world'    #=> hello world 

hello_scope "welcome!" do 
    hello 'bob'    #=> welcome!hello bob 
    hello 'alice'    #=> welcome!hello alice 
end 

저는 루비에서 이런 종류의 일에 관해서 일종의 멍청한 짓입니다. 누군가가 나를 우아한 방식으로 해결하도록 도울 수 있습니까?


편집 :

hello_scope "welcome!" do |h| 
    h "bob"      #=> welcome!hello bob 
    h "alice"     #=> welcome!hello alice 
end 
+1

당신은 아마'hello' 방법을 다시 작성하지 않고도 멋지게 할 수 없습니다. –

+0

@AndrewMarshall 편집을했습니다. 이 일이 더 실현 가능합니까? – naomik

답변

4

한 가지 방법은을 만드는 것입니다 : 우리가 같은 블록에 대한 인수로 방법을 전달하는 경우

이 일을 더 쉽게 만드는 경우, 괜찮아요 블록이 인스턴스 평가 될 "평가 컨텍스트 개체"입니다. 이 객체는 블록과 관련된 모든 메소드를 제공해야합니다. 아래 예제에서 전역 메서드 "hello"를 명시 적으로 참조하는 방법을 기억하지 못하기 때문에 동일한 이름을 사용하지 않았습니다 (무한 재귀를 피하기 위해). 적절한 라이브러리에서 "hello"는 클래스 메소드로 정의 될 수 있으므로 문제가되지 않습니다. 예를

def hello(str) 
    puts "hello #{str}" 
end 
class HelloScope 
    def h(str) 
    print scope 
    hello(str) 
    end 
end 
def hello_scope(scope, &block) 
    HelloScope.new(scope).instance_eval(&block) 
end 
0

그냥 계정 현재 범위에 적용하려면 "안녕하세요"방법을 수정 들어

는 :

class Greeter 
    def initialize 
    @scope = nil 
    end 

    def hello(str) 
    puts "#{@scope}hello #{str}" 
    end 

    def with_scope(scope) 
    @scope = scope 
    yield 
    @scope = nil 
    end 
end 

Greeter.new.instance_eval do 
    hello 'world'    #=> hello world 

    with_scope "welcome!" do 
    hello 'bob'    #=> welcome!hello bob 
    hello 'alice'    #=> welcome!hello alice 
    end 
end 
관련 문제