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