Tôi đang cố gắng tìm ra cách tạo một loại "DSL ít lớp" cho dự án Ruby của tôi, tương tự như cách định nghĩa các bước được định nghĩa trong tệp định nghĩa bước dưa chuột hoặc các tuyến được định nghĩa trong ứng dụng Sinatra.Làm thế nào để tạo một DSL lớp ít trong Ruby?
Ví dụ, tôi muốn có một tập tin mà tất cả các chức năng DSL của tôi đang được gọi là:
#sample.rb
when_string_matches /hello (.+)/ do |name|
call_another_method(name)
end
tôi giả sử đó là một thực tế xấu để gây ô nhiễm (Kernel
) namespace toàn cầu với một loạt các phương pháp đó là cụ thể cho dự án của tôi. Vì vậy, các phương pháp when_string_matches
và call_another_method
sẽ được xác định trong thư viện của tôi và tệp sample.rb
bằng cách nào đó sẽ được đánh giá trong ngữ cảnh của các phương pháp DSL của tôi.
Cập nhật: Dưới đây là một ví dụ về cách các phương pháp DSL hiện đang định nghĩa:
DSL phương pháp được định nghĩa trong một lớp học đang được subclassed (Tôi muốn tìm một cách để tái sử dụng những phương pháp giữa DSL đơn giản và các trường hợp lớp):
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
sau đó, tại một số điểm, trong quá trình khởi tạo các chương trình của tôi, tôi muốn phân tích các tập tin sample.rb
và lưu trữ những hành động này được thực hiện sau:
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
Vấn đề với những gì tôi có cho đến nay (và những thứ khác nhau mà tôi đã thử mà tôi không đề cập ở trên) là khi một khối được định nghĩa trong tệp, phương pháp thể hiện không khả dụng (tôi biết rằng nó đang ở trong một lớp khác ngay bây giờ). Nhưng những gì tôi muốn làm là giống như tạo ra một thể hiện và đánh giá trong bối cảnh đó hơn là đánh giá trong lớp Parser
. Nhưng tôi không biết làm thế nào để làm điều này.
Tôi hy vọng điều đó có ý nghĩa. Bất kỳ trợ giúp, kinh nghiệm hoặc tư vấn nào sẽ được đánh giá cao.
Có rất nhiều thứ để tôi tiêu hóa ở đó vì một số trong số đó hơi hơn đầu tôi, nhưng nó vẫn hữu ích. Cảm ơn! – Andrew