From: rcoder Date: 2006-01-04T05:12:58+09:00 Subject: Re: DSL help? Below is just my 20-minute version -- consider it a source of ideas for doing a more complete DSL, not a real library. With it, you can do something like the following: q = Query.new do foo == 'bar' => exact value baz <=> (1..100) => 'between' woo =~ 'substri%' => 'like' fiz < 10 => lt, gt, leq, geq, etc., should all "just work" end q.to_sql => ["foo = ? AND baz BETWEEN ? AND ? AND fiz < ?", ["bar", 1, 100, 10]] (#to_sql returns query and array of bind params) # query.rb class Clause attr_reader :name, :test, :value def initialize(name) @name = name end def ==(other) @test = :equals @value = other end def =~(pattern) @test = :like @value = pattern end def <=>(range) @test = :between @value = range end def to_sql case @test when :equals ["#{@name} = ?", @value] when :like ["#{@name} LIKE ?", @value] when :between ["#{@name} BETWEEN ? AND ?", [@value.begin, @value.end]] else ["#{@name} #{@test} ?", @value] end end def method_missing(name, *args) @test = name @value = args.first end end class Query attr_reader :vars def initialize(&block) @vars = [] instance_eval(&block) end def method_missing(name, *args) puts "Query#method_missing(#{([name]+args).join(', ')})" if $DEBUG cv = Clause.new(name) @vars << cv cv end def to_sql(bool='AND') params = [] query = [] @vars.each do |cv| q,p = cv.to_sql query << q params << p end [query.join(" #{bool} "), params.flatten] end end