mongo_persist 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -11,8 +11,10 @@ begin
11
11
  gem.homepage = "http://github.com/mharris717/mongo_persist"
12
12
  gem.authors = ["Mike Harris"]
13
13
  gem.add_development_dependency "rspec"
14
+ gem.add_development_dependency 'rr'
14
15
  gem.add_dependency 'fattr'
15
16
  gem.add_dependency 'activesupport'
17
+ gem.add_dependency 'mharris_ext'
16
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
19
  end
18
20
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.1.0
data/examples/only.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'mongo'
3
+ require 'mongo_persist'
4
+
5
+ def db
6
+ Mongo::Connection.new.db('test-db')
7
+ end
8
+
9
+ class Order
10
+ include MongoPersist
11
+ attr_accessor :po_number
12
+ fattr(:order_products) { [] }
13
+ def products
14
+ order_products.map { |x| x.product }
15
+ end
16
+ end
17
+
18
+ class OrderProduct
19
+ include MongoPersist
20
+ attr_accessor :unit_price, :quantity, :product
21
+
22
+ # Store a reference to objects for this attribute, not the entire object.
23
+ mongo_reference_attributes ['product']
24
+ end
25
+
26
+ class Product
27
+ include MongoPersist
28
+ attr_accessor :name
29
+ end
30
+
31
+ products = [Product.new(:name => 'Leather Couch'),Product.new(:name => 'Maroon Chair')].each { |x| x.mongo.save! }
32
+
33
+ orders = []
34
+ orders << Order.new(:po_number => 1234,
35
+ :order_products => [OrderProduct.new(:unit_price => 1000, :quantity => 1, :product => products[0])]).mongo.save!
36
+ orders << Order.new(:po_number => 1235,
37
+ :order_products => [OrderProduct.new(:unit_price => 200, :quantity => 2, :product => products[1])]).mongo.save!
38
+
39
+ # objects are saved to MongoDB as JSON objects
40
+
41
+ # get all order objects back from Mongo
42
+ # you get back the ruby objects you put in, not raw JSON objects
43
+ Order.collection.find_objects
44
+
45
+ # Since on OrderProduct, the product attribute was marked as a reference attribute,
46
+ # the product is stored in MongoDB only as a reference to the product obj
47
+ #
48
+ # When you read the Order/OrderProduct back out, MongoPersist takes care of
49
+ # fetching the Product object again. You don't have to do anything.
50
+ Order.collection.find_one_object.products.first # An object of class Product
51
+ Order.collection.find_one_object.products.first.name # Leather Couch
52
+
53
+ # Because the product is stored as a reference, if you update that product
54
+ # elsewhere and save to Mongo, later reads of Orders with that product will be correctly updated
55
+ products[0].name = 'White Leather Couch'
56
+ products[0].mongo.save!
57
+ Order.collection.find_one_object.products.first.name # White Leather Couch
data/lib/mongo_persist.rb CHANGED
@@ -1,137 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'mongo'
3
- require 'activesupport'
3
+ require 'active_support'
4
4
  require 'fattr'
5
- require File.dirname(__FILE__) + "/mongo_persist/util"
5
+ %w(util core_ext array_ext hash_ext base mongo_ext).each { |x| require File.dirname(__FILE__) + "/mongo_persist/#{x}" }
6
6
  require 'andand'
7
7
 
8
- class Object
9
- def safe_to_mongo_hash
10
- sos(:to_mongo_hash)
11
- end
12
- def safe_to_mongo_object
13
- sos(:to_mongo_object)
14
- end
15
- end
16
8
 
