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 |