Skip to content

Instantly share code, notes, and snippets.

@swistak
Created November 2, 2009 13:40
Show Gist options
  • Save swistak/224162 to your computer and use it in GitHub Desktop.
Save swistak/224162 to your computer and use it in GitHub Desktop.
require 'mh/blank_slate'
require 'mh/message_recorder'
module QueryBuilder
OPERATOR_MAP = {
:'<' => :lt,
:'<=' => :lte,
:'>=' => :gte,
:'>' => :gt,
:'=~' => :matches,
:like => :regex,
:[] => :inludes,
:'include?' => :includes,
}
def map_operator(operator, v)
if operator == :==
operator = case v
when Numeric then :numeq
when Regexp then :regex
else :eq
end
end
OPERATOR_MAP[operator] || operator
end
def sanitize_argument(v)
case v
when Regexp then v.inspect.split('/')[1..-2].join('/')
else v.to_s
end
end
def build_block_query(tokyo_query, &block)
core = MH::RecursiveMessageRecorder.new(true)
if block.arity == 0
core.__instance_eval__(&block)
elsif block.arity == 1
block.call(core)
else
block.call(core, tokyo_query)
end
result = []
queries = core.__flatten__
queries.each do |query|
name = query.first
query.last.each do |sub_query|
operator = sub_query[0]
arguments = sub_query[1].map{|a| sanitize_argument(a)}
operator = map_operator(operator, arguments.first)
result << [name, operator, *arguments]
end
end
result
end
def find(options={}, &block)
tokyo_query = Rufus::Tokyo::TableQuery.new(self)
if block
build_block_query(tokyo_query, &block).each do |result|
tokyo_query.add(*result)
end
else
if c = options.delete(:conditions)
c.each_pair do |k, v|
tokyo_query.add(k, map_operator(:==, v), sanitize_argument(v))
end
end
options.each_pair do |k,v|
tokyo_query.send(k, *v)
end
end
rs = tokyo_query.run
return rs.to_a
ensure
rs && rs.free
end
end
Rufus::Tokyo::Table.send(:include, QueryBuilder)
p @t.find {|t,q|
t.name =~ '.+'
q.limit 2
}
p @t.find(:conditions => {:name => /FOG/}, :limit => 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment