mongodoc 0.1.2 → 0.2.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.
Files changed (47) hide show
  1. data/README.textile +143 -0
  2. data/Rakefile +35 -3
  3. data/VERSION +1 -1
  4. data/examples/simple_document.rb +35 -0
  5. data/examples/simple_object.rb +32 -0
  6. data/features/finders.feature +72 -0
  7. data/features/mongodoc_base.feature +12 -2
  8. data/features/named_scopes.feature +66 -0
  9. data/features/new_record.feature +36 -0
  10. data/features/partial_updates.feature +105 -0
  11. data/features/step_definitions/criteria_steps.rb +4 -41
  12. data/features/step_definitions/document_steps.rb +56 -5
  13. data/features/step_definitions/documents.rb +14 -3
  14. data/features/step_definitions/finder_steps.rb +15 -0
  15. data/features/step_definitions/named_scope_steps.rb +18 -0
  16. data/features/step_definitions/partial_update_steps.rb +32 -0
  17. data/features/step_definitions/query_steps.rb +51 -0
  18. data/features/using_criteria.feature +5 -1
  19. data/lib/mongodoc/attributes.rb +76 -63
  20. data/lib/mongodoc/collection.rb +9 -9
  21. data/lib/mongodoc/criteria.rb +152 -161
  22. data/lib/mongodoc/cursor.rb +7 -5
  23. data/lib/mongodoc/document.rb +95 -31
  24. data/lib/mongodoc/finders.rb +29 -0
  25. data/lib/mongodoc/named_scope.rb +68 -0
  26. data/lib/mongodoc/parent_proxy.rb +15 -6
  27. data/lib/mongodoc/proxy.rb +22 -13
  28. data/lib/mongodoc.rb +3 -3
  29. data/mongodoc.gemspec +42 -14
  30. data/perf/mongodoc_runner.rb +90 -0
  31. data/perf/ruby_driver_runner.rb +64 -0
  32. data/spec/attributes_spec.rb +46 -12
  33. data/spec/collection_spec.rb +23 -23
  34. data/spec/criteria_spec.rb +124 -187
  35. data/spec/cursor_spec.rb +21 -17
  36. data/spec/document_ext.rb +2 -2
  37. data/spec/document_spec.rb +187 -218
  38. data/spec/embedded_save_spec.rb +104 -0
  39. data/spec/finders_spec.rb +81 -0
  40. data/spec/hash_matchers.rb +27 -0
  41. data/spec/named_scope_spec.rb +82 -0
  42. data/spec/new_record_spec.rb +216 -0
  43. data/spec/parent_proxy_spec.rb +8 -6
  44. data/spec/proxy_spec.rb +80 -0
  45. data/spec/spec_helper.rb +2 -0
  46. metadata +35 -7
  47. data/README.rdoc +0 -75