17
- class Array
18
- def to_mongo_hash
19
- map { |x| x.safe_to_mongo_hash }
20
- end
21
- def to_mongo_object
22
- map { |x| x.safe_to_mongo_object }
23
- end
24
- def to_mongo_ref_hash
25
- map { |x| x.to_mongo_ref_hash }
26
- end
27
- end
28
-
29
- class Hash
30
- def get_mongo_id
31
- ['_id','mongo_id'].each { |x| return self[x] if self[x] }
32
- nil
33
- end
34
- def naked_reference?
35
- (keys - ['_id','_mongo_class','mongo_id']).empty? && !!get_mongo_id
36
- end
37
- def mongo_class
38
- self['_mongo_class'] ? eval(self['_mongo_class']) : nil
39
- end
40
- def to_mongo_hash_for_obj
41
- h = reject { |k,v| k == '_mongo_class' }
42
- h['mongo_id'] = h['_id'] if h['_id']
43
- h.reject { |k,v| k == '_id' }
44
- end
45
- def to_mongo_object
46
- return map_value { |v| v.safe_to_mongo_object } unless mongo_class
47
- if naked_reference?
48
- mongo_class.collection.find_one_object('_id' => get_mongo_id)
49
- else
50
- mongo_class.from_mongo_hash(to_mongo_hash_for_obj)
51
- end
52
- end
53
- def to_mongo_hash
54
- res = {}
55
- each { |k,v| res[k.safe_to_mongo_hash] = v.safe_to_mongo_hash }
56
- res
57
- end
58
- end
59
-
60
- class MongoWrapper
61
- attr_accessor :obj
62
- include FromHash
63
- def save!
64
- if obj.mongo_id
65
- obj.klass.collection.update({'_id' => obj.mongo_id},obj.to_mongo_hash)
66
- else
67
- obj.mongo_id = obj.class.collection.save(obj.to_mongo_hash)
68
- end
69
- obj
70
- end
71
- end
72
-
73
- module MongoPersist
74
- attr_accessor :mongo_id
75
- #can be overriden by class. If not, assumes that all instance variables should be saved.
76
- def mongo_attributes
77
- instance_variables.map { |x| x[1..-1] } - ['mongo']
78
- end
79
- def mongo_child_attributes
80
- mongo_attributes - self.class.mongo_reference_attributes
81
- end
82
- def to_mongo_ref_hash
83
- {'_mongo_class' => klass.to_s, '_id' => mongo_id}
84
- end
85
- def to_mongo_hash
86
- res = mongo_child_attributes.inject({}) { |h,attr| h.merge(attr => send(attr).safe_to_mongo_hash) }.merge("_mongo_class" => self.class.to_s)
87
- klass.mongo_reference_attributes.each do |attr|
88
- val = send(attr)
89
- res[attr] = val.to_mongo_ref_hash if val
90
- end
91
- res
92
- end
93
- def from_mongo_hash(h)
94
- h = h.map_value { |v| v.safe_to_mongo_object }
95
- from_hash(h)
96
- end
97
- fattr(:mongo) { MongoWrapper.new(:obj => self) }
98
-
99
- module ClassMethods
100
- dsl_method(:mongo_reference_attributes) { [] }
101
- def default_collection_name
102
- to_s.downcase.pluralize
103
- end
104
- fattr(:collection) { db.collection(default_collection_name) }
105
- def from_mongo_hash(h)
106
- new.tap { |x| x.from_mongo_hash(h) }
107
- end
108
- def mongo_connection(ops)
109
- ops.each { |k,v| send("#{k}=",v) }
110
- end
111
- end
112
- def self.included(mod)
113
- super(mod)
114
- mod.send(:include,FromHash)
115
- mod.send(:extend,ClassMethods)
116
- end
117
- end
118
-
119
- class ObjCursor
120
- attr_accessor :cursor
121
- include FromHash
122
- def each
123
- cursor.each { |x| yield(x.to_mongo_object) }
124
- end
125
- def count
126
- cursor.count
127
- end
128
- end
129
-
130
- class Mongo::Collection
131
- def find_objects(*args)
132
- ObjCursor.new(:cursor => find(*args))
133
- end
134
- def find_one_object(*args)
135
- find_one(*args).to_mongo_object
136
- end
137
- end
@@ -0,0 +1,14 @@
1
+ class Array
2
+ def to_mongo_hash
3
+ map { |x| x.safe_to_mongo_hash }
4
+ end
5
+ def to_mongo_object
6
+ map { |x| x.safe_to_mongo_object }
7
+ end
8
+ def to_mongo_ref_hash
9
+ map { |x| x.to_mongo_ref_hash }
10
+ end
11
+ def can_mongo_convert?
12
+ all? { |x| x.can_mongo_convert? && x }
13
+ end
14
+ end
@@ -0,0 +1,83 @@
1
+ class MongoWrapper
2
+ attr_accessor :obj
3
+ include FromHash
4
+ def save!
5
+ if obj.mongo_id
6
+ obj.klass.collection.update({'_id' => obj.mongo_id},obj.to_mongo_hash)
7
+ else
8
+ obj.mongo_id = obj.class.collection.save(obj.to_mongo_hash)
9
+ end
10
+ obj
11
+ rescue => exp
12
+ require 'pp'
13
+ pp obj.to_mongo_hash
14
+ raise exp
15
+ end
16
+ end
17
+
18
+ module MongoPersist
19
+ NIL_OBJ = 99999
20
+ attr_accessor :mongo_id
21
+ #can be overriden by class. If not, assumes that all instance variables should be saved.
22
+ def mongo_attributes
23
+ (instance_variables.map { |x| x[1..-1] } - ['mongo','mongo_id']).select { |x| respond_to?(x) }
24
+ end
25
+ def mongo_addl_attributes
26
+ []
27
+ end
28
+ def mongo_child_attributes
29
+ (mongo_attributes - self.class.mongo_reference_attributes + mongo_addl_attributes).uniq
30
+ end
31
+ def to_mongo_ref_hash
32
+ {'_mongo_class' => klass.to_s, '_id' => mongo_id}
33
+ end
34
+ def new_hashx(attr,h,obj)
35
+ if obj.can_mongo_convert?
36
+ h.merge(attr => obj.to_mongo_hash)
37
+ else
38
+ h
39
+ end
40
+ rescue
41
+ return h
42
+ end
43
+ def to_mongo_hash
44
+ res = mongo_child_attributes.inject({}) do |h,attr|
45
+ obj = send(attr)
46
+ raise "#{attr} is nil" unless obj
47
+ new_hashx(attr,h,obj)
48
+ end.merge("_mongo_class" => self.class.to_s)
49
+ klass.mongo_reference_attributes.each do |attr|
50
+ val = send(attr)
51
+ res[attr] = val.to_mongo_ref_hash if val
52
+ end
53
+ res
54
+ end
55
+ def from_mongo_hash(h)
56
+ h = h.map_value { |v| v.safe_to_mongo_object }
57
+ from_hash(h)
58
+ end
59
+ fattr(:mongo) { MongoWrapper.new(:obj => self) }
60
+
61
+ module ClassMethods
62
+ dsl_method(:mongo_reference_attributes) { [] }
63
+ def default_collection_name
64
+ to_s.downcase.pluralize
65
+ end
66
+ fattr(:collection) { db.collection(default_collection_name) }
67
+ def new_with_nil_args
68
+ args = (1..(instance_method(:initialize).arity)).map { |x| nil }
69
+ new(*args)
70
+ end
71
+ def from_mongo_hash(h)
72
+ new_with_nil_args.tap { |x| x.from_mongo_hash(h) }
73
+ end
74
+ def mongo_connection(ops)
75
+ ops.each { |k,v| send("#{k}=",v) }
76
+ end
77
+ end
78
+ def self.included(mod)
79
+ super(mod)
80
+ mod.send(:include,FromHash)
81
+ mod.send(:extend,ClassMethods)
82
+ end
83
+ end
@@ -0,0 +1,57 @@
1
+ class Object
2
+ def safe_to_mongo_hash
3
+ respond_to?(:to_mongo_hash) ? to_mongo_hash : nil
4
+ end
5
+ def safe_to_mongo_object
6
+ to_mongo_object
7
+ end
8
+ def ngil_obj?
9
+ self == MongoPersist::NIL_OBJ
10
+ end
11
+ def can_mongo_convert?
12
+ false
13
+ end
14
+ end
15
+
16
+ module BaseObjects
17
+ def to_mongo_hash
18
+ self
19
+ end
20
+ def to_mongo_object
21
+ self
22
+ end
23
+ def can_mongo_convert?
24
+ true
25
+ end
26
+ end
27
+
28
+ [Numeric,Symbol,String,Mongo::ObjectID,TrueClass,FalseClass].each do |cls|
29
+ cls.send(:include,BaseObjects)
30
+ end
31
+
32
+ class NilClass
33
+ def to_mongo_object
34
+ self
35
+ end
36
+ end
37
+
38
+ class Object
39
+ def to_mongo_key
40
+ self
41
+ end
42
+ def from_mongo_key
43
+ self
44
+ end
45
+ end
46
+
47
+ class Fixnum
48
+ def to_mongo_key
49
+ "#{self}-NUM"
50
+ end
51
+ end
52
+
53
+ class String
54
+ def from_mongo_key
55
+ (self =~ /^(.*)-NUM$/) ? $1.to_i : self
56
+ end
57
+ end
@@ -0,0 +1,34 @@
1
+ module MongoHash
2
+ def get_mongo_id
3
+ ['_id','mongo_id'].each { |x| return self[x] if self[x] }
4
+ nil
5
+ end
6
+ def naked_reference?
7
+ (keys - ['_id','_mongo_class','mongo_id']).empty? && !!get_mongo_id
8
+ end
9
+ def mongo_class
10
+ self['_mongo_class'] ? eval(self['_mongo_class']) : nil
11
+ end
12
+ def to_mongo_hash_for_obj
13
+ h = reject { |k,v| k == '_mongo_class' }
14
+ h['mongo_id'] = h['_id'] if h['_id']
15
+ h.reject { |k,v| k == '_id' }
16
+ end
17
+ def to_mongo_object
18
+ return map_value { |v| v.safe_to_mongo_object }.map_key { |k| k.from_mongo_key } unless mongo_class
19
+ if naked_reference?
20
+ mongo_class.collection.find_one_object('_id' => get_mongo_id)
21
+ else
22
+ mongo_class.from_mongo_hash(to_mongo_hash_for_obj)
23
+ end
24
+ end
25
+ def to_mongo_hash
26
+ res = {}
27
+ each { |k,v| res[k.safe_to_mongo_hash.to_mongo_key] = v.safe_to_mongo_hash }
28
+ res
29
+ end
30
+ end
31
+
32
+ class Hash
33
+ include MongoHash
34
+ end
@@ -0,0 +1,23 @@
1
+ class ObjCursor
2
+ attr_accessor :cursor
3
+ include FromHash
4
+ def each
5
+ cursor.each { |x| yield(x.to_mongo_object) }
6
+ end
7
+ def count
8
+ cursor.count
9
+ end
10
+ end
11
+
12
+ module MongoPersistCollection
13
+ def find_objects(*args)
14
+ ObjCursor.new(:cursor => find(*args))
15
+ end
16
+ def find_one_object(*args)
17
+ find_one(*args).to_mongo_object
18
+ end
19
+ end
20
+
21
+ class Mongo::Collection
22
+ include MongoPersistCollection
23
+ end
@@ -44,6 +44,9 @@ module FromHash
44
44
  end
