Experimental Mongo support for ActiveRecord.
Here is an instructional video:
Experimental Mongo support for ActiveRecord.
Here is an instructional video:
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 |