@@ -0,0 +1,68 @@
1
+ # Based on ActiveRecord::NamedScope
2
+ module MongoDoc
3
+ module NamedScope
4
+ def scopes
5
+ read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
6
+ end
7
+
8
+ def named_scope(name, options = {}, &block)
9
+ name = name.to_sym
10
+ scopes[name] = lambda do |parent_scope, *args|
11
+ CriteriaProxy.new(parent_scope, Hash === options ? options : options.call(*args), &block)
12
+ end
13
+ (class << self; self; end).class_eval <<-EOT
14
+ def #{name}(*args)
15
+ scopes[:#{name}].call(self, *args)
16
+ end
17
+ EOT
18
+ end
19
+
20
+ class CriteriaProxy
21
+ attr_accessor :conditions, :klass, :parent_scope
22
+
23
+ delegate :scopes, :to => :parent_scope
24
+
25
+ def initialize(parent_scope, conditions, &block)
26
+ conditions ||= {}
27
+ [conditions.delete(:extend)].flatten.each { |extension| extend extension } if conditions.include?(:extend)
28
+ extend Module.new(&block) if block_given?
29
+ self.klass = parent_scope unless CriteriaProxy === parent_scope
30
+ self.parent_scope, self.conditions = parent_scope, conditions
31
+ end
32
+
33
+ def respond_to?(method, include_private = false)
34
+ super || if klass
35
+ proxy_found.respond_to?(method, include_private)
36
+ else
37
+ parent_scope.respond_to?(method, include_private)
38
+ end
39
+ end
40
+
41
+ protected
42
+
43
+ def proxy_found
44
+ @found || load_found
45
+ end
46
+
47
+ private
48
+
49
+ def method_missing(method, *args, &block)
50
+ if scopes.include?(method)
51
+ scopes[method].call(self, *args)
52
+ elsif klass
53
+ proxy_found.send(method, *args, &block)
54
+ else
55
+ parent_scope.criteria(conditions)
56
+ parent_scope.send(method, *args, &block)
57
+ end
58
+ end
59
+
60
+ def load_found
61
+ @found = Criteria.new(klass)
62
+ @found.criteria(conditions)
63
+ @found
64
+ end
65
+ end
66
+ end
67
+ end
68
+
@@ -9,12 +9,21 @@ module MongoDoc
9
9
  @assoc_name = assoc_name
10
10
  end
11
11
 
12
- def path_to_root(attrs)
13
- assoc_attrs = attrs.inject({}) do |assoc_attrs, (key, value)|
14
- assoc_attrs["#{assoc_name}.#{key}"] = value
15
- assoc_attrs
12
+ def _path_to_root(src, attrs)
13
+ _parent._path_to_root(src, _annotated_keys(attrs))
14
+ end
15
+
16
+ def _selector_path_to_root(selector)
17
+ _parent._selector_path_to_root(_annotated_keys(selector))
18
+ end
19
+
20
+ protected
21
+
22
+ def _annotated_keys(hash)
23
+ hash.inject({}) do |annotated, (key, value)|
24
+ annotated["#{assoc_name}.#{key}"] = value
25
+ annotated
16
26
  end
17
- _parent.path_to_root(assoc_attrs)
18
27
  end
19
28
 
20
29
  private
@@ -32,4 +41,4 @@ module MongoDoc
32
41
  end
33
42
  end
34
43
  end
35
- end
44
+ end
@@ -39,15 +39,14 @@ module MongoDoc
39
39
  end
40
40
 
41
41
  alias_method :append, :<<
42
- def <<(items)
43
- items = [items] unless items.kind_of?(Array)
44
- items.each do |item|
45
- item = collection_class.new(item) if Hash === item
46
- raise NotADocumentError unless collection_class === item
47
- append item
42
+ def <<(item)
43
+ item = build(item) if Hash === item
44
+ if Document === item
48
45
  item._parent = self
49
46
  item._root = _root
47
+ _root.send(:register_save_observer, item)
50
48
  end
49
+ append item
51
50
  self
52
51
  end
53
52
  alias_method :push, :<<
@@ -60,15 +59,25 @@ module MongoDoc
60
59
  end
61
60
  alias kind_of? is_a?
62
61
 
63
- def path_to_root(attrs)
64
- _parent.path_to_root(attrs)
62
+ def _path_to_root(src, attrs)
63
+ assoc_path = "#{assoc_name}.#{index(src)}"
64
+ assoc_attrs = attrs.inject({}) do |assoc_attrs, (key, value)|
65
+ assoc_attrs["#{assoc_path}.#{key}"] = value
66
+ assoc_attrs
67
+ end
68
+ _parent._path_to_root(src, assoc_attrs)
65
69
  end
66
70
 
67
- protected
71
+ def _selector_path_to_root(selector)
72
+ annotated_selector = selector.inject({}) do |annotated, (key, value)|
73
+ annotated["#{assoc_name}.#{key}"] = value
74
+ annotated
75
+ end
76
+ _parent._selector_path_to_root(annotated_selector)
77
+ end
68
78
 
69
- def _propose_update_attributes(src, attrs, safe)
70
- src.errors.add(:base, 'update_attributes called through a has_many')
71
- false
79
+ def build(attrs)
80
+ collection_class.new(attrs)
72
81
  end
73
82
  end
74
- end
83
+ end
data/lib/mongodoc.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require 'rubygems'
2
2
 
3
- gem 'mongo', '0.18.1'
4
- gem 'mongo_ext', '0.18.1'
5
- gem 'durran-validatable', '1.8.3'
3
+ gem 'mongo', '0.18.2'
4
+ gem 'mongo_ext', '0.18.2'
5
+ gem 'durran-validatable', '2.0.1'
6
6
  gem 'leshill-will_paginate', '2.3.11'
7
7
 
8
8
  require 'mongo'
data/mongodoc.gemspec CHANGED
@@ -5,35 +5,45 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongodoc}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Les Hill"]
12
- s.date = %q{2009-12-10}
12
+ s.date = %q{2010-01-18}
13
13
  s.description = %q{ODM for MongoDB}
