honkster-mongo_mapper 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +27 -0
  3. data/UPGRADES +7 -0
  4. data/bin/mmconsole +60 -0
  5. data/examples/attr_accessible.rb +22 -0
  6. data/examples/attr_protected.rb +22 -0
  7. data/examples/cache_key.rb +24 -0
  8. data/examples/custom_types.rb +24 -0
  9. data/examples/identity_map.rb +33 -0
  10. data/examples/identity_map/automatic.rb +8 -0
  11. data/examples/identity_map/middleware.rb +14 -0
  12. data/examples/keys.rb +40 -0
  13. data/examples/modifiers/set.rb +25 -0
  14. data/examples/plugins.rb +41 -0
  15. data/examples/querying.rb +35 -0
  16. data/examples/scopes.rb +52 -0
  17. data/examples/validating/embedded_docs.rb +29 -0
  18. data/lib/mongo_mapper.rb +79 -0
  19. data/lib/mongo_mapper/connection.rb +83 -0
  20. data/lib/mongo_mapper/document.rb +41 -0
  21. data/lib/mongo_mapper/embedded_document.rb +31 -0
  22. data/lib/mongo_mapper/exceptions.rb +27 -0
  23. data/lib/mongo_mapper/extensions/array.rb +19 -0
  24. data/lib/mongo_mapper/extensions/binary.rb +22 -0
  25. data/lib/mongo_mapper/extensions/boolean.rb +44 -0
  26. data/lib/mongo_mapper/extensions/date.rb +25 -0
  27. data/lib/mongo_mapper/extensions/float.rb +14 -0
  28. data/lib/mongo_mapper/extensions/hash.rb +14 -0
  29. data/lib/mongo_mapper/extensions/integer.rb +19 -0
  30. data/lib/mongo_mapper/extensions/kernel.rb +9 -0
  31. data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
  32. data/lib/mongo_mapper/extensions/object.rb +27 -0
  33. data/lib/mongo_mapper/extensions/object_id.rb +30 -0
  34. data/lib/mongo_mapper/extensions/set.rb +20 -0
  35. data/lib/mongo_mapper/extensions/string.rb +18 -0
  36. data/lib/mongo_mapper/extensions/time.rb +29 -0
  37. data/lib/mongo_mapper/plugins.rb +15 -0
  38. data/lib/mongo_mapper/plugins/accessible.rb +44 -0
  39. data/lib/mongo_mapper/plugins/associations.rb +99 -0
  40. data/lib/mongo_mapper/plugins/associations/base.rb +124 -0
  41. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +29 -0
  42. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +24 -0
  43. data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
  44. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +40 -0
  45. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +127 -0
  46. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  47. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +109 -0
  48. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  49. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  50. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  51. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +40 -0
  52. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
  53. data/lib/mongo_mapper/plugins/associations/proxy.rb +139 -0
  54. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  55. data/lib/mongo_mapper/plugins/callbacks.rb +241 -0
  56. data/lib/mongo_mapper/plugins/clone.rb +22 -0
  57. data/lib/mongo_mapper/plugins/descendants.rb +17 -0
  58. data/lib/mongo_mapper/plugins/dirty.rb +124 -0
  59. data/lib/mongo_mapper/plugins/document.rb +41 -0
  60. data/lib/mongo_mapper/plugins/dynamic_querying.rb +43 -0
  61. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  62. data/lib/mongo_mapper/plugins/embedded_document.rb +48 -0
  63. data/lib/mongo_mapper/plugins/equality.rb +17 -0
  64. data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
  65. data/lib/mongo_mapper/plugins/indexes.rb +12 -0
  66. data/lib/mongo_mapper/plugins/inspect.rb +15 -0
  67. data/lib/mongo_mapper/plugins/keys.rb +313 -0
  68. data/lib/mongo_mapper/plugins/keys/key.rb +59 -0
  69. data/lib/mongo_mapper/plugins/logger.rb +18 -0
  70. data/lib/mongo_mapper/plugins/modifiers.rb +112 -0
  71. data/lib/mongo_mapper/plugins/pagination.rb +14 -0
  72. data/lib/mongo_mapper/plugins/persistence.rb +69 -0
  73. data/lib/mongo_mapper/plugins/protected.rb +53 -0
  74. data/lib/mongo_mapper/plugins/querying.rb +176 -0
  75. data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
  76. data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +15 -0
  77. data/lib/mongo_mapper/plugins/rails.rb +58 -0
  78. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  79. data/lib/mongo_mapper/plugins/sci.rb +32 -0
  80. data/lib/mongo_mapper/plugins/scopes.rb +21 -0
  81. data/lib/mongo_mapper/plugins/serialization.rb +76 -0
  82. data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
  83. data/lib/mongo_mapper/plugins/userstamps.rb +15 -0
  84. data/lib/mongo_mapper/plugins/validations.rb +50 -0
  85. data/lib/mongo_mapper/support/descendant_appends.rb +45 -0
  86. data/lib/mongo_mapper/version.rb +4 -0
  87. data/rails/init.rb +19 -0
  88. data/test/_NOTE_ON_TESTING +1 -0
  89. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  90. data/test/functional/associations/test_belongs_to_proxy.rb +93 -0
  91. data/test/functional/associations/test_in_array_proxy.rb +319 -0
  92. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  93. data/test/functional/associations/test_many_documents_proxy.rb +615 -0
  94. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  95. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  96. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  97. data/test/functional/associations/test_one_embedded_proxy.rb +81 -0
  98. data/test/functional/associations/test_one_proxy.rb +182 -0
  99. data/test/functional/test_accessible.rb +168 -0
  100. data/test/functional/test_associations.rb +44 -0
  101. data/test/functional/test_binary.rb +27 -0
  102. data/test/functional/test_caching.rb +76 -0
  103. data/test/functional/test_callbacks.rb +151 -0
  104. data/test/functional/test_dirty.rb +163 -0
  105. data/test/functional/test_document.rb +253 -0
  106. data/test/functional/test_dynamic_querying.rb +75 -0
  107. data/test/functional/test_embedded_document.rb +210 -0
  108. data/test/functional/test_identity_map.rb +514 -0
  109. data/test/functional/test_indexes.rb +42 -0
  110. data/test/functional/test_logger.rb +20 -0
  111. data/test/functional/test_modifiers.rb +416 -0
  112. data/test/functional/test_pagination.rb +91 -0
  113. data/test/functional/test_protected.rb +175 -0
  114. data/test/functional/test_querying.rb +873 -0
  115. data/test/functional/test_safe.rb +76 -0
  116. data/test/functional/test_sci.rb +230 -0
  117. data/test/functional/test_scopes.rb +171 -0
  118. data/test/functional/test_string_id_compatibility.rb +67 -0
  119. data/test/functional/test_timestamps.rb +62 -0
  120. data/test/functional/test_userstamps.rb +27 -0
  121. data/test/functional/test_validations.rb +342 -0
  122. data/test/models.rb +233 -0
  123. data/test/test_active_model_lint.rb +13 -0
  124. data/test/test_helper.rb +105 -0
  125. data/test/unit/associations/test_base.rb +212 -0
  126. data/test/unit/associations/test_proxy.rb +105 -0
  127. data/test/unit/serializers/test_json_serializer.rb +217 -0
  128. data/test/unit/test_clone.rb +69 -0
  129. data/test/unit/test_descendant_appends.rb +71 -0
  130. data/test/unit/test_document.rb +213 -0
  131. data/test/unit/test_dynamic_finder.rb +125 -0
  132. data/test/unit/test_embedded_document.rb +644 -0
  133. data/test/unit/test_extensions.rb +380 -0
  134. data/test/unit/test_key.rb +185 -0
  135. data/test/unit/test_keys.rb +89 -0
  136. data/test/unit/test_mongo_mapper.rb +110 -0
  137. data/test/unit/test_pagination.rb +11 -0
  138. data/test/unit/test_plugins.rb +50 -0
  139. data/test/unit/test_rails.rb +181 -0
  140. data/test/unit/test_rails_compatibility.rb +52 -0
  141. data/test/unit/test_serialization.rb +51 -0
  142. data/test/unit/test_time_zones.rb +39 -0
  143. data/test/unit/test_validations.rb +564 -0
  144. metadata +348 -0
