crnixon-mongomapper 0.2.0 → 0.3.4

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 (68) hide show
  1. data/.gitignore +1 -0
  2. data/History +48 -0
  3. data/README.rdoc +5 -3
  4. data/Rakefile +6 -4
  5. data/VERSION +1 -1
  6. data/bin/mmconsole +56 -0
  7. data/lib/mongomapper.rb +29 -18
  8. data/lib/mongomapper/associations.rb +53 -38
  9. data/lib/mongomapper/associations/base.rb +53 -20
  10. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  11. data/lib/mongomapper/associations/belongs_to_proxy.rb +10 -14
  12. data/lib/mongomapper/associations/many_documents_as_proxy.rb +27 -0
  13. data/lib/mongomapper/associations/many_documents_proxy.rb +103 -0
  14. data/lib/mongomapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  15. data/lib/mongomapper/associations/{has_many_embedded_proxy.rb → many_embedded_proxy.rb} +6 -8
  16. data/lib/mongomapper/associations/many_polymorphic_proxy.rb +11 -0
  17. data/lib/mongomapper/associations/{array_proxy.rb → many_proxy.rb} +1 -1
  18. data/lib/mongomapper/associations/proxy.rb +24 -21
  19. data/lib/mongomapper/callbacks.rb +1 -1
  20. data/lib/mongomapper/document.rb +160 -74
  21. data/lib/mongomapper/dynamic_finder.rb +38 -0
  22. data/lib/mongomapper/embedded_document.rb +154 -105
  23. data/lib/mongomapper/finder_options.rb +11 -7
  24. data/lib/mongomapper/key.rb +15 -21
  25. data/lib/mongomapper/pagination.rb +52 -0
  26. data/lib/mongomapper/rails_compatibility/document.rb +15 -0
  27. data/lib/mongomapper/rails_compatibility/embedded_document.rb +25 -0
  28. data/lib/mongomapper/serialization.rb +1 -1
  29. data/lib/mongomapper/serializers/json_serializer.rb +15 -0
  30. data/lib/mongomapper/support.rb +30 -0
  31. data/mongomapper.gemspec +87 -46
  32. data/test/NOTE_ON_TESTING +1 -0
  33. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +53 -0
  34. data/test/functional/associations/test_belongs_to_proxy.rb +45 -0
  35. data/test/functional/associations/test_many_documents_as_proxy.rb +253 -0
  36. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +131 -0
  37. data/test/functional/associations/test_many_embedded_proxy.rb +106 -0
  38. data/test/functional/associations/test_many_polymorphic_proxy.rb +261 -0
  39. data/test/functional/associations/test_many_proxy.rb +295 -0
  40. data/test/functional/test_associations.rb +47 -0
  41. data/test/{test_callbacks.rb → functional/test_callbacks.rb} +2 -1
  42. data/test/functional/test_document.rb +952 -0
  43. data/test/functional/test_pagination.rb +81 -0
  44. data/test/functional/test_rails_compatibility.rb +30 -0
  45. data/test/functional/test_validations.rb +172 -0
  46. data/test/models.rb +169 -0
  47. data/test/test_helper.rb +7 -2
  48. data/test/unit/serializers/test_json_serializer.rb +189 -0
  49. data/test/unit/test_association_base.rb +144 -0
  50. data/test/unit/test_document.rb +123 -0
  51. data/test/unit/test_embedded_document.rb +526 -0
  52. data/test/{test_finder_options.rb → unit/test_finder_options.rb} +36 -1
  53. data/test/{test_key.rb → unit/test_key.rb} +59 -12
  54. data/test/{test_mongomapper.rb → unit/test_mongomapper.rb} +0 -0
  55. data/test/{test_observing.rb → unit/test_observing.rb} +0 -0
  56. data/test/unit/test_pagination.rb +113 -0
  57. data/test/unit/test_rails_compatibility.rb +34 -0
  58. data/test/{test_serializations.rb → unit/test_serializations.rb} +0 -2
  59. data/test/{test_validations.rb → unit/test_validations.rb} +0 -134
  60. metadata +81 -43
  61. data/lib/mongomapper/associations/has_many_proxy.rb +0 -28
  62. data/lib/mongomapper/associations/polymorphic_belongs_to_proxy.rb +0 -31
  63. data/lib/mongomapper/rails_compatibility.rb +0 -23
  64. data/test/serializers/test_json_serializer.rb +0 -104
  65. data/test/test_associations.rb +0 -174
  66. data/test/test_document.rb +0 -944
  67. data/test/test_embedded_document.rb +0 -253
  68. data/test/test_rails_compatibility.rb +0 -29