14
14
  s.email = %q{leshill@gmail.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.rdoc"
17
+ "README.textile"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
21
  ".gitignore",
22
22
  "LICENSE",
23
- "README.rdoc",
23
+ "README.textile",
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "data/.gitignore",
27
+ "examples/simple_document.rb",
28
+ "examples/simple_object.rb",
29
+ "features/finders.feature",
27
30
  "features/mongodb.yml",
28
31
  "features/mongodoc_base.feature",
32
+ "features/named_scopes.feature",
33
+ "features/new_record.feature",
34
+ "features/partial_updates.feature",
29
35
  "features/saving_an_object.feature",
30
36
  "features/step_definitions/collection_steps.rb",
31
37
  "features/step_definitions/criteria_steps.rb",
32
38
  "features/step_definitions/document_steps.rb",
33
39
  "features/step_definitions/documents.rb",
40
+ "features/step_definitions/finder_steps.rb",
34
41
  "features/step_definitions/json_steps.rb",
42
+ "features/step_definitions/named_scope_steps.rb",
35
43
  "features/step_definitions/object_steps.rb",
36
44
  "features/step_definitions/objects.rb",
45
+ "features/step_definitions/partial_update_steps.rb",
46
+ "features/step_definitions/query_steps.rb",
37
47
  "features/step_definitions/util_steps.rb",
38
48
  "features/support/support.rb",
39
49
  "features/using_criteria.feature",
@@ -60,12 +70,16 @@ Gem::Specification.new do |s|
60
70
  "lib/mongodoc/ext/string.rb",
61
71
  "lib/mongodoc/ext/symbol.rb",
62
72
  "lib/mongodoc/ext/time.rb",
73
+ "lib/mongodoc/finders.rb",
74
+ "lib/mongodoc/named_scope.rb",
63
75
  "lib/mongodoc/parent_proxy.rb",
64
76
  "lib/mongodoc/proxy.rb",
65
77
  "lib/mongodoc/query.rb",
66
78
  "mongod.example.yml",
67
79
  "mongodb.example.yml",
68
80
  "mongodoc.gemspec",
81
+ "perf/mongodoc_runner.rb",
82
+ "perf/ruby_driver_runner.rb",
69
83
  "script/console",
70
84
  "spec/attributes_spec.rb",
71
85
  "spec/bson_matchers.rb",
@@ -76,9 +90,15 @@ Gem::Specification.new do |s|
76
90
  "spec/cursor_spec.rb",
77
91
  "spec/document_ext.rb",
78
92
  "spec/document_spec.rb",
93
+ "spec/embedded_save_spec.rb",
94
+ "spec/finders_spec.rb",
95
+ "spec/hash_matchers.rb",
79
96
  "spec/mongodb.yml",
80
97
  "spec/mongodb_pairs.yml",
98
+ "spec/named_scope_spec.rb",
99
+ "spec/new_record_spec.rb",
81
100
  "spec/parent_proxy_spec.rb",
101
+ "spec/proxy_spec.rb",
82
102
  "spec/query_spec.rb",
83
103
  "spec/spec.opts",
84
104
  "spec/spec_helper.rb"
@@ -98,9 +118,17 @@ Gem::Specification.new do |s|
98
118
  "spec/cursor_spec.rb",
99
119
  "spec/document_ext.rb",
100
120
  "spec/document_spec.rb",
121
+ "spec/embedded_save_spec.rb",
122
+ "spec/finders_spec.rb",
123
+ "spec/hash_matchers.rb",
124
+ "spec/named_scope_spec.rb",
125
+ "spec/new_record_spec.rb",
101
126
  "spec/parent_proxy_spec.rb",
127
+ "spec/proxy_spec.rb",
102
128
  "spec/query_spec.rb",
103
- "spec/spec_helper.rb"
129
+ "spec/spec_helper.rb",
130
+ "examples/simple_document.rb",
131
+ "examples/simple_object.rb"
104
132
  ]
105
133
 
106
134
  if s.respond_to? :specification_version then
