Ruby 这样的 dsl 怎么写?

fsword · 2013年01月22日 · 最后由 mvj3 回复于 2014年01月05日 · 3561 次阅读

这样的 dsl 很容易实现

build_after :some_server do |server|
  server.add_service :my_service
end

如果想改为这样该怎么做呢?

build_after :some_server do
  add_service :my_service
end

这样吗?

class Build
  def add_service(service)
    p "add service #{service}"
  end
end

def build_after(server, &block)
  Build.new.instance_eval(&block) if block_given?
end

build_after :some_server do
  add_service :my_service
end
class Test
  def run(sym, &block)
    p sym
    instance_eval &block
  end

  def pp(str)
    p str
  end
end

t = Test.new
t.run :hi do
  pp :world
end

google

@saiga 学习了,刚好最近也在写 dsl。

然后这样子写就好了

class Server::Configuration 
  include Qor::Dsl

  node :build_after do
    node :my_service
  end
end

#1 楼 @kenshin54 #2 楼 @saiga 多谢,1 楼的做法可以分离一个 builder 对象,有助于理清关系,2 楼的方法比较简洁 #5 楼 @zhangjinzhu 哈哈,这个也很方便,不过我先试试最原始的方式,然后再简化

太巧了。这正好是我刚刚学习完的 codeschool 中 Ruby Bit 2 中的 dsl part 1 章节的内容。obj.instance_eval(&block) 会将 &block 中的 self 设置为调用他的对象,所以可以省去原来的 server. add_service 的前缀直接调用 add_service, 相当与 self.add_service

#7 楼 @wppurking 看来我也要学习一下 codeschool 了,果然不学习要落后

我这里有一个统计分析框架 statlysis 配置的实际例子,也是用的 instance_evalhttps://github.com/mvj3/statlysis/blob/master/lib/statlysis.rb#L34

实际效果比如:

Statlysis.setup do
  set_database :local_statistic

  daily UserRecord.where(item_type: "activity")
end

之前还有一个用来练手的 统计分析 DSL 设计,解决惰性加载 和 作用域 两个问题

需要 登录 后方可回复, 如果你还没有账号请 注册新账号