45
45
  def initialize(ops={})
46
46
  from_hash(ops)
47
+ after_initialize
48
+ end
49
+ def after_initialize
47
50
  end
48
51
  end
49
52
 
@@ -53,4 +56,9 @@ class Hash
53
56
  each { |k,v| res[k] = yield(v) }
54
57
  res
55
58
  end
59
+ def map_key
60
+ res = {}
61
+ each { |k,v| res[yield(k)] = v }
62
+ res
63
+ end
56
64
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongo_persist}
8
- s.version = "0.0.2"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Mike Harris"]
12
- s.date = %q{2009-11-19}
12
+ s.date = %q{2009-12-17}
13
13
  s.description = %q{Library to add MongoDB Persistance to normal Ruby objects}
14
14
  s.email = %q{mharris717@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -24,9 +24,15 @@ Gem::Specification.new do |s|
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "lib/mongo_persist.rb",
27
+ "lib/mongo_persist/array_ext.rb",
28
+ "lib/mongo_persist/base.rb",
29
+ "lib/mongo_persist/core_ext.rb",
30
+ "lib/mongo_persist/hash_ext.rb",
31
+ "lib/mongo_persist/mongo_ext.rb",
27
32
  "lib/mongo_persist/sandbox.rb",
28
33
  "lib/mongo_persist/util.rb",
29
34
  "mongo_persist.gemspec",
35
+ "spec/mocks.rb",
30
36
  "spec/mongo_persist_spec.rb",
31
37
  "spec/spec_helper.rb"
32
38
  ]
