hashrocket-mongomapper 0.3.3

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 (62) hide show
  1. data/.gitignore +7 -0
  2. data/History +70 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/Rakefile +73 -0
  6. data/VERSION +1 -0
  7. data/bin/mmconsole +56 -0
  8. data/lib/mongomapper.rb +70 -0
  9. data/lib/mongomapper/associations.rb +84 -0
  10. data/lib/mongomapper/associations/base.rb +69 -0
  11. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  12. data/lib/mongomapper/associations/belongs_to_proxy.rb +22 -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/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 +63 -0
  19. data/lib/mongomapper/callbacks.rb +106 -0
  20. data/lib/mongomapper/document.rb +337 -0
  21. data/lib/mongomapper/dynamic_finder.rb +38 -0
  22. data/lib/mongomapper/embedded_document.rb +267 -0
  23. data/lib/mongomapper/finder_options.rb +85 -0
  24. data/lib/mongomapper/key.rb +76 -0
  25. data/lib/mongomapper/observing.rb +50 -0
  26. data/lib/mongomapper/pagination.rb +52 -0
  27. data/lib/mongomapper/rails_compatibility/document.rb +15 -0
  28. data/lib/mongomapper/rails_compatibility/embedded_document.rb +25 -0
  29. data/lib/mongomapper/save_with_validation.rb +19 -0
  30. data/lib/mongomapper/serialization.rb +55 -0
  31. data/lib/mongomapper/serializers/json_serializer.rb +92 -0
  32. data/lib/mongomapper/support.rb +30 -0
  33. data/lib/mongomapper/validations.rb +61 -0
  34. data/mongomapper.gemspec +142 -0
  35. data/test/NOTE_ON_TESTING +1 -0
  36. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +53 -0
  37. data/test/functional/associations/test_belongs_to_proxy.rb +45 -0
  38. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +131 -0
  39. data/test/functional/associations/test_many_embedded_proxy.rb +106 -0
  40. data/test/functional/associations/test_many_polymorphic_proxy.rb +261 -0
  41. data/test/functional/associations/test_many_proxy.rb +295 -0
  42. data/test/functional/test_associations.rb +47 -0
  43. data/test/functional/test_callbacks.rb +85 -0
  44. data/test/functional/test_document.rb +952 -0
  45. data/test/functional/test_pagination.rb +81 -0
  46. data/test/functional/test_rails_compatibility.rb +30 -0
  47. data/test/functional/test_validations.rb +172 -0
  48. data/test/models.rb +139 -0
  49. data/test/test_helper.rb +67 -0
  50. data/test/unit/serializers/test_json_serializer.rb +157 -0
  51. data/test/unit/test_association_base.rb +144 -0
  52. data/test/unit/test_document.rb +123 -0
  53. data/test/unit/test_embedded_document.rb +526 -0
  54. data/test/unit/test_finder_options.rb +183 -0
  55. data/test/unit/test_key.rb +247 -0
  56. data/test/unit/test_mongomapper.rb +28 -0
  57. data/test/unit/test_observing.rb +101 -0
  58. data/test/unit/test_pagination.rb +113 -0
  59. data/test/unit/test_rails_compatibility.rb +34 -0
  60. data/test/unit/test_serializations.rb +52 -0
  61. data/test/unit/test_validations.rb +500 -0
  62. 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,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
@@ -0,0 +1,139 @@
1
+ class Address
2
+ include MongoMapper::EmbeddedDocument
3
+
4
+ key :address, String
5
+ key :city, String
6
+ key :state, String
7
+ key :zip, Integer
8
+ end
9
+
10
+ class Message
11
+ include MongoMapper::Document
12
+
13
+ key :body, String
14
+ key :position, Integer
15
+ key :_type, String
16
+ key :room_id, String
17
+
18
+ belongs_to :room
19
+ end
20
+
21
+ class Enter < Message; end
22
+ class Exit < Message; end
23
+ class Chat < Message; end
24
+
25
+ class Room
26
+ include MongoMapper::Document
27
+
28
+ key :name, String
29
+ many :messages, :polymorphic => true
30
+ end
31
+
32
+ class Project
33
+ include MongoMapper::Document
34
+
35
+ key :name, String
36
+ many :statuses
37
+ many :addresses
38
+ end
39
+
40
+ class Status
41
+ include MongoMapper::Document
42
+
43
+ key :project_id, String
44
+ key :target_id, String
45
+ key :target_type, String
46
+ key :name, String
47
+ key :position, Integer
48
+
49
+ belongs_to :project
50
+ belongs_to :target, :polymorphic => true
51
+ end
52
+
53
+ class RealPerson
54
+ include MongoMapper::Document
55
+
56
+ many :pets
57
+ key :name, String
58
+
59
+ def realname=(n)
60
+ self.name = n
61
+ end
62
+ end
63
+
64
+ class Person
65
+ include MongoMapper::EmbeddedDocument
66
+
67
+ key :name, String
68
+ key :child, Person
69
+
70
+ many :pets
71
+ end
72
+
73
+ class Pet
74
+ include MongoMapper::EmbeddedDocument
75
+
76
+ key :name, String
77
+ key :species, String
78
+ end
79
+
80
+ class Media
81
+ include MongoMapper::EmbeddedDocument
82
+
83
+ key :_type, String
84
+ key :file, String
85
+ end
86
+
87
+ class Video < Media
88
+ key :length, Integer
89
+ end
90
+
91
+ class Image < Media
92
+ key :width, Integer
93
+ key :height, Integer
94
+ end
95
+
96
+ class Music < Media
97
+ key :bitrate, String
98
+ end
99
+
100
+ class Catalog
101
+ include MongoMapper::Document
102
+
103
+ many :medias, :polymorphic => true
104
+ end
105
+
106
+ module TrModels
107
+ class Transport
108
+ include MongoMapper::EmbeddedDocument
109
+
110
+ key :_type, String
111
+ key :license_plate, String
112
+ end
113
+
114
+ class Car < TrModels::Transport
115
+ include MongoMapper::EmbeddedDocument
116
+
117
+ key :model, String
118
+ key :year, Integer
119
+ end
120
+
121
+ class Bus < TrModels::Transport
122
+ include MongoMapper::EmbeddedDocument
123
+
124
+ key :max_passengers, Integer
125
+ end
126
+
127
+ class Ambulance < TrModels::Transport
128
+ include MongoMapper::EmbeddedDocument
129
+
130
+ key :icu, Boolean
131
+ end
132
+
133
+ class Fleet
134
+ include MongoMapper::Document
135
+
136
+ many :transports, :polymorphic => true, :class_name => "TrModels::Transport"
137
+ key :name, String
138
+ end
139
+ 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