djsun-mongomapper 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +7 -0
  2. data/History +51 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/Rakefile +71 -0
  6. data/VERSION +1 -0
  7. data/bin/mmconsole +56 -0
  8. data/lib/mongomapper.rb +96 -0
  9. data/lib/mongomapper/associations.rb +61 -0
  10. data/lib/mongomapper/associations/base.rb +71 -0
  11. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +32 -0
  12. data/lib/mongomapper/associations/belongs_to_proxy.rb +22 -0
  13. data/lib/mongomapper/associations/many_documents_proxy.rb +85 -0
  14. data/lib/mongomapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  15. data/lib/mongomapper/associations/many_embedded_proxy.rb +17 -0
  16. data/lib/mongomapper/associations/many_polymorphic_proxy.rb +11 -0
  17. data/lib/mongomapper/associations/many_proxy.rb +6 -0
  18. data/lib/mongomapper/associations/proxy.rb +67 -0
  19. data/lib/mongomapper/callbacks.rb +106 -0
  20. data/lib/mongomapper/document.rb +278 -0
  21. data/lib/mongomapper/embedded_document.rb +237 -0
  22. data/lib/mongomapper/finder_options.rb +96 -0
  23. data/lib/mongomapper/key.rb +80 -0
  24. data/lib/mongomapper/observing.rb +50 -0
  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/save_with_validation.rb +19 -0
  29. data/lib/mongomapper/serialization.rb +55 -0
  30. data/lib/mongomapper/serializers/json_serializer.rb +79 -0
  31. data/lib/mongomapper/validations.rb +47 -0
  32. data/mongomapper.gemspec +139 -0
  33. data/test/NOTE_ON_TESTING +1 -0
  34. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +39 -0
  35. data/test/functional/associations/test_belongs_to_proxy.rb +35 -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 +267 -0
  39. data/test/functional/associations/test_many_proxy.rb +236 -0
  40. data/test/functional/test_associations.rb +40 -0
  41. data/test/functional/test_callbacks.rb +85 -0
  42. data/test/functional/test_document.rb +691 -0
  43. data/test/functional/test_pagination.rb +81 -0
  44. data/test/functional/test_rails_compatibility.rb +31 -0
  45. data/test/functional/test_validations.rb +172 -0
  46. data/test/models.rb +108 -0
  47. data/test/test_helper.rb +67 -0
  48. data/test/unit/serializers/test_json_serializer.rb +103 -0
  49. data/test/unit/test_association_base.rb +136 -0
  50. data/test/unit/test_document.rb +125 -0
  51. data/test/unit/test_embedded_document.rb +370 -0
  52. data/test/unit/test_finder_options.rb +214 -0
  53. data/test/unit/test_key.rb +217 -0
  54. data/test/unit/test_mongo_id.rb +35 -0
  55. data/test/unit/test_mongomapper.rb +28 -0
  56. data/test/unit/test_observing.rb +101 -0
  57. data/test/unit/test_pagination.rb +113 -0
  58. data/test/unit/test_rails_compatibility.rb +34 -0
  59. data/test/unit/test_serializations.rb +52 -0
  60. data/test/unit/test_validations.rb +259 -0
  61. metadata +189 -0