@@ -108,24 +136,24 @@ Gem::Specification.new do |s|
108
136
  s.specification_version = 3
109
137
 
110
138
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
111
- s.add_runtime_dependency(%q<mongo>, ["= 0.18.1"])
112
- s.add_runtime_dependency(%q<mongo_ext>, ["= 0.18.1"])
113
- s.add_runtime_dependency(%q<durran-validatable>, ["= 1.8.3"])
139
+ s.add_runtime_dependency(%q<mongo>, ["= 0.18.2"])
140
+ s.add_runtime_dependency(%q<mongo_ext>, ["= 0.18.2"])
141
+ s.add_runtime_dependency(%q<durran-validatable>, ["= 1.8.4"])
114
142
  s.add_runtime_dependency(%q<leshill-will_paginate>, ["= 2.3.11"])
115
143
  s.add_development_dependency(%q<rspec>, ["= 1.2.9"])
116
144
  s.add_development_dependency(%q<cucumber>, ["= 0.4.4"])
117
145
  else
118
- s.add_dependency(%q<mongo>, ["= 0.18.1"])
119
- s.add_dependency(%q<mongo_ext>, ["= 0.18.1"])
120
- s.add_dependency(%q<durran-validatable>, ["= 1.8.3"])
146
+ s.add_dependency(%q<mongo>, ["= 0.18.2"])
147
+ s.add_dependency(%q<mongo_ext>, ["= 0.18.2"])
148
+ s.add_dependency(%q<durran-validatable>, ["= 1.8.4"])
121
149
  s.add_dependency(%q<leshill-will_paginate>, ["= 2.3.11"])
122
150
  s.add_dependency(%q<rspec>, ["= 1.2.9"])
123
151
  s.add_dependency(%q<cucumber>, ["= 0.4.4"])
124
152
  end
125
153
  else
126
- s.add_dependency(%q<mongo>, ["= 0.18.1"])
127
- s.add_dependency(%q<mongo_ext>, ["= 0.18.1"])
128
- s.add_dependency(%q<durran-validatable>, ["= 1.8.3"])
154
+ s.add_dependency(%q<mongo>, ["= 0.18.2"])
155
+ s.add_dependency(%q<mongo_ext>, ["= 0.18.2"])
156
+ s.add_dependency(%q<durran-validatable>, ["= 1.8.4"])
129
157
  s.add_dependency(%q<leshill-will_paginate>, ["= 2.3.11"])
130
158
  s.add_dependency(%q<rspec>, ["= 1.2.9"])
131
159
  s.add_dependency(%q<cucumber>, ["= 0.4.4"])
