danielharan-mongo_mapper 0.6.5

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 (74) hide show
  1. data/.gitignore +10 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +53 -0
  4. data/Rakefile +55 -0
  5. data/VERSION +1 -0
  6. data/bin/mmconsole +60 -0
  7. data/lib/mongo_mapper.rb +134 -0
  8. data/lib/mongo_mapper/associations.rb +183 -0
  9. data/lib/mongo_mapper/associations/base.rb +110 -0
  10. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  11. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +22 -0
  12. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +25 -0
  13. data/lib/mongo_mapper/associations/many_documents_proxy.rb +127 -0
  14. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  15. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +53 -0
  16. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +11 -0
  17. data/lib/mongo_mapper/associations/many_proxy.rb +6 -0
  18. data/lib/mongo_mapper/associations/proxy.rb +80 -0
  19. data/lib/mongo_mapper/callbacks.rb +109 -0
  20. data/lib/mongo_mapper/dirty.rb +136 -0
  21. data/lib/mongo_mapper/document.rb +481 -0
  22. data/lib/mongo_mapper/dynamic_finder.rb +35 -0
  23. data/lib/mongo_mapper/embedded_document.rb +386 -0
  24. data/lib/mongo_mapper/finder_options.rb +133 -0
  25. data/lib/mongo_mapper/key.rb +36 -0
  26. data/lib/mongo_mapper/observing.rb +50 -0
  27. data/lib/mongo_mapper/pagination.rb +53 -0
  28. data/lib/mongo_mapper/rails_compatibility/document.rb +15 -0
  29. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +27 -0
  30. data/lib/mongo_mapper/serialization.rb +54 -0
  31. data/lib/mongo_mapper/serializers/json_serializer.rb +92 -0
  32. data/lib/mongo_mapper/support.rb +193 -0
  33. data/lib/mongo_mapper/validations.rb +41 -0
  34. data/mongo_mapper.gemspec +171 -0
  35. data/specs.watchr +32 -0
  36. data/test/NOTE_ON_TESTING +1 -0
  37. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +55 -0
  38. data/test/functional/associations/test_belongs_to_proxy.rb +48 -0
  39. data/test/functional/associations/test_many_documents_as_proxy.rb +246 -0
  40. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +156 -0
  41. data/test/functional/associations/test_many_embedded_proxy.rb +196 -0
  42. data/test/functional/associations/test_many_polymorphic_proxy.rb +339 -0
  43. data/test/functional/associations/test_many_proxy.rb +384 -0
  44. data/test/functional/test_associations.rb +44 -0
  45. data/test/functional/test_binary.rb +18 -0
  46. data/test/functional/test_callbacks.rb +85 -0
  47. data/test/functional/test_dirty.rb +159 -0
  48. data/test/functional/test_document.rb +1180 -0
  49. data/test/functional/test_embedded_document.rb +125 -0
  50. data/test/functional/test_logger.rb +20 -0
  51. data/test/functional/test_pagination.rb +95 -0
  52. data/test/functional/test_rails_compatibility.rb +25 -0
  53. data/test/functional/test_string_id_compatibility.rb +72 -0
  54. data/test/functional/test_validations.rb +369 -0
  55. data/test/models.rb +271 -0
  56. data/test/support/custom_matchers.rb +55 -0
  57. data/test/support/timing.rb +16 -0
  58. data/test/test_helper.rb +27 -0
  59. data/test/unit/serializers/test_json_serializer.rb +189 -0
  60. data/test/unit/test_association_base.rb +166 -0
  61. data/test/unit/test_document.rb +204 -0
  62. data/test/unit/test_dynamic_finder.rb +125 -0
  63. data/test/unit/test_embedded_document.rb +718 -0
  64. data/test/unit/test_finder_options.rb +296 -0
  65. data/test/unit/test_key.rb +172 -0
  66. data/test/unit/test_mongo_mapper.rb +65 -0
  67. data/test/unit/test_observing.rb +101 -0
  68. data/test/unit/test_pagination.rb +113 -0
  69. data/test/unit/test_rails_compatibility.rb +49 -0
  70. data/test/unit/test_serializations.rb +52 -0
  71. data/test/unit/test_support.rb +342 -0
  72. data/test/unit/test_time_zones.rb +40 -0
  73. data/test/unit/test_validations.rb +503 -0
  74. metadata +233 -0
