루비 프로젝트에 대해 "클래스없는 DSL"을 만드는 방법을 알아 내려고합니다. 단계 정의가 오이클 단계 정의 파일에 정의되어 있거나 경로가 Sinatra 응용 프로그램에 정의 된 것과 비슷합니다. 내가이 방법의 무리와 함께 글로벌 (Kernel
) 네임 스페이스를 오염하는 나쁜 습관이다 가정Ruby에서 클래스리스 DSL을 만드는 방법은 무엇입니까?
#sample.rb
when_string_matches /hello (.+)/ do |name|
call_another_method(name)
end
:
예를 들어, 내 모든 DSL 함수가 호출되는 파일을 갖고 싶어 내 프로젝트와 관련이 있습니다. 그래서 when_string_matches
과 call_another_method
메서드는 내 라이브러리에 정의되어 있고 sample.rb
파일은 어떻게 든 내 DSL 메서드의 컨텍스트에서 평가됩니다.
업데이트 : 다음은 이러한 DSL 방법은 현재 정의하는 방법의 예
방법이 서브 클래스되고있는 클래스에 정의 된 DSL은 (I 사이 이러한 방법을 다시 사용하는 방법을 찾으려면 간단한 DSL과 클래스 인스턴스) : 내 프로그램의 초기화 동안 일부 지점에서 그런
module MyMod
class Action
def call_another_method(value)
puts value
end
def handle(text)
# a subclass would be expected to define
# this method (as an alternative to the
# simple DSL approach)
end
end
end
가, 내가 sample.rb
파일을 구문 분석하고 이러한 작업을 저장할 나중에 실행되는 :
module MyMod
class Parser
# parse the file, saving the blocks and regular expressions to call later
def parse_it
file_contents = File.read('sample.rb')
instance_eval file_contents
end
# doesnt seem like this belongs here, but it won't work if it's not
def self.when_string_matches(regex, &block)
MyMod.blocks_for_executing_later << { regex: regex, block: block }
end
end
end
# Later...
module MyMod
class Runner
def run
string = 'hello Andrew'
MyMod.blocks_for_executing_later.each do |action|
if string =~ action[:regex]
args = action[:regex].match(string).captures
action[:block].call(args)
end
end
end
end
end
내가 지금까지 가지고있는 문제 (그리고 위에서 언급하지 않은 여러 가지 것들)는 블록이 파일에 정의되어있을 때 인스턴스 메서드를 사용할 수없는 경우입니다. 그것은 지금 다른 수업에 있습니다). 하지만 내가하고 싶은 것은 Parser
클래스의 eval'ing보다는 인스턴스를 만들고 eval'ing하는 것입니다. 그러나 나는 이것을 어떻게하는지 모른다.
나는 그것이 의미가 있기를 바랍니다. 도움, 경험 또는 조언을 주시면 감사하겠습니다.
def when_string_matches(regex)
# do whatever is required to produce `my_string` and `name`
yield(name) if my_string =~ regex
end
:
그 중 일부는 내 머리 위로 조금씩 이어져 있기 때문에 거기에서 소화해야 할 부분이 많지만 여전히 유용합니다. 감사! – Andrew