@@ -36,8 +42,10 @@ Gem::Specification.new do |s|
36
42
  s.rubygems_version = %q{1.3.5}
37
43
  s.summary = %q{Library to add MongoDB Persistance to normal Ruby objects}
38
44
  s.test_files = [
39
- "spec/mongo_persist_spec.rb",
40
- "spec/spec_helper.rb"
45
+ "spec/mocks.rb",
46
+ "spec/mongo_persist_spec.rb",
47
+ "spec/spec_helper.rb",
48
+ "examples/only.rb"
41
49
  ]
42
50
 
43
51
  if s.respond_to? :specification_version then
@@ -46,16 +54,22 @@ Gem::Specification.new do |s|
46
54
 
47
55
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
48
56
  s.add_development_dependency(%q<rspec>, [">= 0"])
57
+ s.add_development_dependency(%q<rr>, [">= 0"])
49
58
  s.add_runtime_dependency(%q<fattr>, [">= 0"])
50
59
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
60
+ s.add_runtime_dependency(%q<mharris_ext>, [">= 0"])
51
61
  else
52
62
  s.add_dependency(%q<rspec>, [">= 0"])
63
+ s.add_dependency(%q<rr>, [">= 0"])
53
64
  s.add_dependency(%q<fattr>, [">= 0"])