@@ -0,0 +1,90 @@
1
+ require "benchmark"
2
+ require "ruby-prof"
3
+ require "mongodoc"
4
+
5
+ class Person < MongoDoc::Document
6
+ key :birth_date
7
+ has_one :name
8
+ has_one :address
9
+ has_many :phones
10
+ end
11
+
12
+ class Name < MongoDoc::Document
13
+ key :given
14
+ key :family
15
+ key :middle
16
+ end
17
+
18
+ class Address < MongoDoc::Document
19
+ key :street
20
+ key :city
21
+ key :state
22
+ key :post_code
23
+ key :type
24
+ end
25
+
26
+ class Phone < MongoDoc::Document
27
+ key :country_code
28
+ key :number
29
+ key :type
30
+ end
31
+
32
+ class MongoDocRunner
33
+ def self.benchmark
34
+ MongoDoc.connect_to_database('mongodoc_perf_test')
35
+ MongoDoc.database.collection('people').drop
36
+
37
+ puts "Starting benchmark..."
38
+
39
+ 10.times do |n|
40
+ person = Person.new(:birth_date => Date.new(1970, 1, 1))
41
+ name = Name.new(:given => "James", :family => "Kirk", :middle => "Tiberius")
42
+ address = Address.new(:street => "1 Starfleet Command Way", :city => "San Francisco", :state => "CA", :post_code => "94133", :type => "Work")
43
+ phone = Phone.new(:country_code => 1, :number => "415-555-1212", :type => "Mobile")
44
+ person.name = name
45
+ person.address = address
46
+ person.phones << phone
47
+ person.save
48
+ end
49
+
50
+ Benchmark.bm do |bm|
51
+ bm.report('MongoDoc') do
52
+ 10000.times do |n|
53
+ person = Person.new(:birth_date => Date.new(1970, 1, 1))
54
+ name = Name.new(:given => "James", :family => "Kirk", :middle => "Tiberius")
55
+ address = Address.new(:street => "1 Starfleet Command Way", :city => "San Francisco", :state => "CA", :post_code => "94133", :type => "Work")
56
+ phone = Phone.new(:country_code => 1, :number => "415-555-1212", :type => "Mobile")
57
+ person.name = name
58
+ person.address = address
59
+ person.phones << phone
60
+ person.save
61
+ end
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ def self.profile
68
+ MongoDoc.connect_to_database('mongodoc_perf_test')
69
+ MongoDoc.database.collection('people').drop
70
+
71
+ RubyProf.start
72
+
73
+ puts "Starting profiler..."
74
+
75
+ 1000.times do |n|
76
+ person = Person.new(:birth_date => Date.new(1970, 1, 1))
77
+ name = Name.new(:given => "James", :family => "Kirk", :middle => "Tiberius")
78
+ address = Address.new(:street => "1 Starfleet Command Way", :city => "San Francisco", :state => "CA", :post_code => "94133", :type => "Work")
79
+ phone = Phone.new(:country_code => 1, :number => "415-555-1212", :type => "Mobile")
80
+ person.name = name
81
+ person.address = address
82
+ person.phones << phone
83
+ person.save
84
+ end
85
+
86
+ result = RubyProf.stop
87
+ printer = RubyProf::FlatPrinter.new(result)
88
+ printer.print(STDOUT, 0)
89
+ end
90
+ end
@@ -0,0 +1,64 @@
1
+ require "rubygems"
2
+ require "ruby-prof"
3
+ require "mongodoc"
4
+
5
+ class RubyDriverRunner
6
+ def self.benchmark
7
+ MongoDoc.connect_to_database('mongodoc_perf_test')
8
+ collection = MongoDoc.database.collection('people')
9
+ collection.drop
10
+
11
+ puts "Starting benchmark..."
12
+
13
+ 10.times do |n|
14
+ person = {:birth_date => Date.new(1970, 1, 1).to_bson, :phones => []}
15
+ name = {:given => "James", :family => "Kirk", :middle => "Tiberius"}
16
+ address = {:street => "1 Starfleet Command Way", :city => "San Francisco", :state => "CA", :post_code => "94133", :type => "Work"}
17
+ phone = {:country_code => 1, :number => "415-555-1212", :type => "Mobile"}
18
+ person[:name] = name
19
+ person[:address] = address
20
+ person[:phones] << phone
21
+ collection.save(person)
22
+ end
23
+
24
+ Benchmark.bm do |bm|
25
+ bm.report('Driver') do
26
+ 10000.times do |n|
27
+ person = {:birth_date => Date.new(1970, 1, 1).to_bson, :phones => []}
28
+ name = {:given => "James", :family => "Kirk", :middle => "Tiberius"}
29
+ address = {:street => "1 Starfleet Command Way", :city => "San Francisco", :state => "CA", :post_code => "94133", :type => "Work"}
30
+ phone = {:country_code => 1, :number => "415-555-1212", :type => "Mobile"}
31
+ person[:name] = name
32
+ person[:address] = address
33
+ person[:phones] << phone
34
+ collection.save(person)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def self.profile
41
+ MongoDoc.connect_to_database('mongodoc_perf_test')
42
+ collection = MongoDoc.database.collection('people')
43
+ collection.drop
44
+
45
+ RubyProf.start
46
+
47
+ puts "Starting profiler..."
48
+
49
+ 1000.times do |n|
50
+ person = {:birth_date => Date.new(1970, 1, 1), :phones => []}
51
+ name = {:given => "James", :family => "Kirk", :middle => "Tiberius"}
52
+ address = { :street => "1 Starfleet Command Way", :city => "San Francisco", :state => "CA", :post_code => "94133", :type => "Work"}
53
+ phone = {:country_code => 1, :number => "415-555-1212", :type => "Mobile"}
54
+ person[:name] = name
55
+ person[:address] = address
56
+ person[:phones] << phone
57
+ collection.insert(person)
58
+ end
59
+
60
+ result = RubyProf.stop
61
+ printer = RubyProf::FlatPrinter.new(result)
62
+ printer.print(STDOUT, 0)
63
+ end
64
+ end
@@ -1,8 +1,18 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "MongoDoc::Attributes" do
4
+ class AttributesTest
5
+ include MongoDoc::Attributes
6
+ end
7
+
8
+ it "defines _id attribute" do
9
+ AttributesTest.new.should respond_to(:_id)
10
+ AttributesTest.new.should respond_to(:_id=)
11
+ end
12
+
4
13
  context ".key" do
