Skip to content

Instantly share code, notes, and snippets.

@tenderlove
Created February 27, 2011 00:34
Show Gist options
  • Save tenderlove/845782 to your computer and use it in GitHub Desktop.
Save tenderlove/845782 to your computer and use it in GitHub Desktop.
readme
module Arel
module Visitors
###
# The Identity visitor returns anything passed to the `accept` method.
class Identity < Arel::Visitors::Visitor
def initialize engine
end
def accept ast
ast
end
end
end
end
module Arel
module Visitors
class Mongo < Arel::Visitors::Visitor
attr_reader :db
def initialize db
@db = db
end
Query = Struct.new(:collection_name, :fields, :conditions)
private
def visit_Arel_Nodes_SelectStatement o
o.cores.map { |c| visit_Arel_Nodes_SelectCore c }.map { |query|
collection = db.collection query.collection_name
fields = query.fields
selector = Hash[query.conditions]
opts = {}
opts[:fields] = fields unless fields.empty?
opts[:limit] = o.limit.expr.to_i if o.limit
collection.find(selector, opts).to_a
}.flatten
end
def visit_Arel_Nodes_SelectCore o
fields = o.projections.map { |proj| visit(proj) }.compact
conditions = o.wheres.map { |condition| visit(condition) }.flatten(1)
Query.new(visit(o.source), fields, conditions)
end
def visit_Arel_Nodes_And o
o.children.map { |child| visit child }
end
def visit_Arel_Nodes_Equality o
[visit(o.left), visit(o.right)]
end
def visit_Arel_Attributes_Attribute o
return if o.name == '*'
o.name
end
def visit_Arel_Nodes_JoinSource o
visit o.left
end
def visit_Arel_Table o
o.name
end
def literal o; o; end
alias :visit_String :literal
alias :visit_Fixnum :literal
end
end
end
require 'active_record/connection_adapters/abstract_adapter'
require 'arel/visitors/identity'
require 'arel/visitors/mongo'
# Ensure that to_sql returns the AST.
Arel::Visitors::VISITORS['mongo'] = Arel::Visitors::Identity
require 'mongo'
module ActiveRecord
class Base
def self.mongo_connection(config)
connection = Mongo::Connection.new
ConnectionAdapters::MongoAdapter.new(connection, logger, config)
end
end
module ConnectionAdapters
class MongoAdapter < AbstractAdapter
attr_reader :db
def initialize connection, logger, config
super(connection, logger)
@config = config
@db = connection.db config[:database]
end
###
# There is no concept of columns, so return an empty set.
def columns(table_name, name = nil)
[]
end
def table_exists? name
true
end
def primary_key table
"_id"
end
def select(ast, name = nil, binds = [])
visitor = Arel::Visitors::Mongo.new db
visitor.accept ast
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment