Ruby DSL初探

Ruby 是当前用于建立内部 DSL 最流行的语言。当在 Ruby 上开发时你所考虑的大部分基础设施都是基于 DSL 的例如:Active Record、RSpec、Cucumber、Rake 以及许多其他方面,— 因为它是服从于主机托管内部 DSL 的。行为驱动开发 (BDD) 的新潮技术需要一个强大的 DSL 基础来实现其普及。Rails DSL很大程度上依赖于Ruby的元编程能力,这里将对Ruby的 DSL 写一个简单测试的例子,功能如下:


##首先给出测试脚本,新建test.txt文件:

host "www.baidu.com"
port 80
page "s"
field "wd","everyday-cn"
field "sourceid","Mozilla-search"
get
check_content "tang.jilong"
check_content "Tim.Tang"

##编写ruby dsl文件:

require 'open-uri'
class MyDSL
	def self.dsl_accessor(*symbols)
		symbols.each { |sym|
			class_eval %{
				def #{sym}(*val)
				  if val.empty?
				   @#{sym}
				  else
				   @#{sym} = val.size == 1 ? val[0] : val
				  end
				end
			}
		}
	end
	def method_missing(sym, *args)
		self.class.dsl_accessor sym
		puts "method missing #{sym}, #{args}"
		send(sym, *args)
	end
	attr_accessor :query
	dsl_accessor :test
	def self.load(filename)
		dsl = new
		dsl.instance_eval(File.read(filename), filename)
		puts File.read(filename)
		dsl
	end
	def self.loads(filename)
		dsl = new
		dsl.instance_eval(filename)
		dsl
	end
	def field(field_string,value)
		puts "#{field_string}=#{value}"
		if ! @query
			@query="#{field_string}=#{value}"
		else
			@query="#{@query}&#{field_string}=#{value}"
		end
		puts @query
	end
	def get
		puts 'get'
		@request="http://#{@host}:#{@port}/#{@page}?#{@query}"
		puts @request
		@result=open(@request)
	end
	def check_content(s)
		tmp=@result.read.scan(s).uniq
		if tmp.length!=0
			puts "found"
			puts tmp
		else
			puts "not found"
		end
	end
	def post
		puts 'post'
	end
end
dsl=MyDSL.load("dsl.txt")
p dsl
p dsl.instance_variables

##其中method_missing和dsl_accessor让客户端动态增删属性的功能

目前ruby dsl还主要用在测试领域,将来的发展潜力巨大。

174 Words 13 December 2011 Suzhou, China