5
- class TestKeys < MongoDoc::Document
14
+ class TestKeys
15
+ include MongoDoc::Document
6
16
  end
7
17
 
8
18
  it "adds its arguments to _keys" do
@@ -28,7 +38,9 @@ describe "MongoDoc::Attributes" do
28
38
  end
29
39
 
30
40
  describe "used with inheritance" do
31
- class TestParent < MongoDoc::Document
41
+ class TestParent
42
+ include MongoDoc::Document
43
+
32
44
  key :parent_attr
33
45
  end
34
46
 
@@ -43,15 +55,23 @@ describe "MongoDoc::Attributes" do
43
55
  it "has the keys from the parent class" do
44
56
  TestChild._keys.should include(*TestParent._keys)
45
57
  end
58
+
59
+ it "does not add keys to the parent class" do
60
+ TestParent._keys.should_not include(:child_attr)
61
+ end
46
62
  end
47
63
  end
48
64
 
49
65
  context ".has_one" do
50
- class TestDoc < MongoDoc::Document
66
+ class TestDoc
67
+ include MongoDoc::Document
68
+
51
69
  has_one :subdoc
52
70
  end
53
71
 
54
- class SubDoc < MongoDoc::Document
72
+ class SubDoc
73
+ include MongoDoc::Document
74
+
55
75
  key :data
56
76
  end
57
77
 
@@ -77,7 +97,9 @@ describe "MongoDoc::Attributes" do
77
97
  subdoc._root.should == doc
78
98
  end
79
99
 
80
- class HasOneValidationTest < MongoDoc::Document
100
+ class HasOneValidationTest
101
+ include MongoDoc::Document
102
+
81
103
  key :data
82
104
  validates_presence_of :data
83
105
  end
@@ -90,7 +112,9 @@ describe "MongoDoc::Attributes" do
90
112
  end
91
113
 
92
114
  context "._attributes" do
93
- class TestHasOneDoc < MongoDoc::Document
115
+ class TestHasOneDoc
116
+ include MongoDoc::Document
117
+
94
118
  key :key
95
119
  has_one :has_one
96
120
  end
@@ -102,15 +126,21 @@ describe "MongoDoc::Attributes" do
102
126
 
103
127
  context ".has_many" do
104
128
 
105
- class SubHasManyDoc < MongoDoc::Document
129
+ class SubHasManyDoc
130
+ include MongoDoc::Document
131
+
106
132
  key :data
107
133
  end
108
134
 
109
- class TestHasManyDoc < MongoDoc::Document
135
+ class TestHasManyDoc
136
+ include MongoDoc::Document
137
+
110
138
  has_many :sub_docs, :class_name => 'SubHasManyDoc'
111
139
  end
112
140
 
113
- class TestImplicitHasManyDoc < MongoDoc::Document
141
+ class TestImplicitHasManyDoc
142
+ include MongoDoc::Document
143
+
114
144
  has_many :sub_has_many_docs
115
145
  end
116
146
 
@@ -135,12 +165,16 @@ describe "MongoDoc::Attributes" do
135
165
  doc = TestImplicitHasManyDoc.new(:sub_has_many_docs => [subdoc])
136
166
  end
137
167
 
138
- class HasManyValidationChild < MongoDoc::Document
168
+ class HasManyValidationChild
169
+ include MongoDoc::Document
170
+
139
171
  key :data
140
172
  validates_presence_of :data
141
173
  end
142
174
 
143
- class HasManyValidationTest < MongoDoc::Document
175
+ class HasManyValidationTest
176
+ include MongoDoc::Document
177
+
144
178
  has_many :subdocs, :class_name => 'HasManyValidationChild'
145
179
  end
146
180
 
@@ -156,4 +190,4 @@ describe "MongoDoc::Attributes" do
156
190
  invalid.should have(1).error_on(:data)
157
191
  end
158
192
  end
159
- end
193
+ end