@@ -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,31 @@
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
+ id = MongoID.new
22
+ instance = Order.create('_id' => id.to_s)
23
+ instance.to_param.should == id.to_s
24
+ end
25
+
26
+ should "alias new to new_record?" do
27
+ instance = Order.new
28
+ instance.new_record?.should == instance.new?
29
+ end
30
+ end
31
+ 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,108 @@
1
+ class Address
2
+ include MongoMapper::EmbeddedDocument
3
+ key :address, String
4
+ key :city, String
5
+ key :state, String
6
+ key :zip, Integer
7
+ end
8
+
9
+ class Message
10
+ include MongoMapper::Document
11
+ key :body, String
12
+ belongs_to :room
13
+ end
14
+
15
+ class Enter < Message; end
16
+ class Exit < Message; end
17
+ class Chat < Message; end
18
+
19
+ class Room
20
+ include MongoMapper::Document
21
+ key :name, String
22
+ many :messages, :polymorphic => true
23
+ end
24
+
25
+ class Project
26
+ include MongoMapper::Document
27
+ key :name, String
28
+ many :statuses
29
+ many :addresses
30
+ end
31
+
32
+ class Status
33
+ include MongoMapper::Document
34
+ belongs_to :project
35
+ belongs_to :target, :polymorphic => true
36
+ key :name, String
37
+ end
38
+
39
+ class RealPerson
40
+ include MongoMapper::Document
41
+ many :pets
42
+ key :name, String
43
+ end
44
+
45
+ class Person
46
+ include MongoMapper::EmbeddedDocument
47
+ key :name, String
48
+ key :child, Person
49
+ many :pets
50
+ end
51
+
52
+ class Pet
53
+ include MongoMapper::EmbeddedDocument
54
+ key :name, String
55
+ key :species, String
56
+ end
57
+
58
+ class Media
59
+ include MongoMapper::EmbeddedDocument
60
+ key :file, String
61
+ end
62
+
63
+ class Video < Media
64
+ key :length, Integer
65
+ end
66
+
67
+ class Image < Media
68
+ key :width, Integer
69
+ key :height, Integer
70
+ end
71
+
72
+ class Music < Media
73
+ key :bitrate, String
74
+ end
75
+
76
+ class Catalog
77
+ include MongoMapper::Document
78
+ many :medias, :polymorphic => true
79
+ end
80
+
81
+ module TrModels
82
+ class Transport
83
+ include MongoMapper::EmbeddedDocument
84
+ key :license_plate, String
85
+ end
86
+
87
+ class Car < TrModels::Transport
88
+ include MongoMapper::EmbeddedDocument
89
+ key :model, String
90
+ key :year, Integer
91
+ end
92
+
93
+ class Bus < TrModels::Transport
94
+ include MongoMapper::EmbeddedDocument
95
+ key :max_passengers, Integer
96
+ end
97
+
98
+ class Ambulance < TrModels::Transport
99
+ include MongoMapper::EmbeddedDocument
100
+ key :icu, Boolean
101
+ end
102
+
103
+ class Fleet
104
+ include MongoMapper::Document
105
+ many :transports, :polymorphic => true, :class_name => "TrModels::Transport"
106
+ key :name, String
107
+ end
108
+ end
@@ -0,0 +1,67 @@
1
+ require 'pathname'
2
+ require 'pp'
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'shoulda'
6
+
7
+ gem 'mocha', '0.9.4'
8
+ gem 'jnunemaker-matchy', '0.4.0'
9
+
10
+ require 'matchy'
11
+ require 'mocha'
12
+
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ dir = (Pathname(__FILE__).dirname + '..' + 'lib').expand_path
15
+ require dir + 'mongomapper'
16
+
17
+ class Test::Unit::TestCase
18
+ def clear_all_collections
19
+ MongoMapper::Document.descendants.map(&:delete_all)
20
+ end
21
+
22
+ custom_matcher :be_nil do |receiver, matcher, args|
23
+ matcher.positive_failure_message = "Expected #{receiver} to be nil but it wasn't"
24
+ matcher.negative_failure_message = "Expected #{receiver} not to be nil but it was"
25
+ receiver.nil?
26
+ end
27
+
28
+ custom_matcher :be_true do |receiver, matcher, args|
29
+ matcher.positive_failure_message = "Expected #{receiver} to be true but it wasn't"
30
+ matcher.negative_failure_message = "Expected #{receiver} not to be true but it was"
31
+ receiver.eql?(true)
32
+ end
33
+
34
+ custom_matcher :be_false do |receiver, matcher, args|
35
+ matcher.positive_failure_message = "Expected #{receiver} to be false but it wasn't"
36
+ matcher.negative_failure_message = "Expected #{receiver} not to be false but it was"
37
+ receiver.eql?(false)
38
+ end
39
+
40
+ custom_matcher :be_valid do |receiver, matcher, args|
41
+ matcher.positive_failure_message = "Expected to be valid but it was invalid #{receiver.errors.inspect}"
42
+ matcher.negative_failure_message = "Expected to be invalid but it was valid #{receiver.errors.inspect}"
43
+ receiver.valid?
44
+ end
45
+
46
+ custom_matcher :have_error_on do |receiver, matcher, args|
47
+ receiver.valid?
48
+ attribute = args[0]
49
+ expected_message = args[1]
50
+
51
+ if expected_message.nil?
52
+ matcher.positive_failure_message = "#{receiver} had no errors on #{attribute}"
53
+ matcher.negative_failure_message = "#{receiver} had errors on #{attribute} #{receiver.errors.inspect}"
54
+ !receiver.errors.on(attribute).blank?
55
+ else
56
+ actual = receiver.errors.on(attribute)
57
+ matcher.positive_failure_message = %Q(Expected error on #{attribute} to be "#{expected_message}" but was "#{actual}")
58
+ matcher.negative_failure_message = %Q(Expected error on #{attribute} not to be "#{expected_message}" but was "#{actual}")
59
+ actual == expected_message
60
+ end
61
+ end
62
+ end
63
+
64
+ DefaultDatabase = 'test' unless defined?(DefaultDatabase)
65
+ AlternateDatabase = 'test2' unless defined?(AlternateDatabase)
66
+
67
+ MongoMapper.database = DefaultDatabase