@@ -0,0 +1,81 @@
1
+ require 'test_helper'
2
+
3
+ class PaginationTest < Test::Unit::TestCase
4
+ context "Paginating" do
5
+ setup do
6
+ @document = Class.new do
7
+ include MongoMapper::Document
8
+ collection 'users'
9
+
10
+ key :first_name, String
11
+ key :last_name, String
12
+ key :age, Integer
13
+ end
14
+
15
+ @document.collection.clear
16
+
17
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
18
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
19
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
20
+ end
21
+
22
+ should "return the total pages" do
23
+ result = @document.paginate(:per_page => 2, :page => 1)
24
+ result.total_pages.should == 2
25
+ end
26
+
27
+ should "return the total of records" do
28
+ result = @document.paginate(:per_page => 2, :page => 1)
29
+ result.total_entries.should == 3
30
+ end
31
+
32
+ should "return the items" do
33
+ result = @document.paginate(:per_page => 2, :page => 1, :order => 'first_name')
34
+ result.size.should == 2
35
+ result.should == [@doc1, @doc3]
36
+ end
37
+
38
+ should "accept conditions" do
39
+ result = @document.paginate({
40
+ :conditions => {:last_name => 'Nunemaker'},
41
+ :order => "age DESC",
42
+ :per_page => 2,
43
+ :page => 1,
44
+ })
45
+ result.should == [@doc1, @doc3]
46
+ result.first.age.should == 27
47
+ end
48
+
49
+ should "withstand rigor" do
50
+ result = @document.paginate({
51
+ :per_page => 1,
52
+ :page => 1,
53
+ :order => 'age desc',
54
+ :conditions => {:last_name => 'Nunemaker'}
55
+ })
56
+ result.should == [@doc1]
57
+ result.total_entries.should == 2
58
+ result.total_pages.should == 2
59
+
60
+ result = @document.paginate({
61
+ :per_page => 1,
62
+ :page => 2,
63
+ :order => 'age desc',
64
+ :conditions => {:last_name => 'Nunemaker'}
65
+ })
66
+ result.should == [@doc3]
67
+ result.total_entries.should == 2
68
+ result.total_pages.should == 2
69
+
70
+ result = @document.paginate({
71
+ :per_page => 2,
72
+ :page => 1,
73
+ :order => 'age desc',
74
+ :conditions => {:last_name => 'Nunemaker'}
75
+ })
76
+ result.should == [@doc1, @doc3]
77
+ result.total_entries.should == 2
78
+ result.total_pages.should == 1
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ class TestRailsCompatibility < Test::Unit::TestCase
4
+ class Item
5
+ include MongoMapper::EmbeddedDocument
6
+ key :for_all, String
7
+ end
8
+
9
+ class Order
10
+ include MongoMapper::Document
11
+ many :items, :class_name => 'TestRailsCompatibility::Item'
12
+ key :order_only, String
13
+ end
14
+
15
+ context "Document" do
16
+ setup do
17
+ Order.collection.clear
18
+ end
19
+
20
+ should "have to_param that returns id" do
21
+ instance = Order.create('_id' => 1234)
22
+ instance.to_param.should == '1234'
23
+ end
24
+
25
+ should "alias new to new_record?" do
26
+ instance = Order.new
27
+ instance.new_record?.should == instance.new?
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,172 @@
1
+ require 'test_helper'
2
+
3
+ class ValidationsTest < Test::Unit::TestCase
4
+ context "Saving a new document that is invalid" do
5
+ setup do
6
+ @document = Class.new do
7
+ include MongoMapper::Document
8
+ key :name, String, :required => true
9
+ end
10
+ @document.collection.clear
11
+ end
12
+
13
+ should "not insert document" do
14
+ doc = @document.new
15
+ doc.save
16
+ @document.count.should == 0
17
+ end
18
+
19
+ should "populate document's errors" do
20
+ doc = @document.new
21
+ doc.errors.size.should == 0
22
+ doc.save
23
+ doc.errors.full_messages.should == ["Name can't be empty"]
24
+ end
25
+ end
26
+
27
+ context "Saving a document that is invalid (destructive)" do
28
+ setup do
29
+ @document = Class.new do
30
+ include MongoMapper::Document
31
+ key :name, String, :required => true
32
+ end
33
+ @document.collection.clear
34
+ end
35
+
36
+ should "raise error" do
37
+ doc = @document.new
38
+ lambda { doc.save! }.should raise_error(MongoMapper::DocumentNotValid)
39
+ end
40
+ end
41
+
42
+ context "Saving an existing document that is invalid" do
43
+ setup do
44
+ @document = Class.new do
45
+ include MongoMapper::Document
46
+ key :name, String, :required => true
47
+ end
48
+ @document.collection.clear
49
+
50
+ @doc = @document.create(:name => 'John Nunemaker')
51
+ end
52
+
53
+ should "not update document" do
54
+ @doc.name = nil
55
+ @doc.save
56
+ @document.find(@doc.id).name.should == 'John Nunemaker'
57
+ end
58
+
59
+ should "populate document's errors" do
60
+ @doc.name = nil
61
+ @doc.save
62
+ @doc.errors.full_messages.should == ["Name can't be empty"]
63
+ end
64
+ end
65
+
66
+ context "Adding validation errors" do
67
+ setup do
68
+ @document = Class.new do
69
+ include MongoMapper::Document
70
+ key :action, String
71
+ def action_present
72
+ errors.add(:action, 'is invalid') if action.blank?
73
+ end
74
+ end
75
+ @document.collection.clear
76
+ end
77
+
78
+ should "work with validate_on_create callback" do
79
+ @document.validate_on_create :action_present
80
+
81
+ doc = @document.new
82
+ doc.action = nil
83
+ doc.should have_error_on(:action)
84
+
85
+ doc.action = 'kick'
86
+ doc.should_not have_error_on(:action)
87
+ doc.save
88
+
89
+ doc.action = nil
90
+ doc.should_not have_error_on(:action)
91
+ end
92
+
93
+ should "work with validate_on_update callback" do
94
+ @document.validate_on_update :action_present
95
+
96
+ doc = @document.new
97
+ doc.action = nil
98
+ doc.should_not have_error_on(:action)
99
+ doc.save
100
+
101
+ doc.action = nil
102
+ doc.should have_error_on(:action)
103
+
104
+ doc.action = 'kick'
105
+ doc.should_not have_error_on(:action)
106
+ end
107
+ end
108
+
109
+ context "validating uniqueness of" do
110
+ setup do
111
+ @document = Class.new do
112
+ include MongoMapper::Document
113
+ key :name, String
114
+ validates_uniqueness_of :name
115
+ end
116
+ @document.collection.clear
117
+ end
118
+
119
+ should "not fail if object is new" do
120
+ doc = @document.new
121
+ doc.should_not have_error_on(:name)
122
+ end
123
+
124
+ should "allow to update an object" do
125
+ doc = @document.new("name" => "joe")
126
+ doc.save.should be_true
127
+
128
+ @document \
129
+ .stubs(:find) \
130
+ .with(:first, :conditions => {:name => 'joe'}, :limit => 1) \
131
+ .returns(doc)
132
+
133
+ doc.name = "joe"
134
+ doc.valid?.should be_true
135
+ doc.should_not have_error_on(:name)
136
+ end
137
+
138
+ should "fail if object name is not unique" do
139
+ doc = @document.new("name" => "joe")
140
+ doc.save.should be_true
141
+
142
+ @document \
143
+ .stubs(:find) \
144
+ .with(:first, :conditions => {:name => 'joe'}, :limit => 1) \
145
+ .returns(doc)
146
+
147
+ doc2 = @document.new("name" => "joe")
148
+ doc2.should have_error_on(:name)
149
+ end
150
+ end
151
+
152
+ context "validates uniqueness of with :unique shortcut" do
153
+ should "work" do
154
+ @document = Class.new do
155
+ include MongoMapper::Document
156
+ key :name, String, :unique => true
157
+ end
158
+ @document.collection.clear
159
+
160
+ doc = @document.create(:name => 'John')
161
+ doc.should_not have_error_on(:name)
162
+
163
+ @document \
164
+ .stubs(:find) \
165
+ .with(:first, :conditions => {:name => 'John'}, :limit => 1) \
166
+ .returns(doc)
167
+
168
+ second_john = @document.create(:name => 'John')
169
+ second_john.should have_error_on(:name, 'has already been taken')
170
+ end
171
+ end
172
+ end
data/test/models.rb ADDED
@@ -0,0 +1,169 @@
1
+ class Post
2
+ include MongoMapper::Document
3
+
4
+ key :title, String
5
+ key :body, String
6
+
7
+ has_many :comments, :as => :commentable, :class_name => 'PostComment'
8
+
9
+ timestamps!
10
+ end
11
+
12
+ class PostComment
13
+ include MongoMapper::Document
14
+
15
+ key :username, String, :default => 'Anonymous'
16
+ key :body, String
17
+
18
+ key :commentable_id, String
19
+ key :commentable_type, String
20
+ belongs_to :commentable, :polymorphic => true
21
+
22
+ timestamps!
23
+ end
24
+
25
+ class Address
26
+ include MongoMapper::EmbeddedDocument
27
+
28
+ key :address, String
29
+ key :city, String
30
+ key :state, String
31
+ key :zip, Integer
32
+ end
33
+
34
+ class Message
35
+ include MongoMapper::Document
36
+
37
+ key :body, String
38
+ key :position, Integer
39
+ key :_type, String
40
+ key :room_id, String
41
+
42
+ belongs_to :room
43
+ end
44
+
45
+ class Answer
46
+ include MongoMapper::Document
47
+
48
+ key :body, String
49
+ end
50
+
51
+ class Enter < Message; end
52
+ class Exit < Message; end
53
+ class Chat < Message; end
54
+
55
+ class Room
56
+ include MongoMapper::Document
57
+
58
+ key :name, String
59
+ many :messages, :polymorphic => true
60
+ end
61
+
62
+ class Project
63
+ include MongoMapper::Document
64
+
65
+ key :name, String
66
+ many :statuses
67
+ many :addresses
68
+ end
69
+
70
+ class Status
71
+ include MongoMapper::Document
72
+
73
+ key :project_id, String
74
+ key :target_id, String
75
+ key :target_type, String
76
+ key :name, String
77
+ key :position, Integer
78
+
79
+ belongs_to :project
80
+ belongs_to :target, :polymorphic => true
81
+ end
82
+
83
+ class RealPerson
84
+ include MongoMapper::Document
85
+
86
+ many :pets
87
+ key :name, String
88
+
89
+ def realname=(n)
90
+ self.name = n
91
+ end
92
+ end
93
+
94
+ class Person
95
+ include MongoMapper::EmbeddedDocument
96
+
97
+ key :name, String
98
+ key :child, Person
99
+
100
+ many :pets
101
+ end
102
+
103
+ class Pet
104
+ include MongoMapper::EmbeddedDocument
105
+
106
+ key :name, String
107
+ key :species, String
108
+ end
109
+
110
+ class Media
111
+ include MongoMapper::EmbeddedDocument
112
+
113
+ key :_type, String
114
+ key :file, String
115
+ end
116
+
117
+ class Video < Media
118
+ key :length, Integer
119
+ end
120
+
121
+ class Image < Media
122
+ key :width, Integer
123
+ key :height, Integer
124
+ end
125
+
126
+ class Music < Media
127
+ key :bitrate, String
128
+ end
129
+
130
+ class Catalog
131
+ include MongoMapper::Document
132
+
133
+ many :medias, :polymorphic => true
134
+ end
135
+
136
+ module TrModels
137
+ class Transport
138
+ include MongoMapper::EmbeddedDocument
139
+
140
+ key :_type, String
141
+ key :license_plate, String
142
+ end
143
+
144
+ class Car < TrModels::Transport
145
+ include MongoMapper::EmbeddedDocument
146
+
147
+ key :model, String
148
+ key :year, Integer
149
+ end
150
+
151
+ class Bus < TrModels::Transport
152
+ include MongoMapper::EmbeddedDocument
153
+
154
+ key :max_passengers, Integer
155
+ end
156
+
157
+ class Ambulance < TrModels::Transport
158
+ include MongoMapper::EmbeddedDocument
159
+
160
+ key :icu, Boolean
161
+ end
162
+
163
+ class Fleet
164
+ include MongoMapper::Document
165
+
166
+ many :transports, :polymorphic => true, :class_name => "TrModels::Transport"
167
+ key :name, String
168
+ end
169
+ end