54
65
  s.add_dependency(%q<activesupport>, [">= 0"])
66
+ s.add_dependency(%q<mharris_ext>, [">= 0"])
55
67
  end
56
68
  else
57
69
  s.add_dependency(%q<rspec>, [">= 0"])
70
+ s.add_dependency(%q<rr>, [">= 0"])
58
71
  s.add_dependency(%q<fattr>, [">= 0"])
59
72
  s.add_dependency(%q<activesupport>, [">= 0"])
73
+ s.add_dependency(%q<mharris_ext>, [">= 0"])
60
74
  end
61
75
  end
data/spec/mocks.rb ADDED
@@ -0,0 +1,48 @@
1
+ class MockDB
2
+ def collection(name)
3
+ MockCollection.new(:name => name)
4
+ end
5
+ end
6
+
7
+ class MockCursor
8
+ include Enumerable
9
+ attr_accessor :objs
10
+ include FromHash
11
+ def each(&b)
12
+ objs.each(&b)
13
+ end
14
+ def count
15
+ objs.size
16
+ end
17
+ end
18
+
19
+ class MockCollection
20
+ include MongoPersistCollection
21
+ attr_accessor :name
22
+ include FromHash
23
+ fattr(:objs) { {} }
24
+ def remove
25
+ objs!
26
+ end
27
+ def save(doc)
28
+ doc['_id'] = rand(10000000000)
29
+ objs[doc['_id']] = doc
30
+ doc['_id']
31
+ end
32
+ def update(ops,new_doc)
33
+ find_raw(ops).each do |doc|
34
+ objs[doc['_id']] = new_doc.merge('_id' => doc['_id'])
35
+ end
36
+ end
37
+ def find_raw(ops={})
38
+ objs.values.select do |h|
39
+ ops.all? { |k,v| v === h[k.to_s] }
40
+ end
41
+ end
42
+ def find(ops={})
43
+ MockCursor.new(:objs => find_raw(ops))
44
+ end
45
+ def find_one(ops={})
46
+ find_raw(ops).first
47
+ end
48
+ end
@@ -1,7 +1,20 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
+ require_lib "/code/mongo_scope/lib/mongo_scope"
4
+ require 'mharris_ext'
5
+
6
+ def on_rcr?
7
+ dir = File.expand_path(File.dirname(__FILE__))
8
+ !!(dir =~ /\/mnt\/repos/)#.tap { |x| puts "Dir #{dir} rcr? #{x}" }
9
+ end
10
+
3
11
  def db