@@ -0,0 +1,166 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class FooMonster; end
5
+
6
+ class AssociationBaseTest < Test::Unit::TestCase
7
+ include MongoMapper::Associations
8
+
9
+ should "initialize with type and name" do
10
+ base = Base.new(:many, :foos)
11
+ base.type.should == :many
12
+ base.name.should == :foos
13
+ end
14
+
15
+ should "also allow options when initializing" do
16
+ base = Base.new(:many, :foos, :polymorphic => true)
17
+ base.options[:polymorphic].should be_true
18
+ end
19
+
20
+ context "class_name" do
21
+ should "work for belongs_to" do
22
+ Base.new(:belongs_to, :user).class_name.should == 'User'
23
+ end
24
+
25
+ should "work for many" do
26
+ Base.new(:many, :smart_people).class_name.should == 'SmartPerson'
27
+ end
28
+
29
+ should "be changeable using class_name option" do
30
+ base = Base.new(:many, :smart_people, :class_name => 'IntelligentPerson')
31
+ base.class_name.should == 'IntelligentPerson'
32
+ end
33
+ end
34
+
35
+ context "klass" do
36
+ should "default to class_name constantized" do
37
+ Base.new(:belongs_to, :foo_monster).klass.should == FooMonster
38
+ end
39
+
40
+ should "be the specified class" do
41
+ anonnymous_class = Class.new
42
+ Base.new(:belongs_to, :foo_monster, :class => anonnymous_class).klass.should == anonnymous_class
43
+ end
44
+ end
45
+
46
+ context "many?" do
47
+ should "be true if many" do
48
+ Base.new(:many, :foos).many?.should be_true
49
+ end
50
+
51
+ should "be false if not many" do
52
+ Base.new(:belongs_to, :foo).many?.should be_false
53
+ end
54
+ end
55
+
56
+ context "finder_options" do
57
+ should "default to empty hash" do
58
+ base = Base.new(:many, :foos)
59
+ base.finder_options.should == {}
60
+ end
61
+
62
+ should "work with order" do
63
+ base = Base.new(:many, :foos, :order => 'position')
64
+ base.finder_options.should == {:order => 'position'}
65
+ end
66
+
67
+ should "correctly parse from options" do
68
+ base = Base.new(:many, :foos, :order => 'position', :somekey => 'somevalue')
69
+ base.finder_options.should == {:order => 'position', :somekey => 'somevalue'}
70
+ end
71
+ end
72
+
73
+ context "belongs_to?" do
74
+ should "be true if belongs_to" do
75
+ Base.new(:belongs_to, :foo).belongs_to?.should be_true
76
+ end
77
+
78
+ should "be false if not belongs_to" do
79
+ Base.new(:many, :foos).belongs_to?.should be_false
80
+ end
81
+ end
82
+
83
+ context "polymorphic?" do
84
+ should "be true if polymorphic" do
85
+ Base.new(:many, :foos, :polymorphic => true).polymorphic?.should be_true
86
+ end
87
+
88
+ should "be false if not polymorphic" do
89
+ Base.new(:many, :bars).polymorphic?.should be_false
90
+ end
91
+ end
92
+
93
+ context "type_key_name" do
94
+ should "be _type for many" do
95
+ Base.new(:many, :foos).type_key_name.should == '_type'
96
+ end
97
+
98
+ should "be association name _ type for belongs_to" do
99
+ Base.new(:belongs_to, :foo).type_key_name.should == 'foo_type'
100
+ end
101
+ end
102
+
103
+ context "foreign_key" do
104
+ should "default to assocation_name_id" do
105
+ base = Base.new(:belongs_to, :foo)
106
+ base.foreign_key.should == 'foo_id'
107
+ end
108
+
109
+ should "be overridable with :foreign_key option" do
110
+ base = Base.new(:belongs_to, :foo, :foreign_key => 'foobar_id')
111
+ base.foreign_key.should == 'foobar_id'
112
+ end
113
+ end
114
+
115
+ should "have ivar that is association name" do
116
+ Base.new(:belongs_to, :foo).ivar.should == '@_foo'
117
+ end
118
+
119
+ context "embeddable?" do
120
+ should "be true if class is embeddable" do
121
+ base = Base.new(:many, :medias)
122
+ base.embeddable?.should be_true
123
+ end
124
+
125
+ should "be false if class is not embeddable" do
126
+ base = Base.new(:many, :statuses)
127
+ base.embeddable?.should be_false
128
+
129
+ base = Base.new(:belongs_to, :project)
130
+ base.embeddable?.should be_false
131
+ end
132
+ end
133
+
134
+ context "proxy_class" do
135
+ should "be ManyProxy for many" do
136
+ base = Base.new(:many, :statuses)
137
+ base.proxy_class.should == ManyProxy
138
+ end
139
+
140
+ should "be ManyPolymorphicProxy for polymorphic many" do
141
+ base = Base.new(:many, :messages, :polymorphic => true)
142
+ base.proxy_class.should == ManyPolymorphicProxy
143
+ end
144
+
145
+ should "be ManyEmbeddedProxy for many embedded" do
146
+ base = Base.new(:many, :medias)
147
+ base.proxy_class.should == ManyEmbeddedProxy
148
+ end
149
+
150
+ should "be ManyEmbeddedPolymorphicProxy for polymorphic many embedded" do
151
+ base = Base.new(:many, :medias, :polymorphic => true)
152
+ base.proxy_class.should == ManyEmbeddedPolymorphicProxy
153
+ end
154
+
155
+ should "be BelongsToProxy for belongs_to" do
156
+ base = Base.new(:belongs_to, :project)
157
+ base.proxy_class.should == BelongsToProxy
158
+ end
159
+
160
+ should "be BelongsToPolymorphicProxy for polymorphic belongs_to" do
161
+ base = Base.new(:belongs_to, :target, :polymorphic => true)
162
+ base.proxy_class.should == BelongsToPolymorphicProxy
163
+ end
164
+ end
165
+
166
+ end
@@ -0,0 +1,204 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class DocumentTest < Test::Unit::TestCase
5
+ context "The Document Class" do
6
+ setup do
7
+ @document = Class.new do
8
+ include MongoMapper::Document
9
+ set_collection_name 'test'
10
+ end
11
+ @document.collection.remove
12
+ end
13
+
14
+ should "have logger method" do
15
+ @document.logger.should == MongoMapper.logger
16
+ @document.logger.should be_instance_of(Logger)
17
+ end
18
+
19
+ should "track its descendants" do
20
+ MongoMapper::Document.descendants.should include(@document)
21
+ end
22
+
23
+ should "use default database by default" do
24
+ @document.database.should == MongoMapper.database
25
+ end
26
+
27
+ should "have a connection" do
28
+ @document.connection.should be_instance_of(Mongo::Connection)
29
+ end
30
+
31
+ should "allow setting different connection without affecting the default" do
32
+ conn = Mongo::Connection.new
33
+ @document.connection conn
34
+ @document.connection.should == conn
35
+ @document.connection.should_not == MongoMapper.connection
36
+ end
37
+
38
+ should "allow setting a different database without affecting the default" do
39
+ @document.set_database_name 'test2'
40
+ @document.database_name.should == 'test2'
41
+ @document.database.name.should == 'test2'
42
+
43
+ another_document = Class.new do
44
+ include MongoMapper::Document
45
+ set_collection_name 'test'
46
+ end
47
+ another_document.database.should == MongoMapper.database
48
+ end
49
+
50
+ should "default collection name to class name tableized" do
51
+ class ::Item
52
+ include MongoMapper::Document
53
+ end
54
+
55
+ Item.collection.should be_instance_of(Mongo::Collection)
56
+ Item.collection.name.should == 'items'
57
+ end
58
+
59
+ should "default collection name of namespaced class to tableized with dot separation" do
60
+ module ::BloggyPoo
61
+ class Post
62
+ include MongoMapper::Document
63
+ end
64
+ end
65
+
66
+ BloggyPoo::Post.collection.should be_instance_of(Mongo::Collection)
67
+ BloggyPoo::Post.collection.name.should == 'bloggy_poo.posts'
68
+ end
69
+
70
+ should "allow setting the collection name" do
71
+ @document.set_collection_name('foobar')
72
+ @document.collection.should be_instance_of(Mongo::Collection)
73
+ @document.collection.name.should == 'foobar'
74
+ end
75
+ end # Document class
76
+
77
+ context "Documents that inherit from other documents" do
78
+ should "default collection name to inherited class" do
79
+ Message.collection_name.should == 'messages'
80
+ Enter.collection_name.should == 'messages'
81
+ Exit.collection_name.should == 'messages'
82
+ Chat.collection_name.should == 'messages'
83
+ end
84
+
85
+ should "default associations to inherited class" do
86
+ Message.associations.keys.should include("room")
87
+ Enter.associations.keys.should include("room")
88
+ Exit.associations.keys.should include("room")
89
+ Chat.associations.keys.should include("room")
90
+ end
91
+
92
+ should "track subclasses" do
93
+ Message.subclasses.should == [Enter, Exit, Chat]
94
+ end
95
+ end
96
+
97
+ context "An instance of a document" do
98
+ setup do
99
+ @document = Class.new do
100
+ include MongoMapper::Document
101
+ set_collection_name 'test'
102
+
103
+ key :name, String
104
+ key :age, Integer
105
+ end
106
+ @document.collection.remove
107
+ end
108
+
109
+ should "have access to logger" do
110
+ doc = @document.new
111
+ doc.logger.should == @document.logger
112
+ doc.logger.should be_instance_of(Logger)
113
+ end
114
+
115
+ should "have access to the class's collection" do
116
+ doc = @document.new
117
+ doc.collection.name.should == @document.collection.name
118
+ end
119
+
120
+ should "use default values if defined for keys" do
121
+ @document.key :active, Boolean, :default => true
122
+
123
+ @document.new.active.should be_true
124
+ @document.new(:active => false).active.should be_false
125
+ end
126
+
127
+ should "use default values if defined even when custom data type" do
128
+ @document.key :window, WindowSize, :default => WindowSize.new(600, 480)
129
+
130
+ doc = @document.new
131
+ doc.window.should == WindowSize.new(600, 480)
132
+ end
133
+
134
+ context "root document" do
135
+ should "have a nil _root_document" do
136
+ @document.new._root_document.should be_nil
137
+ end
138
+
139
+ should "set self to the root document on embedded documents" do
140
+ klass = Class.new do
141
+ include MongoMapper::Document
142
+ end
143
+
144
+ pets = Class.new do
145
+ include MongoMapper::EmbeddedDocument
146
+ end
147
+ klass.many :pets, :class => pets
148
+
149
+ doc = klass.new(:pets => [{}])
150
+ doc.pets.first._root_document.should == doc
151
+ end
152
+ end
153
+
154
+ context "new?" do
155
+ should "be true if no id" do
156
+ @document.new.new?.should be_true
157
+ end
158
+
159
+ should "be true if id but using custom id and not saved yet" do
160
+ @document.key :_id, String
161
+ doc = @document.new
162
+ doc.id = '1234'
163
+ doc.new?.should be_true
164
+ end
165
+ end
166
+
167
+ context "clone" do
168
+ should "not set the id" do
169
+ doc = @document.create(:name => "foo", :age => 27)
170
+ clone = doc.clone
171
+ clone.should be_new
172
+ end
173
+
174
+ should "copy the attributes" do
175
+ doc = @document.create(:name => "foo", :age => 27)
176
+ clone = doc.clone
177
+ clone.name.should == "foo"
178
+ clone.age.should == 27
179
+ end
180
+ end
181
+
182
+ context "equality" do
183
+ setup do
184
+ @oid = Mongo::ObjectID.new
185
+ end
186
+ should "be equal if id and class are the same" do
187
+ (@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be(true)
188
+ end
189
+
190
+ should "not be equal if class same but id different" do
191
+ (@document.new('_id' => @oid) == @document.new('_id' => Mongo::ObjectID.new)).should be(false)
192
+ end
193
+
194
+ should "not be equal if id same but class different" do
195
+ @another_document = Class.new do
196
+ include MongoMapper::Document
197
+ set_collection_name 'test'
198
+ end
199
+
200
+ (@document.new('_id' => @oid) == @another_document.new('_id' => @oid)).should be(false)
201
+ end
202
+ end
203
+ end # instance of a document
204
+ end # DocumentTest
@@ -0,0 +1,125 @@
1
+ require 'test_helper'
2
+
3
+ class DynamicFinderTest < Test::Unit::TestCase
4
+ include MongoMapper
5
+
6
+ should "initialize with method" do
7
+ finder = DynamicFinder.new(:foobar)
8
+ finder.method.should == :foobar
9
+ end
10
+
11
+ context "found?" do
12
+ should "be true for find_by" do
13
+ DynamicFinder.new(:find_by_foo).found?.should be_true
14
+ end
15
+
16
+ should "be true for find_by with !" do
17
+ DynamicFinder.new(:find_by_foo!).found?.should be_true
18
+ end
19
+
20
+ should "be true for find_all_by" do
21
+ DynamicFinder.new(:find_all_by_foo).found?.should be_true
22
+ end
23
+
24
+ should "be true for find_or_initialize_by" do
25
+ DynamicFinder.new(:find_or_initialize_by_foo).found?.should be_true
26
+ end
27
+
28
+ should "be true for find_or_create_by" do
29
+ DynamicFinder.new(:find_or_create_by_foo).found?.should be_true
30
+ end
31
+
32
+ should "be false for anything else" do
33
+ [:foobar, :bazwick].each do |method|
34
+ DynamicFinder.new(method).found?.should be_false
35
+ end
36
+ end
37
+ end
38
+
39
+ context "find_all_by" do
40
+ should "parse one attribute" do
41
+ DynamicFinder.new(:find_all_by_foo).attributes.should == %w(foo)
42
+ end
43
+
44
+ should "parse multiple attributes" do
45
+ DynamicFinder.new(:find_all_by_foo_and_bar).attributes.should == %w(foo bar)
46
+ DynamicFinder.new(:find_all_by_foo_and_bar_and_baz).attributes.should == %w(foo bar baz)
47
+ end
48
+
49
+ should "set finder to :all" do
50
+ DynamicFinder.new(:find_all_by_foo_and_bar).finder.should == :all
51
+ end
52
+ end
53
+
54
+ context "find_by" do
55
+ should "parse one attribute" do
56
+ DynamicFinder.new(:find_by_foo).attributes.should == %w(foo)
57
+ end
58
+
59
+ should "parse multiple attributes" do
60
+ DynamicFinder.new(:find_by_foo_and_bar).attributes.should == %w(foo bar)
61
+ end
62
+
63
+ should "set finder to :first" do
64
+ DynamicFinder.new(:find_by_foo).finder.should == :first
65
+ end
66
+
67
+ should "set bang to false" do
68
+ DynamicFinder.new(:find_by_foo).bang.should be_false
69
+ end
70
+ end
71
+
72
+ context "find_by with !" do
73
+ should "parse one attribute" do
74
+ DynamicFinder.new(:find_by_foo!).attributes.should == %w(foo)
75
+ end
76
+
77
+ should "parse multiple attributes" do
78
+ DynamicFinder.new(:find_by_foo_and_bar!).attributes.should == %w(foo bar)
79
+ end
80
+
81
+ should "set finder to :first" do
82
+ DynamicFinder.new(:find_by_foo!).finder.should == :first
83
+ end
84
+
85
+ should "set bang to true" do
86
+ DynamicFinder.new(:find_by_foo!).bang.should be_true
87
+ end
88
+ end
89
+
90
+ context "find_or_initialize_by" do
91
+ should "parse one attribute" do
92
+ DynamicFinder.new(:find_or_initialize_by_foo).attributes.should == %w(foo)
93
+ end
94
+
95
+ should "parse multiple attributes" do
96
+ DynamicFinder.new(:find_or_initialize_by_foo_and_bar).attributes.should == %w(foo bar)
97
+ end
98
+
99
+ should "set finder to :first" do
100
+ DynamicFinder.new(:find_or_initialize_by_foo).finder.should == :first
101
+ end
102
+
103
+ should "set instantiator to new" do
104
+ DynamicFinder.new(:find_or_initialize_by_foo).instantiator.should == :new
105
+ end
106
+ end
107
+
108
+ context "find_or_create_by" do
109
+ should "parse one attribute" do
110
+ DynamicFinder.new(:find_or_create_by_foo).attributes.should == %w(foo)
111
+ end
112
+
113
+ should "parse multiple attributes" do
114
+ DynamicFinder.new(:find_or_create_by_foo_and_bar).attributes.should == %w(foo bar)
115
+ end
116
+
117
+ should "set finder to :first" do
118
+ DynamicFinder.new(:find_or_create_by_foo).finder.should == :first
119
+ end
120
+
121
+ should "set instantiator to new" do
122
+ DynamicFinder.new(:find_or_create_by_foo).instantiator.should == :create
123
+ end
124
+ end
125
+ end