@@ -0,0 +1,81 @@
1
+ require 'test_helper'
2
+
3
+ class OneEmbeddedProxyTest < Test::Unit::TestCase
4
+ def setup
5
+ @post_class = Doc('Post') do
6
+ key :title, String
7
+ end
8
+ @author_class = EDoc('Author') do
9
+ key :name, String
10
+ embedded_in :post
11
+ end
12
+ end
13
+
14
+ should "default to nil" do
15
+ @post_class.one :author, :class => @author_class
16
+ @post_class.new.author.should be_nil
17
+ end
18
+
19
+ should "be able to build" do
20
+ @post_class.one :author, :class => @author_class
21
+
22
+ post = @post_class.create
23
+ author = post.author.build(:name => "John")
24
+ post.author.should be_instance_of(@author_class)
25
+ post.author.should be_new
26
+ post.author.name.should == 'John'
27
+ post.author.should == author
28
+ post.author.post.should == post
29
+ end
30
+
31
+ should "be able to replace the association" do
32
+ @post_class.one :author, :class => @author_class
33
+
34
+ post = @post_class.new
35
+ author = @author_class.new(:name => 'Frank')
36
+ post.author = author
37
+ post.save
38
+ post.reload
39
+
40
+ post.author.should == author
41
+ post.author.nil?.should be_false
42
+
43
+ new_author = @author_class.new(:name => 'Emily')
44
+ post.author = new_author
45
+ post.author.should == new_author
46
+ end
47
+
48
+ should "not have problem loading root document if embedded one is nil" do
49
+ @post_class.one :author, :class => @author_class
50
+ post = @post_class.create
51
+
52
+ lambda {
53
+ @post_class.find(post.id)
54
+ }.should_not raise_error
55
+ end
56
+
57
+ should "load the parent and root documents for nested embedded documents" do
58
+ @address_class = EDoc('Address') do
59
+ key :city, String
60
+ key :state, String
61
+ end
62
+ @author_class.one :address, :class => @address_class
63
+ @post_class.one :author, :class => @author_class
64
+
65
+ post = @post_class.create(:title => 'Post Title', :author => { :name => 'Frank', :address => { :city => 'Boston', :state => 'MA' } })
66
+
67
+ post.author.address._parent_document.should == post.author
68
+ post.author.address._root_document.should == post
69
+ end
70
+
71
+ should "have boolean method for testing presence" do
72
+ @post_class.one :author, :class => @author_class
73
+
74
+ post = @post_class.new
75
+ post.author?.should be_false
76
+
77
+ post.author = @author_class.new(:name => 'Frank')
78
+ post.author?.should be_true
79
+ end
80
+
81
+ end
@@ -0,0 +1,182 @@
1
+ require 'test_helper'
2
+
3
+ class OneProxyTest < Test::Unit::TestCase
4
+ def setup
5
+ @post_class = Doc('Post')
6
+ @author_class = Doc do
7
+ key :post_id, ObjectId
8
+ end
9
+ end
10
+
11
+ should "default to nil" do
12
+ @post_class.one :author, :class => @author_class
13
+ @post_class.new.author.nil?.should be_true
14
+ end
15
+
16
+ should "allow assignment of associated document using a hash" do
17
+ @post_class.one :author, :class => @author_class
18
+
19
+ post = @post_class.new('author' => { 'name' => 'Frank' })
20
+ post.author.name.should == 'Frank'
21
+
22
+ post.save.should be_true
23
+ post.reload
24
+
25
+ post.author.name.should == 'Frank'
26
+ end
27
+
28
+ context "replacing the association" do
29
+ context "with an object of the class" do
30
+ should "work" do
31
+ @post_class.one :author, :class => @author_class
32
+
33
+ post = @post_class.new
34
+ author = @author_class.new(:name => 'Frank')
35
+ post.author = author
36
+ post.reload
37
+
38
+ post.author.should == author
39
+ post.author.nil?.should be_false
40
+
41
+ new_author = @author_class.new(:name => 'Emily')
42
+ post.author = new_author
43
+ post.author.should == new_author
44
+ end
45
+ end
46
+
47
+ context "with a Hash" do
48
+ should "convert to an object of the class and work" do
49
+ @post_class.one :author, :class => @author_class
50
+
51
+ post = @post_class.new
52
+ post.author = {'name' => 'Frank'}
53
+ post.reload
54
+
55
+ post.author.name.should == 'Frank'
56
+ post.author.nil?.should be_false
57
+
58
+ post.author = {'name' => 'Emily'}
59
+ post.author.name.should == 'Emily'
60
+ end
61
+ end
62
+ end
63
+
64
+ should "have boolean method for testing presence" do
65
+ @post_class.one :author, :class => @author_class
66
+
67
+ post = @post_class.new
68
+ post.author?.should be_false
69
+
70
+ post.author = @author_class.new(:name => 'Frank')
71
+ post.author?.should be_true
72
+ end
73
+
74
+ should "work with criteria" do
75
+ @post_class.one :primary_author, :class => @author_class, :primary => true
76
+ @post_class.one :author, :class => @author_class, :primary => false
77
+
78
+ post = @post_class.create
79
+ author = @author_class.create(:name => 'Frank', :primary => false, :post_id => post.id)
80
+ primary = @author_class.create(:name => 'Bill', :primary => true, :post_id => post.id)
81
+ post.reload
82
+ post.author.should == author
83
+ post.primary_author.should == primary
84
+ end
85
+
86
+ should "unset the association" do
87
+ @post_class.one :author, :class => @author_class
88
+ post = @post_class.new
89
+ author = @author_class.new
90
+ post.author = author
91
+ post.reload
92
+
93
+ post.author = nil
94
+ post.author.nil?.should be_false
95
+ end
96
+
97
+ should "work with :dependent delete" do
98
+ @post_class.one :author, :class => @author_class, :dependent => :delete
99
+
100
+ post = @post_class.create
101
+ author = @author_class.new
102
+ post.author = author
103
+ post.reload
104
+
105
+ @author_class.any_instance.expects(:delete).once
106
+ post.author = @author_class.new
107
+ end
108
+
109
+ should "work with :dependent destroy" do
110
+ @post_class.one :author, :class => @author_class, :dependent => :destroy
111
+
112
+ post = @post_class.create
113
+ author = @author_class.new
114
+ post.author = author
115
+ post.reload
116
+
117
+ @author_class.any_instance.expects(:destroy).once
118
+ post.author = @author_class.new
119
+ end
120
+
121
+ should "work with :dependent nullify" do
122
+ @post_class.one :author, :class => @author_class, :dependent => :nullify
123
+
124
+ post = @post_class.create
125
+ author = @author_class.new
126
+ post.author = author
127
+ post.reload
128
+
129
+ post.author = @author_class.new
130
+
131
+ author.reload
132
+ author.post_id.should be_nil
133
+ end
134
+
135
+ should "be able to build" do
136
+ @post_class.one :author, :class => @author_class
137
+
138
+ post = @post_class.create
139
+ author = post.author.build(:name => 'John')
140
+ post.author.should be_instance_of(@author_class)
141
+ post.author.should be_new
142
+ post.author.name.should == 'John'
143
+ post.author.should == author
144
+ post.author.post_id.should == post.id
145
+ end
146
+
147
+ should "be able to create" do
148
+ @post_class.one :author, :class => @author_class
149
+
150
+ post = @post_class.create
151
+ author = post.author.create(:name => 'John')
152
+ post.author.should be_instance_of(@author_class)
153
+ post.author.should_not be_new
154
+ post.author.name.should == 'John'
155
+ post.author.should == author
156
+ post.author.post_id.should == post.id
157
+ end
158
+
159
+ context "#create!" do
160
+ setup do
161
+ @author_class.key :name, String, :required => true
162
+ @post_class.one :author, :class => @author_class
163
+ end
164
+
165
+ should "raise exception if invalid" do
166
+ post = @post_class.create
167
+ assert_raises(MongoMapper::DocumentNotValid) do
168
+ post.author.create!
169
+ end
170
+ end
171
+
172
+ should "work if valid" do
173
+ post = @post_class.create
174
+ author = post.author.create!(:name => 'John')
175
+ post.author.should be_instance_of(@author_class)
176
+ post.author.should_not be_new
177
+ post.author.name.should == 'John'
178
+ post.author.should == author
179
+ post.author.post_id.should == post.id
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,168 @@
1
+ require 'test_helper'
2
+
3
+ class AccessibleTest < Test::Unit::TestCase
4
+ context 'A document with accessible attributes' do
5
+ setup do
6
+ @doc_class = Doc do
7
+ key :name, String
8
+ key :admin, Boolean, :default => false
9
+
10
+ attr_accessible :name
11
+ end
12
+
13
+ @doc = @doc_class.create(:name => 'Steve Sloan')
14
+ end
15
+
16
+ should 'have accessible attributes class method' do
17
+ @doc_class.accessible_attributes.should == [:name].to_set
18
+ end
19
+
20
+ should "default accessible attributes to nil" do
21
+ Doc().accessible_attributes.should be_nil
22
+ end
23
+
24
+ should "have accessible_attributes instance method" do
25
+ @doc.accessible_attributes.should equal(@doc_class.accessible_attributes)
26
+ end
27
+
28
+ should "raise error if there are protected attributes" do
29
+ doc = Doc('Post')
30
+ doc.attr_protected :admin
31
+ lambda { doc.attr_accessible :name }.
32
+ should raise_error(/Declare either attr_protected or attr_accessible for Post/)
33
+ end
34
+
35
+ should "know if using accessible attributes" do
36
+ @doc_class.accessible_attributes?.should be(true)
37
+ Doc().accessible_attributes?.should be(false)
38
+ end
39
+
40
+ should "assign inaccessible attribute through accessor" do
41
+ @doc.admin = true
42
+ @doc.admin.should be_true
43
+ end
44
+
45
+ should "ignore inaccessible attribute on #initialize" do
46
+ doc = @doc_class.new(:name => 'John', :admin => true)
47
+ doc.admin.should be_false
48
+ doc.name.should == 'John'
49
+ end
50
+
51
+ should "not ignore inaccessible attributes on #initialize from the database" do
52
+ doc = @doc_class.new(:name => 'John')
53
+ doc.admin = true
54
+ doc.save!
55
+
56
+ doc = @doc_class.first(:name => 'John')
57
+ doc.admin.should be_true
58
+ doc.name.should == 'John'
59
+ end
60
+
61
+ should "ignore inaccessible attribute on #update_attributes" do
62
+ @doc.update_attributes(:name => 'Ren Hoek', :admin => true)
63
+ @doc.name.should == 'Ren Hoek'
64
+ @doc.admin.should be_false
65
+ end
66
+
67
+ should "ignore inaccessible attribute on #update_attributes!" do
68
+ @doc.update_attributes!(:name => 'Stimpson J. Cat', :admin => true)
69
+ @doc.name.should == 'Stimpson J. Cat'
70
+ @doc.admin.should be_false
71
+ end
72
+
73
+ should "be indifferent to whether the accessible keys are strings or symbols" do
74
+ @doc.update_attributes!("name" => 'Stimpson J. Cat', "admin" => true)
75
+ @doc.name.should == 'Stimpson J. Cat'
76
+ @doc.admin.should be_false
77
+ end
78
+
79
+ should "accept nil as constructor's argument without raising exception" do
80
+ lambda { @doc_class.new(nil) }.should_not raise_error
81
+ end
82
+ end
83
+
84
+ context "Single collection inherited accessible attributes" do
85
+ setup do
86
+ class ::GrandParent
87
+ include MongoMapper::Document
88
+ attr_accessible :name
89
+ key :name, String
90
+ key :site_id, ObjectId
91
+ end
92
+ GrandParent.collection.remove
93
+
94
+ class ::Child < ::GrandParent
95
+ attr_accessible :position
96
+ key :position, Integer
97
+ end
98
+
99
+ class ::GrandChild < ::Child; end
100
+
101
+ class ::OtherChild < ::GrandParent
102
+ attr_accessible :favorite_color
103
+ key :favorite_color, String
104
+ key :blog_id, ObjectId
105
+ end
106
+ end
107
+
108
+ teardown do
109
+ Object.send :remove_const, 'GrandParent' if defined?(::GrandParent)
110
+ Object.send :remove_const, 'Child' if defined?(::Child)
111
+ Object.send :remove_const, 'GrandChild' if defined?(::GrandChild)
112
+ Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
113
+ end
114
+
115
+ should "share keys down the inheritance trail" do
116
+ GrandParent.accessible_attributes.should == [:name].to_set
117
+ Child.accessible_attributes.should == [:name, :position].to_set
118
+ GrandChild.accessible_attributes.should == [:name, :position].to_set
119
+ OtherChild.accessible_attributes.should == [:name, :favorite_color].to_set
120
+ end
121
+ end
122
+
123
+ context "An embedded document with accessible attributes" do
124
+ setup do
125
+ @doc_class = Doc('Project')
126
+ @edoc_class = EDoc('Person') do
127
+ key :name, String
128
+ key :admin, Boolean, :default => false
129
+
130
+ attr_accessible :name
131
+ end
132
+ @doc_class.many :people, :class => @edoc_class
133
+
134
+ @doc = @doc_class.create(:title => 'MongoMapper')
135
+ @edoc = @edoc_class.new(:name => 'Steve Sloan')
136
+ @doc.people << @edoc
137
+ end
138
+
139
+ should "have accessible attributes class method" do
140
+ @edoc_class.accessible_attributes.should == [:name].to_set
141
+ end
142
+
143
+ should "default accessible attributes to nil" do
144
+ EDoc().accessible_attributes.should be_nil
145
+ end
146
+
147
+ should "have accessible attributes instance method" do
148
+ @edoc.accessible_attributes.should equal(@edoc_class.accessible_attributes)
149
+ end
150
+
151
+ should "assign inaccessible attribute through accessor" do
152
+ @edoc.admin = true
153
+ @edoc.admin.should be_true
154
+ end
155
+
156
+ should "ignore inaccessible attribute on #update_attributes" do
157
+ @edoc.update_attributes(:name => 'Ren Hoek', :admin => true)
158
+ @edoc.name.should == 'Ren Hoek'
159
+ @edoc.admin.should be_false
160
+ end
161
+
162
+ should "ignore inaccessible attribute on #update_attributes!" do
163
+ @edoc.update_attributes!(:name => 'Stimpson J. Cat', :admin => true)
164
+ @edoc.name.should == 'Stimpson J. Cat'
165
+ @edoc.admin.should be_false
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,44 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class AssociationsTest < Test::Unit::TestCase
5
+ should "allow changing class names" do
6
+ class AwesomeUser
7
+ include MongoMapper::Document
8
+
9
+ many :posts, :class_name => 'AssociationsTest::AwesomePost', :foreign_key => :creator_id
10
+ end
11
+ AwesomeUser.collection.remove
12
+
13
+ class AwesomeTag
14
+ include MongoMapper::EmbeddedDocument
15
+
16
+ key :name, String
17
+ key :post_id, ObjectId
18
+
19
+ belongs_to :post, :class_name => 'AssociationsTest::AwesomeUser'
20
+ end
21
+
22
+ class AwesomePost
23
+ include MongoMapper::Document
24
+
25
+ key :creator_id, ObjectId
26
+
27
+ belongs_to :creator, :class_name => 'AssociationsTest::AwesomeUser'
28
+ many :tags, :class_name => 'AssociationsTest::AwesomeTag', :foreign_key => :post_id
29
+ end
30
+
31
+ AwesomeUser.collection.remove
32
+ AwesomePost.collection.remove
33
+
34
+ user = AwesomeUser.create
35
+ tag1 = AwesomeTag.new(:name => 'awesome')
36
+ tag2 = AwesomeTag.new(:name => 'grand')
37
+ post1 = AwesomePost.create(:creator => user, :tags => [tag1])
38
+ post2 = AwesomePost.create(:creator => user, :tags => [tag2])
39
+ user.posts.should == [post1, post2]
40
+
41
+ post1 = post1.reload
42
+ post1.tags.should == [tag1]
43
+ end
44
+ end