4
- Mongo::Connection.new.db('test-db')
12
+ if on_rcr?
13
+ require File.dirname(__FILE__) + "/mocks"
14
+ MockDB.new
15
+ else
16
+ Mongo::Connection.new('98.129.37.34',27017).db('test-db')
17
+ end
5
18
  end
6
19
 
7
20
  class Order
@@ -36,6 +49,17 @@ class Customer
36
49
  attr_accessor :email
37
50
  end
38
51
 
52
+ class Foo
53
+ include MongoPersist
54
+ attr_accessor :bar
55
+ def initialize(b)
56
+ @bar = b
57
+ end
58
+ def self.fgrom_mongo_hash(ops)
59
+ new(nil).from_hash(ops)
60
+ end
61
+ end
62
+ if true
39
63
  # too many assertions per test, too many "this is how things should be before i check the point of this test" assertions
40
64
  describe MongoPersist do
41
65
  before do
@@ -84,6 +108,81 @@ describe MongoPersist do
84
108
  o = Order.new(:po_number => 1, :some_hash => {'1' => Product.new(:name => 'Chair')})
85
109
  o.mongo.save!
86
110
  Order.collection.find_one_object(:po_number => 1).some_hash['1'].name.should == 'Chair'
87
- Order.collection.find_one_object.subtotal.should == 1000
111
+ Order.collection.find_one_object(:po_number => 1234).subtotal.should == 1000
112
+ end
113
+ it 'saving reference hashes' do
114
+ p = Product.new(:name => 'Chair')
115
+ p.mongo.save!
116
+ o = Order.new(:po_number => 1, :some_hash => {'1' => p})
117
+ o.mongo.save!
118
+ Order.collection.find_one_object(:po_number => 1).some_hash['1'].name.should == 'Chair'
119
+ Order.collection.find_one_object(:po_number => 1234).subtotal.should == 1000
120
+ end
121
+ it 'obj with own constructor' do
122
+ Foo.collection.remove
123
+ Foo.new(14).mongo.save!
124
+ Foo.collection.find_one_object.bar.should == 14
125
+ end
126
+ it 'hash with number key' do
127
+ Foo.collection.remove
128
+ f = Foo.new(14)
129
+ f.bar = {1 => 2}
130
+ f.mongo.save!
131
+ Foo.collection.find_one_object.bar.keys.should == [1]
132
+ end
133
+ it 'grouping' do
134
+ if false; coll = db.collection('abc')
135
+ coll.remove
136
+ coll.save('a' => 'a', 'b' => 1)
137
+ coll.save("a" => 'a', 'b' => 3)
138
+ coll.save('a' => 'b', 'b' => 2)
139
+
140
+ # reduce_function = "function (obj, prev) { prev.count += obj.b; }"
141
+ # code = Mongo::Code.new(reduce_function)
142
+ # res = coll.group(['a'], {}, {"count" => 0},code)
143
+
144
+ res = coll.sum_by_raw(:key => 'a', :sum_field => 'b')
145
+
146
+ res.find { |x| x['a'] == 'a'}['count'].should == 4
147
+ res.find { |x| x['a'] == 'b'}['count'].should == 2
148
+
149
+ res = coll.sum_by(:key => 'a', :sum_field => 'b').should == {'a' => 4, 'b' => 2}; end
150
+ end
151
+ end
152
+ end
153
+ describe "n+1" do
154
+ before do
155
+ $proxy = true
156
+ [Order,Product].each { |x| x.collection.remove }
157
+ @products = [Product.new(:name => 'Leather Couch'),Product.new(:name => 'Maroon Chair')].each { |x| x.mongo.save! }
158
+ #@products = (1..5000).map { |x| Product.new(:name => x.to_s) }
159
+ @products.each { |x| x.mongo.save! }
160
+ @order_products = @products.map { |x| OrderProduct.new(:product => x) }
161
+ @order = Order.new(:order_products => @order_products).mongo.save!
162
+ end
163
+ it 'loading products should only do 1 lookup' do
164
+ mock.proxy(Product.collection).find()
165
+ Order.collection.find_one_object.products.map { |x| x.name }.should == @products.map { |x| x.name }
166
+ end
167
+ it 'speed test' do
168
+ tm('with proxy') do
169
+ Order.collection.find_one_object.products.each { |x| x.name }
170
+ end
171
+ tm('without proxy') do
172
+ $proxy = false
173
+ Order.collection.find_one_object.products.each { |x| x.name }
174
+ end
88
175
  end
