Skip to content

Instantly share code, notes, and snippets.

@mharris717
Created November 17, 2009 19:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mharris717/237159 to your computer and use it in GitHub Desktop.
Save mharris717/237159 to your computer and use it in GitHub Desktop.
require 'rubygems'
require 'mharris_ext'
require 'mongo'
class OrderedHash
def reject(&b)
res = OrderedHash.new
each { |k,v| res[k] = v unless yield(k,v) }
res
end
end
class Object
def sos(m)
respond_to?(m) ? send(m) : self
end
end
class Object
def safe_to_mongo_hash
sos(:to_mongo_hash)
end
def safe_to_mongo_object
sos(:to_mongo_object)
end
end
class Array
def to_mongo_hash
map { |x| x.safe_to_mongo_hash }
end
def to_mongo_object
map { |x| x.safe_to_mongo_object }
end
end
module MongoHash
def to_mongo_object
return self unless self['_mongo_class']
cls = eval(self['_mongo_class'])
h = reject { |k,v| k == '_mongo_class' || k == '_id' }
cls.from_mongo_hash(h)
end
end
[Hash,OrderedHash].each { |cls| cls.send(:include,MongoHash) }
module MongoPersist
#can be overriden by class. If not, assumes that all instance variables should be saved.
def mongo_attributes
instance_variables.map { |x| x[1..-1] }
end
def to_mongo_hash
mongo_attributes.inject({}) { |h,attr| h.merge(attr => send(attr).safe_to_mongo_hash) }.merge("_mongo_class" => self.class.to_s)
end
def from_mongo_hash(h)
h = h.map_value { |v| v.safe_to_mongo_object }
from_hash(h)
end
def mongo_save!
self.class.collection.save(to_mongo_hash)
end
module ClassMethods
attr_accessor :collection
def from_mongo_hash(h)
new.tap { |x| x.from_mongo_hash(h) }
end
def mongo_connection(ops)
ops.each { |k,v| send("#{k}=",v) }
end
end
def self.included(mod)
super(mod)
mod.send(:extend,ClassMethods)
end
end
class ObjCursor
attr_accessor :cursor
include FromHash
def each
cursor.each { |x| yield(x.to_mongo_object) }
end
end
class Mongo::Collection
def find_objects(*args)
ObjCursor.new(:cursor => find(*args))
end
end
###### END LIBRARY, START CLIENT CODE THAT USES LIBRARY ###########
def get_coll
Mongo::Connection.new.db('test-db').collection('orders')
end
class Order
include FromHash
include MongoPersist
mongo_connection :collection => get_coll
attr_accessor :po_number
fattr(:products) { [] }
end
class Product
include FromHash
include MongoPersist
attr_accessor :sku, :price
end
Order.collection.remove
Order.new(:po_number => 1234, :products => [Product.new(:sku => 'ABC-454', :price => 50)]).mongo_save!
Order.new(:po_number => 1235, :products => [Product.new(:sku => 'ABC-455', :price => 50)]).mongo_save!
Order.collection.find_objects.each { |x| puts x.inspect }
#<Order:0x168e114 @products=[#<Product:0x168dc14 @price=50, @sku="ABC-455">], @po_number=1235>
#<Order:0x168d624 @products=[#<Product:0x168d124 @price=50, @sku="ABC-454">], @po_number=1234>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment