drogus-mongo_mapper 0.6.10

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 (91) hide show
  1. data/.gitignore +10 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +29 -0
  4. data/Rakefile +55 -0
  5. data/VERSION +1 -0
  6. data/bin/mmconsole +60 -0
  7. data/lib/mongo_mapper.rb +131 -0
  8. data/lib/mongo_mapper/document.rb +417 -0
  9. data/lib/mongo_mapper/embedded_document.rb +55 -0
  10. data/lib/mongo_mapper/finder_options.rb +127 -0
  11. data/lib/mongo_mapper/plugins.rb +30 -0
  12. data/lib/mongo_mapper/plugins/associations.rb +104 -0
  13. data/lib/mongo_mapper/plugins/associations/base.rb +121 -0
  14. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
  15. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
  16. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  17. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
  18. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  19. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  20. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  21. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  22. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  23. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  24. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
  25. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  26. data/lib/mongo_mapper/plugins/callbacks.rb +134 -0
  27. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  28. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  29. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  30. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  31. data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
  32. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  33. data/lib/mongo_mapper/plugins/keys.rb +324 -0
  34. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  35. data/lib/mongo_mapper/plugins/pagination.rb +85 -0
  36. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  37. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  38. data/lib/mongo_mapper/plugins/serialization.rb +105 -0
  39. data/lib/mongo_mapper/plugins/validations.rb +57 -0
  40. data/lib/mongo_mapper/support.rb +217 -0
  41. data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
  42. data/lib/mongo_mapper/support/find.rb +77 -0
  43. data/mongo_mapper.gemspec +195 -0
  44. data/performance/read_write.rb +52 -0
  45. data/specs.watchr +51 -0
  46. data/test/NOTE_ON_TESTING +1 -0
  47. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  48. data/test/functional/associations/test_belongs_to_proxy.rb +101 -0
  49. data/test/functional/associations/test_in_array_proxy.rb +309 -0
  50. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  51. data/test/functional/associations/test_many_documents_proxy.rb +431 -0
  52. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  53. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  54. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  55. data/test/functional/associations/test_one_proxy.rb +161 -0
  56. data/test/functional/test_associations.rb +44 -0
  57. data/test/functional/test_binary.rb +27 -0
  58. data/test/functional/test_callbacks.rb +81 -0
  59. data/test/functional/test_dirty.rb +163 -0
  60. data/test/functional/test_document.rb +1264 -0
  61. data/test/functional/test_embedded_document.rb +125 -0
  62. data/test/functional/test_identity_map.rb +508 -0
  63. data/test/functional/test_logger.rb +20 -0
  64. data/test/functional/test_modifiers.rb +252 -0
  65. data/test/functional/test_pagination.rb +93 -0
  66. data/test/functional/test_protected.rb +155 -0
  67. data/test/functional/test_string_id_compatibility.rb +67 -0
  68. data/test/functional/test_validations.rb +329 -0
  69. data/test/models.rb +232 -0
  70. data/test/support/custom_matchers.rb +55 -0
  71. data/test/support/timing.rb +16 -0
  72. data/test/test_helper.rb +60 -0
  73. data/test/unit/associations/test_base.rb +207 -0
  74. data/test/unit/associations/test_proxy.rb +105 -0
  75. data/test/unit/serializers/test_json_serializer.rb +189 -0
  76. data/test/unit/test_descendant_appends.rb +71 -0
  77. data/test/unit/test_document.rb +231 -0
  78. data/test/unit/test_dynamic_finder.rb +123 -0
  79. data/test/unit/test_embedded_document.rb +663 -0
  80. data/test/unit/test_finder_options.rb +329 -0
  81. data/test/unit/test_keys.rb +169 -0
  82. data/test/unit/test_mongo_mapper.rb +65 -0
  83. data/test/unit/test_pagination.rb +127 -0
  84. data/test/unit/test_plugins.rb +50 -0
  85. data/test/unit/test_rails.rb +123 -0
  86. data/test/unit/test_rails_compatibility.rb +52 -0
  87. data/test/unit/test_serialization.rb +51 -0
  88. data/test/unit/test_support.rb +354 -0
  89. data/test/unit/test_time_zones.rb +39 -0
  90. data/test/unit/test_validations.rb +544 -0
  91. metadata +290 -0
@@ -0,0 +1,161 @@
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 "send object id to target" do
17
+ @post_class.one :author, :class => @author_class
18
+
19
+ post = @post_class.new
20
+ author = @author_class.new(:name => 'Frank')
21
+ post.author = author
22
+ author.save.should be_true
23
+ post.save.should be_true
24
+
25
+ post.author.object_id.should == post.author.target.object_id
26
+ end
27
+
28
+ should "be able to replace the association" do
29
+ @post_class.one :author, :class => @author_class
30
+
31
+ post = @post_class.new
32
+ author = @author_class.new(:name => 'Frank')
33
+ post.author = author
34
+ post.reload
35
+
36
+ post.author.should == author
37
+ post.author.nil?.should be_false
38
+
39
+ new_author = @author_class.new(:name => 'Emily')
40
+ post.author = new_author
41
+ post.author.should == new_author
42
+ end
43
+
44
+ should "have boolean method for testing presence" do
45
+ @post_class.one :author, :class => @author_class
46
+
47
+ post = @post_class.new
48
+ post.author?.should be_false
49
+
50
+ post.author = @author_class.new(:name => 'Frank')
51
+ post.author?.should be_true
52
+ end
53
+
54
+ should "work with criteria" do
55
+ @post_class.one :primary_author, :class => @author_class, :primary => true
56
+ @post_class.one :author, :class => @author_class
57
+
58
+ post = @post_class.create
59
+ author = @author_class.create(:name => 'Frank', :primary => false, :post_id => post.id)
60
+ primary = @author_class.create(:name => 'Bill', :primary => true, :post_id => post.id)
61
+ post.author.should == author
62
+ post.primary_author.should == primary
63
+ end
64
+
65
+ should "unset the association" do
66
+ @post_class.one :author, :class => @author_class
67
+ post = @post_class.new
68
+ author = @author_class.new
69
+ post.author = author
70
+ post.reload
71
+
72
+ post.author = nil
73
+ post.author.nil?.should be_false
74
+ end
75
+
76
+ should "work with :dependent delete" do
77
+ @post_class.one :author, :class => @author_class, :dependent => :delete
78
+
79
+ post = @post_class.create
80
+ author = @author_class.new
81
+ post.author = author
82
+ post.reload
83
+
84
+ @author_class.any_instance.expects(:delete).once
85
+ post.author = @author_class.new
86
+ end
87
+
88
+ should "work with :dependent destroy" do
89
+ @post_class.one :author, :class => @author_class, :dependent => :destroy
90
+
91
+ post = @post_class.create
92
+ author = @author_class.new
93
+ post.author = author
94
+ post.reload
95
+
96
+ @author_class.any_instance.expects(:destroy).once
97
+ post.author = @author_class.new
98
+ end
99
+
100
+ should "work with :dependent nullify" do
101
+ @post_class.one :author, :class => @author_class, :dependent => :nullify
102
+
103
+ post = @post_class.create
104
+ author = @author_class.new
105
+ post.author = author
106
+ post.reload
107
+
108
+ post.author = @author_class.new
109
+
110
+ author.reload
111
+ author.post_id.should be_nil
112
+ end
113
+
114
+ should "be able to build" do
115
+ @post_class.one :author, :class => @author_class
116
+
117
+ post = @post_class.create
118
+ author = post.author.build(:name => 'John')
119
+ post.author.should be_instance_of(@author_class)
120
+ post.author.should be_new
121
+ post.author.name.should == 'John'
122
+ post.author.should == author
123
+ post.author.post_id.should == post.id
124
+ end
125
+
126
+ should "be able to create" do
127
+ @post_class.one :author, :class => @author_class
128
+
129
+ post = @post_class.create
130
+ author = post.author.create(:name => 'John')
131
+ post.author.should be_instance_of(@author_class)
132
+ post.author.should_not be_new
133
+ post.author.name.should == 'John'
134
+ post.author.should == author
135
+ post.author.post_id.should == post.id
136
+ end
137
+
138
+ context "#create!" do
139
+ setup do
140
+ @author_class.key :name, String, :required => true
141
+ @post_class.one :author, :class => @author_class
142
+ end
143
+
144
+ should "raise exception if invalid" do
145
+ post = @post_class.create
146
+ assert_raises(MongoMapper::DocumentNotValid) do
147
+ post.author.create!
148
+ end
149
+ end
150
+
151
+ should "work if valid" do
152
+ post = @post_class.create
153
+ author = post.author.create!(:name => 'John')
154
+ post.author.should be_instance_of(@author_class)
155
+ post.author.should_not be_new
156
+ post.author.name.should == 'John'
157
+ post.author.should == author
158
+ post.author.post_id.should == post.id
159
+ end
160
+ end
161
+ 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
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class BinaryTest < Test::Unit::TestCase
4
+ should "serialize and deserialize correctly" do
5
+ klass = Doc do
6
+ key :contents, Binary
7
+ end
8
+
9
+ doc = klass.new(:contents => '010101')
10
+ doc.save
11
+
12
+ doc = doc.reload
13
+ doc.contents.to_s.should == ByteBuffer.new('010101').to_s
14
+ end
15
+
16
+ context "Saving a document with a blank binary value" do
17
+ setup do
18
+ @document = Doc do
19
+ key :file, Binary
20
+ end
21
+ end
22
+
23
+ should "not fail" do
24
+ assert_nothing_raised { @document.new(:file => nil).save }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,81 @@
1
+ require 'test_helper'
2
+
3
+ class CallbacksTest < Test::Unit::TestCase
4
+ context "Defining and running callbacks" do
5
+ setup do
6
+ @document = Doc do
7
+ key :name, String
8
+
9
+ [ :before_validation_on_create, :before_validation_on_update,
10
+ :before_validation, :after_validation,
11
+ :before_create, :after_create,
12
+ :before_update, :after_update,
13
+ :before_save, :after_save,
14
+ :before_destroy, :after_destroy].each do |callback|
15
+ callback_method = "#{callback}_callback"
16
+ send(callback, callback_method)
17
+ define_method(callback_method) do
18
+ history << callback.to_sym
19
+ end
20
+ end
21
+
22
+ def history
23
+ @history ||= []
24
+ end
25
+
26
+ def clear_history
27
+ @history = nil
28
+ end
29
+ end
30
+ end
31
+
32
+ should "get the order right for creating documents" do
33
+ doc = @document.create(:name => 'John Nunemaker')
34
+ doc.history.should == [:before_validation, :before_validation_on_create, :after_validation, :before_save, :before_create, :after_create, :after_save]
35
+ end
36
+
37
+ should "get the order right for updating documents" do
38
+ doc = @document.create(:name => 'John Nunemaker')
39
+ doc.clear_history
40
+ doc.name = 'John'
41
+ doc.save
42
+ doc.history.should == [:before_validation, :before_validation_on_update, :after_validation, :before_save, :before_update, :after_update, :after_save]
43
+ end
44
+
45
+ should "work for before and after validation" do
46
+ doc = @document.new(:name => 'John Nunemaker')
47
+ doc.valid?
48
+ doc.history.should include(:before_validation)
49
+ doc.history.should include(:after_validation)
50
+ end
51
+
52
+ should "work for before and after create" do
53
+ doc = @document.create(:name => 'John Nunemaker')
54
+ doc.history.should include(:before_create)
55
+ doc.history.should include(:after_create)
56
+ end
57
+
58
+ should "work for before and after update" do
59
+ doc = @document.create(:name => 'John Nunemaker')
60
+ doc.name = 'John Doe'
61
+ doc.save
62
+ doc.history.should include(:before_update)
63
+ doc.history.should include(:after_update)
64
+ end
65
+
66
+ should "work for before and after save" do
67
+ doc = @document.new
68
+ doc.name = 'John Doe'
69
+ doc.save
70
+ doc.history.should include(:before_save)
71
+ doc.history.should include(:after_save)
72
+ end
73
+
74
+ should "work for before and after destroy" do
75
+ doc = @document.create(:name => 'John Nunemaker')
76
+ doc.destroy
77
+ doc.history.should include(:before_destroy)
78
+ doc.history.should include(:after_destroy)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,163 @@
1
+ require 'test_helper'
2
+
3
+ class DirtyTest < Test::Unit::TestCase
4
+ def setup
5
+ @document = Doc { key :phrase, String }
6
+ end
7
+
8
+ context "marking changes" do
9
+ should "not happen if there are none" do
10
+ doc = @document.new
11
+ doc.phrase_changed?.should be_false
12
+ doc.phrase_change.should be_nil
13
+ end
14
+
15
+ should "happen when change happens" do
16
+ doc = @document.new
17
+ doc.phrase = 'Golly Gee Willikers Batman'
18
+ doc.phrase_changed?.should be_true
19
+ doc.phrase_was.should be_nil
20
+ doc.phrase_change.should == [nil, 'Golly Gee Willikers Batman']
21
+ end
22
+
23
+ should "happen when initializing" do
24
+ doc = @document.new(:phrase => 'Foo')
25
+ doc.changed?.should be_true
26
+ end
27
+
28
+ should "clear changes on save" do
29
+ doc = @document.new
30
+ doc.phrase = 'Golly Gee Willikers Batman'
31
+ doc.phrase_changed?.should be_true
32
+ doc.save
33
+ doc.phrase_changed?.should_not be_true
34
+ doc.phrase_change.should be_nil
35
+ end
36
+
37
+ should "clear changes on save!" do
38
+ doc = @document.new
39
+ doc.phrase = 'Golly Gee Willikers Batman'
40
+ doc.phrase_changed?.should be_true
41
+ doc.save!
42
+ doc.phrase_changed?.should_not be_true
43
+ doc.phrase_change.should be_nil
44
+ end
45
+
46
+ should "not happen when loading from database" do
47
+ doc = @document.create(:phrase => 'Foo')
48
+ doc = @document.find(doc.id)
49
+
50
+ doc.changed?.should be_false
51
+ doc.phrase = 'Fart'
52
+ doc.changed?.should be_true
53
+ doc.reload
54
+ doc.changed?.should be_false
55
+ end
56
+
57
+ should "happen if changed after loading from database" do
58
+ doc = @document.create(:phrase => 'Foo')
59
+ doc.reload
60
+ doc.changed?.should be_false
61
+ doc.phrase = 'Bar'
62
+ doc.changed?.should be_true
63
+ end
64
+ end
65
+
66
+ context "blank new value and type integer" do
67
+ should "not mark changes" do
68
+ @document.key :age, Integer
69
+
70
+ [nil, ''].each do |value|
71
+ doc = @document.new
72
+ doc.age = value
73
+ doc.age_changed?.should be_false
74
+ doc.age_change.should be_nil
75
+ end
76
+ end
77
+ end
78
+
79
+ context "blank new value and type float" do
80
+ should "not mark changes" do
81
+ @document.key :amount, Float
82
+
83
+ [nil, ''].each do |value|
84
+ doc = @document.new
85
+ doc.amount = value
86
+ doc.amount_changed?.should be_false
87
+ doc.amount_change.should be_nil
88
+ end
89
+ end
90
+ end
91
+
92
+ context "changed?" do
93
+ should "be true if key changed" do
94
+ doc = @document.new
95
+ doc.phrase = 'A penny saved is a penny earned.'
96
+ doc.changed?.should be_true
97
+ end
98
+
99
+ should "be false if no keys changed" do
100
+ @document.new.changed?.should be_false
101
+ end
102
+ end
103
+
104
+ context "changes" do
105
+ should "be empty hash if no changes" do
106
+ @document.new.changes.should == {}
107
+ end
108
+
109
+ should "be hash of keys with values of changes if there are changes" do
110
+ doc = @document.new
111
+ doc.phrase = 'A penny saved is a penny earned.'
112
+ doc.changes['phrase'].should == [nil, 'A penny saved is a penny earned.']
113
+ end
114
+ end
115
+
116
+ context "changed" do
117
+ should "be empty array if no changes" do
118
+ @document.new.changed.should == []
119
+ end
120
+
121
+ should "be array of keys that have changed if there are changes" do
122
+ doc = @document.new
123
+ doc.phrase = 'A penny saved is a penny earned.'
124
+ doc.changed.should == ['phrase']
125
+ end
126
+ end
127
+
128
+ context "will_change!" do
129
+ should "mark changes" do
130
+ doc = @document.create(:phrase => 'Foo')
131
+
132
+ doc.phrase << 'bar'
133
+ doc.phrase_changed?.should be_false
134
+
135
+ doc.phrase_will_change!
136
+ doc.phrase_changed?.should be_true
137
+ doc.phrase_change.should == ['Foobar', 'Foobar']
138
+
139
+ doc.phrase << '!'
140
+ doc.phrase_changed?.should be_true
141
+ doc.phrase_change.should == ['Foobar', 'Foobar!']
142
+ end
143
+ end
144
+
145
+ context "changing a foreign key through association" do
146
+ should "mark changes" do
147
+ project_class = Doc do
148
+ key :name, String
149
+ end
150
+
151
+ milestone_class = Doc do
152
+ key :project_id, ObjectId
153
+ key :name, String
154
+ end
155
+ milestone_class.belongs_to :project, :class => project_class
156
+
157
+ milestone = milestone_class.create(:name => 'Launch')
158
+ milestone.project = project_class.create(:name => 'Harmony')
159
+ milestone.changed?.should be_true
160
+ milestone.changed.should == %w(project_id)
161
+ end
162
+ end
163
+ end