89
176
  end
177
+
178
+ class Mongo::Collection
179
+ def sum_by_raw(ops)
180
+ reduce_function = "function (obj, prev) { prev.count += (obj.#{ops[:sum_field]} ? obj.#{ops[:sum_field]} : 0); }"
181
+ code = Mongo::Code.new(reduce_function)
182
+ group([ops[:key]].flatten, {'a' => 'a'}, {"count" => 0},code)
183
+ end
184
+ def sum_by(ops)
185
+ sum_by_raw(ops).inject({}) { |h,a| k = ops[:key]; h.merge(a[k] => a['count'])}
186
+ end
187
+ end
188
+
data/spec/spec_helper.rb CHANGED
@@ -5,5 +5,15 @@ require 'spec'
5
5
  require 'spec/autorun'
6
6
 
7
7
  Spec::Runner.configure do |config|
8
-
8
+ config.mock_with :rr
9
9
  end
10
+
11
+ def require_lib(path,name=nil)
12
+ name ||= path.split("/")[-1]
13
+ file = "#{path}.rb"
14
+ if FileTest.exists?(file)
15
+ require path
16
+ else
17
+ require name
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo_persist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Harris
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-19 00:00:00 -05:00
12
+ date: 2009-12-17 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,6 +22,16 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rr
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
25
35
  - !ruby/object:Gem::Dependency
26
36
  name: fattr
27
37
  type: :runtime
@@ -42,6 +52,16 @@ dependencies:
42
52
  - !ruby/object:Gem::Version
43
53
  version: "0"
44
54
  version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: mharris_ext
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
45
65
  description: Library to add MongoDB Persistance to normal Ruby objects
46
66
  email: mharris717@gmail.com
47
67
  executables: []
@@ -59,9 +79,15 @@ files:
59
79
  - Rakefile
60
80
  - VERSION
61
81
  - lib/mongo_persist.rb
82
+ - lib/mongo_persist/array_ext.rb
83
+ - lib/mongo_persist/base.rb
84
+ - lib/mongo_persist/core_ext.rb
85
+ - lib/mongo_persist/hash_ext.rb
86
+ - lib/mongo_persist/mongo_ext.rb
62
87
  - lib/mongo_persist/sandbox.rb
63
88
  - lib/mongo_persist/util.rb
64
89
  - mongo_persist.gemspec
90
+ - spec/mocks.rb
65
91
  - spec/mongo_persist_spec.rb
66
92
  - spec/spec_helper.rb
67
93
  has_rdoc: true
@@ -93,5 +119,7 @@ signing_key:
93
119
  specification_version: 3
94
120
  summary: Library to add MongoDB Persistance to normal Ruby objects
95
121
  test_files:
122
+ - spec/mocks.rb
96
123
  - spec/mongo_persist_spec.rb
97
124
  - spec/spec_helper.rb
125
+ - examples/only.rb