mongo_mapper 0.7.6 → 0.8.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 (134) hide show
  1. data/README.rdoc +4 -8
  2. data/bin/mmconsole +1 -1
  3. data/examples/keys.rb +37 -0
  4. data/examples/plugins.rb +41 -0
  5. data/examples/querying.rb +35 -0
  6. data/examples/scopes.rb +52 -0
  7. data/lib/mongo_mapper.rb +77 -97
  8. data/lib/mongo_mapper/connection.rb +83 -0
  9. data/lib/mongo_mapper/document.rb +10 -252
  10. data/lib/mongo_mapper/embedded_document.rb +7 -46
  11. data/lib/mongo_mapper/exceptions.rb +30 -0
  12. data/lib/mongo_mapper/extensions/array.rb +19 -0
  13. data/lib/mongo_mapper/extensions/binary.rb +22 -0
  14. data/lib/mongo_mapper/extensions/boolean.rb +44 -0
  15. data/lib/mongo_mapper/extensions/date.rb +25 -0
  16. data/lib/mongo_mapper/extensions/float.rb +14 -0
  17. data/lib/mongo_mapper/extensions/hash.rb +14 -0
  18. data/lib/mongo_mapper/extensions/integer.rb +19 -0
  19. data/lib/mongo_mapper/extensions/kernel.rb +9 -0
  20. data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
  21. data/lib/mongo_mapper/extensions/object.rb +27 -0
  22. data/lib/mongo_mapper/extensions/object_id.rb +30 -0
  23. data/lib/mongo_mapper/extensions/set.rb +20 -0
  24. data/lib/mongo_mapper/extensions/string.rb +18 -0
  25. data/lib/mongo_mapper/extensions/time.rb +29 -0
  26. data/lib/mongo_mapper/plugins.rb +1 -21
  27. data/lib/mongo_mapper/plugins/accessible.rb +44 -0
  28. data/lib/mongo_mapper/plugins/associations.rb +7 -24
  29. data/lib/mongo_mapper/plugins/associations/base.rb +1 -0
  30. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +5 -6
  31. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +5 -6
  32. data/lib/mongo_mapper/plugins/associations/collection.rb +1 -0
  33. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +2 -1
  34. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +22 -39
  35. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +4 -4
  36. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +22 -23
  37. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +1 -0
  38. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +1 -0
  39. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -0
  40. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +2 -3
  41. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +6 -7
  42. data/lib/mongo_mapper/plugins/associations/proxy.rb +8 -6
  43. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  44. data/lib/mongo_mapper/plugins/callbacks.rb +4 -3
  45. data/lib/mongo_mapper/plugins/clone.rb +10 -4
  46. data/lib/mongo_mapper/plugins/descendants.rb +1 -0
  47. data/lib/mongo_mapper/plugins/dirty.rb +1 -0
  48. data/lib/mongo_mapper/plugins/document.rb +41 -0
  49. data/lib/mongo_mapper/plugins/dynamic_querying.rb +41 -0
  50. data/lib/mongo_mapper/{support/find.rb → plugins/dynamic_querying/dynamic_finder.rb} +3 -36
  51. data/lib/mongo_mapper/plugins/embedded_document.rb +49 -0
  52. data/lib/mongo_mapper/plugins/equality.rb +3 -9
  53. data/lib/mongo_mapper/plugins/identity_map.rb +8 -10
  54. data/lib/mongo_mapper/plugins/indexes.rb +12 -0
  55. data/lib/mongo_mapper/plugins/inspect.rb +1 -0
  56. data/lib/mongo_mapper/plugins/keys.rb +15 -27
  57. data/lib/mongo_mapper/plugins/keys/key.rb +14 -3
  58. data/lib/mongo_mapper/plugins/logger.rb +1 -0
  59. data/lib/mongo_mapper/plugins/modifiers.rb +3 -2
  60. data/lib/mongo_mapper/plugins/pagination.rb +5 -15
  61. data/lib/mongo_mapper/plugins/persistence.rb +12 -11
  62. data/lib/mongo_mapper/plugins/protected.rb +8 -0
  63. data/lib/mongo_mapper/plugins/querying.rb +236 -0
  64. data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
  65. data/lib/mongo_mapper/plugins/rails.rb +1 -0
  66. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  67. data/lib/mongo_mapper/plugins/sci.rb +32 -0
  68. data/lib/mongo_mapper/plugins/scopes.rb +21 -0
  69. data/lib/mongo_mapper/plugins/serialization.rb +1 -0
  70. data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
  71. data/lib/mongo_mapper/plugins/userstamps.rb +1 -0
  72. data/lib/mongo_mapper/plugins/validations.rb +5 -1
  73. data/lib/mongo_mapper/support/descendant_appends.rb +5 -6
  74. data/lib/mongo_mapper/version.rb +2 -1
  75. data/test/NOTE_ON_TESTING +1 -0
  76. data/test/active_model_lint_test.rb +13 -0
  77. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  78. data/test/functional/associations/test_belongs_to_proxy.rb +93 -0
  79. data/test/functional/associations/test_in_array_proxy.rb +319 -0
  80. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  81. data/test/functional/associations/test_many_documents_proxy.rb +536 -0
  82. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  83. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  84. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  85. data/test/functional/associations/test_one_embedded_proxy.rb +58 -0
  86. data/test/functional/associations/test_one_proxy.rb +182 -0
  87. data/test/functional/test_accessible.rb +168 -0
  88. data/test/functional/test_associations.rb +44 -0
  89. data/test/functional/test_binary.rb +27 -0
  90. data/test/functional/test_caching.rb +76 -0
  91. data/test/functional/test_callbacks.rb +151 -0
  92. data/test/functional/test_dirty.rb +163 -0
  93. data/test/functional/test_document.rb +253 -0
  94. data/test/functional/test_dynamic_querying.rb +75 -0
  95. data/test/functional/test_embedded_document.rb +210 -0
  96. data/test/functional/test_identity_map.rb +506 -0
  97. data/test/functional/test_indexes.rb +42 -0
  98. data/test/functional/test_logger.rb +20 -0
  99. data/test/functional/test_modifiers.rb +416 -0
  100. data/test/functional/test_pagination.rb +91 -0
  101. data/test/functional/test_protected.rb +175 -0
  102. data/test/functional/test_querying.rb +873 -0
  103. data/test/functional/test_safe.rb +76 -0
  104. data/test/functional/test_sci.rb +230 -0
  105. data/test/functional/test_scopes.rb +171 -0
  106. data/test/functional/test_string_id_compatibility.rb +67 -0
  107. data/test/functional/test_timestamps.rb +62 -0
  108. data/test/functional/test_userstamps.rb +27 -0
  109. data/test/functional/test_validations.rb +342 -0
  110. data/test/models.rb +227 -0
  111. data/test/test_helper.rb +98 -0
  112. data/test/unit/associations/test_base.rb +212 -0
  113. data/test/unit/associations/test_proxy.rb +105 -0
  114. data/test/unit/serializers/test_json_serializer.rb +202 -0
  115. data/test/unit/test_clone.rb +69 -0
  116. data/test/unit/test_descendant_appends.rb +71 -0
  117. data/test/unit/test_document.rb +213 -0
  118. data/test/unit/test_dynamic_finder.rb +125 -0
  119. data/test/unit/test_embedded_document.rb +644 -0
  120. data/test/unit/test_extensions.rb +380 -0
  121. data/test/unit/test_key.rb +185 -0
  122. data/test/unit/test_keys.rb +55 -0
  123. data/test/unit/test_mongo_mapper.rb +110 -0
  124. data/test/unit/test_pagination.rb +11 -0
  125. data/test/unit/test_plugins.rb +50 -0
  126. data/test/unit/test_rails.rb +181 -0
  127. data/test/unit/test_rails_compatibility.rb +52 -0
  128. data/test/unit/test_serialization.rb +51 -0
  129. data/test/unit/test_time_zones.rb +39 -0
  130. data/test/unit/test_validations.rb +544 -0
  131. metadata +113 -44
  132. data/lib/mongo_mapper/plugins/pagination/proxy.rb +0 -72
  133. data/lib/mongo_mapper/query.rb +0 -23
  134. data/lib/mongo_mapper/support.rb +0 -196
@@ -0,0 +1,58 @@
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 "have boolean method for testing presence" do
49
+ @post_class.one :author, :class => @author_class
50
+
51
+ post = @post_class.new
52
+ post.author?.should be_false
53
+
54
+ post.author = @author_class.new(:name => 'Frank')
55
+ post.author?.should be_true
56
+ end
57
+
58
+ 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