djsun-mongo_mapper 0.5.0.1
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.
- data/.gitignore +8 -0
- data/LICENSE +20 -0
- data/README.rdoc +39 -0
- data/Rakefile +87 -0
- data/VERSION +1 -0
- data/bin/mmconsole +55 -0
- data/lib/mongo_mapper/associations/base.rb +83 -0
- data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
- data/lib/mongo_mapper/associations/belongs_to_proxy.rb +22 -0
- data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +27 -0
- data/lib/mongo_mapper/associations/many_documents_proxy.rb +116 -0
- data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
- data/lib/mongo_mapper/associations/many_embedded_proxy.rb +67 -0
- data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +11 -0
- data/lib/mongo_mapper/associations/many_proxy.rb +6 -0
- data/lib/mongo_mapper/associations/proxy.rb +74 -0
- data/lib/mongo_mapper/associations.rb +86 -0
- data/lib/mongo_mapper/callbacks.rb +106 -0
- data/lib/mongo_mapper/document.rb +308 -0
- data/lib/mongo_mapper/dynamic_finder.rb +35 -0
- data/lib/mongo_mapper/embedded_document.rb +354 -0
- data/lib/mongo_mapper/finder_options.rb +94 -0
- data/lib/mongo_mapper/key.rb +32 -0
- data/lib/mongo_mapper/observing.rb +50 -0
- data/lib/mongo_mapper/pagination.rb +51 -0
- data/lib/mongo_mapper/rails_compatibility/document.rb +15 -0
- data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +27 -0
- data/lib/mongo_mapper/save_with_validation.rb +19 -0
- data/lib/mongo_mapper/serialization.rb +55 -0
- data/lib/mongo_mapper/serializers/json_serializer.rb +92 -0
- data/lib/mongo_mapper/support.rb +171 -0
- data/lib/mongo_mapper/validations.rb +69 -0
- data/lib/mongo_mapper.rb +95 -0
- data/mongo_mapper.gemspec +156 -0
- data/specs.watchr +32 -0
- data/test/NOTE_ON_TESTING +1 -0
- data/test/custom_matchers.rb +48 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +55 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +49 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +244 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +132 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +174 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +297 -0
- data/test/functional/associations/test_many_proxy.rb +331 -0
- data/test/functional/test_associations.rb +44 -0
- data/test/functional/test_binary.rb +18 -0
- data/test/functional/test_callbacks.rb +85 -0
- data/test/functional/test_document.rb +964 -0
- data/test/functional/test_embedded_document.rb +97 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_pagination.rb +87 -0
- data/test/functional/test_rails_compatibility.rb +30 -0
- data/test/functional/test_validations.rb +279 -0
- data/test/models.rb +169 -0
- data/test/test_helper.rb +30 -0
- data/test/unit/serializers/test_json_serializer.rb +193 -0
- data/test/unit/test_association_base.rb +144 -0
- data/test/unit/test_document.rb +165 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +643 -0
- data/test/unit/test_finder_options.rb +193 -0
- data/test/unit/test_key.rb +175 -0
- data/test/unit/test_mongomapper.rb +28 -0
- data/test/unit/test_observing.rb +101 -0
- data/test/unit/test_pagination.rb +109 -0
- data/test/unit/test_rails_compatibility.rb +39 -0
- data/test/unit/test_serializations.rb +52 -0
- data/test/unit/test_support.rb +272 -0
- data/test/unit/test_time_zones.rb +40 -0
- data/test/unit/test_validations.rb +503 -0
- metadata +207 -0
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FinderOptionsTest < Test::Unit::TestCase
|
4
|
+
include MongoMapper
|
5
|
+
|
6
|
+
should "raise error if provided something other than a hash" do
|
7
|
+
lambda { FinderOptions.new }.should raise_error(ArgumentError)
|
8
|
+
lambda { FinderOptions.new(1) }.should raise_error(ArgumentError)
|
9
|
+
end
|
10
|
+
|
11
|
+
should "have symbolize the keys of the hash provided" do
|
12
|
+
FinderOptions.new('offset' => 1).options.keys.map do |key|
|
13
|
+
key.should be_instance_of(Symbol)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "#criteria" do
|
18
|
+
should "convert conditions to criteria" do
|
19
|
+
FinderOptions.expects(:to_mongo_criteria).with(:foo => 1).returns({})
|
20
|
+
FinderOptions.new(:conditions => {:foo => 1}).criteria
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "#options" do
|
25
|
+
should "convert options to mongo options" do
|
26
|
+
FinderOptions.expects(:to_mongo_options).with(:order => 'foo asc', :select => 'foo,bar').returns({})
|
27
|
+
FinderOptions.new(:order => 'foo asc', :select => 'foo,bar').options
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "Converting conditions to criteria" do
|
32
|
+
should "work with simple criteria" do
|
33
|
+
FinderOptions.to_mongo_criteria(:foo => 'bar').should == {
|
34
|
+
:foo => 'bar'
|
35
|
+
}
|
36
|
+
|
37
|
+
FinderOptions.to_mongo_criteria(:foo => 'bar', :baz => 'wick').should == {
|
38
|
+
:foo => 'bar',
|
39
|
+
:baz => 'wick'
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
should "convert id to _id" do
|
44
|
+
FinderOptions.to_mongo_criteria(:id => '1').should == {
|
45
|
+
:_id => '1'
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
should "use $in for arrays" do
|
50
|
+
FinderOptions.to_mongo_criteria(:foo => [1,2,3]).should == {
|
51
|
+
:foo => {'$in' => [1,2,3]}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
should "not use $in for arrays if already using array operator" do
|
56
|
+
FinderOptions.to_mongo_criteria(:foo => {'$all' => [1,2,3]}).should == {
|
57
|
+
:foo => {'$all' => [1,2,3]}
|
58
|
+
}
|
59
|
+
|
60
|
+
FinderOptions.to_mongo_criteria(:foo => {'$any' => [1,2,3]}).should == {
|
61
|
+
:foo => {'$any' => [1,2,3]}
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
should "work arbitrarily deep" do
|
66
|
+
FinderOptions.to_mongo_criteria(:foo => {:bar => [1,2,3]}).should == {
|
67
|
+
:foo => {:bar => {'$in' => [1,2,3]}}
|
68
|
+
}
|
69
|
+
|
70
|
+
FinderOptions.to_mongo_criteria(:foo => {:bar => {'$any' => [1,2,3]}}).should == {
|
71
|
+
:foo => {:bar => {'$any' => [1,2,3]}}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "ordering" do
|
77
|
+
should "single field with ascending direction" do
|
78
|
+
hash = OrderedHash.new
|
79
|
+
hash[:foo] = 1
|
80
|
+
FinderOptions.to_mongo_options(:order => 'foo asc')[:sort].should == hash
|
81
|
+
FinderOptions.to_mongo_options(:order => 'foo ASC')[:sort].should == hash
|
82
|
+
end
|
83
|
+
|
84
|
+
should "single field with descending direction" do
|
85
|
+
hash = OrderedHash.new
|
86
|
+
hash[:foo] = -1
|
87
|
+
FinderOptions.to_mongo_options(:order => 'foo desc')[:sort].should == hash
|
88
|
+
FinderOptions.to_mongo_options(:order => 'foo DESC')[:sort].should == hash
|
89
|
+
end
|
90
|
+
|
91
|
+
should "convert field without direction to ascending" do
|
92
|
+
hash = OrderedHash.new
|
93
|
+
hash[:foo] = 1
|
94
|
+
FinderOptions.to_mongo_options(:order => 'foo')[:sort].should == hash
|
95
|
+
end
|
96
|
+
|
97
|
+
should "convert multiple fields with directions" do
|
98
|
+
hash = OrderedHash.new
|
99
|
+
hash[:foo] = -1
|
100
|
+
hash[:bar] = 1
|
101
|
+
hash[:baz] = -1
|
102
|
+
FinderOptions.to_mongo_options(:order => 'foo desc, bar asc, baz desc')[:sort].should == hash
|
103
|
+
end
|
104
|
+
|
105
|
+
should "convert multiple fields with some missing directions" do
|
106
|
+
hash = OrderedHash.new
|
107
|
+
hash[:foo] = -1
|
108
|
+
hash[:bar] = 1
|
109
|
+
hash[:baz] = 1
|
110
|
+
FinderOptions.to_mongo_options(:order => 'foo desc, bar, baz')[:sort].should == hash
|
111
|
+
end
|
112
|
+
|
113
|
+
should "just use sort if sort and order are present" do
|
114
|
+
FinderOptions.to_mongo_options(:sort => {'$natural' => 1}, :order => 'foo asc')[:sort].should == {
|
115
|
+
'$natural' => 1
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
should "convert natural in order to proper" do
|
120
|
+
hash = OrderedHash.new
|
121
|
+
hash[:'$natural'] = 1
|
122
|
+
FinderOptions.to_mongo_options(:order => '$natural asc')[:sort].should == hash
|
123
|
+
hash[:'$natural'] = -1
|
124
|
+
FinderOptions.to_mongo_options(:order => '$natural desc')[:sort].should == hash
|
125
|
+
end
|
126
|
+
|
127
|
+
should "work for natural order ascending" do
|
128
|
+
FinderOptions.to_mongo_options(:sort => {'$natural' => 1})[:sort]['$natural'].should == 1
|
129
|
+
end
|
130
|
+
|
131
|
+
should "work for natural order descending" do
|
132
|
+
FinderOptions.to_mongo_options(:sort => {'$natural' => -1})[:sort]['$natural'].should == -1
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context "skip" do
|
137
|
+
should "default to 0" do
|
138
|
+
FinderOptions.to_mongo_options({})[:skip].should == 0
|
139
|
+
end
|
140
|
+
|
141
|
+
should "use skip provided" do
|
142
|
+
FinderOptions.to_mongo_options(:skip => 2)[:skip].should == 2
|
143
|
+
end
|
144
|
+
|
145
|
+
should "covert string to integer" do
|
146
|
+
FinderOptions.to_mongo_options(:skip => '2')[:skip].should == 2
|
147
|
+
end
|
148
|
+
|
149
|
+
should "convert offset to skip" do
|
150
|
+
FinderOptions.to_mongo_options(:offset => 1)[:skip].should == 1
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "limit" do
|
155
|
+
should "default to 0" do
|
156
|
+
FinderOptions.to_mongo_options({})[:limit].should == 0
|
157
|
+
end
|
158
|
+
|
159
|
+
should "use limit provided" do
|
160
|
+
FinderOptions.to_mongo_options(:limit => 2)[:limit].should == 2
|
161
|
+
end
|
162
|
+
|
163
|
+
should "covert string to integer" do
|
164
|
+
FinderOptions.to_mongo_options(:limit => '2')[:limit].should == 2
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "fields" do
|
169
|
+
should "default to nil" do
|
170
|
+
FinderOptions.to_mongo_options({})[:fields].should be(nil)
|
171
|
+
end
|
172
|
+
|
173
|
+
should "be converted to nil if empty string" do
|
174
|
+
FinderOptions.to_mongo_options(:fields => '')[:fields].should be(nil)
|
175
|
+
end
|
176
|
+
|
177
|
+
should "be converted to nil if []" do
|
178
|
+
FinderOptions.to_mongo_options(:fields => [])[:fields].should be(nil)
|
179
|
+
end
|
180
|
+
|
181
|
+
should "should work with array" do
|
182
|
+
FinderOptions.to_mongo_options({:fields => %w(a b)})[:fields].should == %w(a b)
|
183
|
+
end
|
184
|
+
|
185
|
+
should "convert comma separated list to array" do
|
186
|
+
FinderOptions.to_mongo_options({:fields => 'a, b'})[:fields].should == %w(a b)
|
187
|
+
end
|
188
|
+
|
189
|
+
should "also work as select" do
|
190
|
+
FinderOptions.new(:select => %w(a b)).options[:fields].should == %w(a b)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end # FinderOptionsTest
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Address
|
4
|
+
include MongoMapper::EmbeddedDocument
|
5
|
+
|
6
|
+
key :address, String
|
7
|
+
key :city, String
|
8
|
+
key :state, String
|
9
|
+
key :zip, Integer
|
10
|
+
end
|
11
|
+
|
12
|
+
class FooType < Struct.new(:bar)
|
13
|
+
def self.to_mongo(value)
|
14
|
+
'to_mongo'
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from_mongo(value)
|
18
|
+
'from_mongo'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class KeyTest < Test::Unit::TestCase
|
23
|
+
include MongoMapper
|
24
|
+
|
25
|
+
context "Initializing a new key" do
|
26
|
+
should "allow setting the name" do
|
27
|
+
Key.new(:foo, String).name.should == 'foo'
|
28
|
+
end
|
29
|
+
|
30
|
+
should "allow setting the type" do
|
31
|
+
Key.new(:foo, Integer).type.should be(Integer)
|
32
|
+
end
|
33
|
+
|
34
|
+
should "allow setting options" do
|
35
|
+
Key.new(:foo, Integer, :required => true).options[:required].should be(true)
|
36
|
+
end
|
37
|
+
|
38
|
+
should "default options to {}" do
|
39
|
+
Key.new(:foo, Integer, nil).options.should == {}
|
40
|
+
end
|
41
|
+
|
42
|
+
should "symbolize option keys" do
|
43
|
+
Key.new(:foo, Integer, 'required' => true).options[:required].should be(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
should "work with just name" do
|
47
|
+
key = Key.new(:foo)
|
48
|
+
key.name.should == 'foo'
|
49
|
+
end
|
50
|
+
|
51
|
+
should "work with name and type" do
|
52
|
+
key = Key.new(:foo, String)
|
53
|
+
key.name.should == 'foo'
|
54
|
+
key.type.should == String
|
55
|
+
end
|
56
|
+
|
57
|
+
should "work with name, type, and options" do
|
58
|
+
key = Key.new(:foo, String, :required => true)
|
59
|
+
key.name.should == 'foo'
|
60
|
+
key.type.should == String
|
61
|
+
key.options[:required].should be_true
|
62
|
+
end
|
63
|
+
|
64
|
+
should "work with name and options" do
|
65
|
+
key = Key.new(:foo, :required => true)
|
66
|
+
key.name.should == 'foo'
|
67
|
+
key.options[:required].should be_true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "A key" do
|
72
|
+
should "be equal to another key with same name and type" do
|
73
|
+
Key.new(:name, String).should == Key.new(:name, String)
|
74
|
+
end
|
75
|
+
|
76
|
+
should "not be equal to another key with different name" do
|
77
|
+
Key.new(:name, String).should_not == Key.new(:foo, String)
|
78
|
+
end
|
79
|
+
|
80
|
+
should "not be equal to another key with different type" do
|
81
|
+
Key.new(:name, String).should_not == Key.new(:name, Integer)
|
82
|
+
end
|
83
|
+
|
84
|
+
should "know if it is a embedded_document" do
|
85
|
+
klass = Class.new do
|
86
|
+
include MongoMapper::EmbeddedDocument
|
87
|
+
end
|
88
|
+
Key.new(:name, klass).embeddable?.should be_true
|
89
|
+
end
|
90
|
+
|
91
|
+
should "know if it is not a embedded_document" do
|
92
|
+
Key.new(:name, String).embeddable?.should be_false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "setting a value with a custom type" do
|
97
|
+
should "correctly typecast" do
|
98
|
+
key = Key.new(:foo, FooType)
|
99
|
+
key.set("something").should == 'to_mongo'
|
100
|
+
end
|
101
|
+
|
102
|
+
should "correctly typecast if object of that type is given" do
|
103
|
+
key = Key.new(:foo, FooType)
|
104
|
+
key.set(FooType.new('something')).should == 'to_mongo'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "getting a value with a custom type" do
|
109
|
+
should "use #from_mongo to convert back to custom type" do
|
110
|
+
key = Key.new(:foo, FooType)
|
111
|
+
key.get('something').should == 'from_mongo'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "getting a value" do
|
116
|
+
should "work with a type" do
|
117
|
+
key = Key.new(:foo, String)
|
118
|
+
key.get('bar').should == 'bar'
|
119
|
+
end
|
120
|
+
|
121
|
+
should "work without type" do
|
122
|
+
key = Key.new(:foo)
|
123
|
+
key.get([1, '2']).should == [1, '2']
|
124
|
+
key.get(false).should == false
|
125
|
+
key.get({}).should == {}
|
126
|
+
end
|
127
|
+
|
128
|
+
context "for a embedded_document" do
|
129
|
+
should "default to nil" do
|
130
|
+
key = Key.new(:foo, Address)
|
131
|
+
key.get(nil).should be_nil
|
132
|
+
end
|
133
|
+
|
134
|
+
should "return instance if instance" do
|
135
|
+
address = Address.new(:city => 'South Bend', :state => 'IN', :zip => 46544)
|
136
|
+
key = Key.new(:foo, Address)
|
137
|
+
key.get(address).should == address
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "string key with 'baz' default" do
|
143
|
+
setup do
|
144
|
+
@key = Key.new(:foo, String, :default => 'baz')
|
145
|
+
end
|
146
|
+
|
147
|
+
should "return default value if value nil" do
|
148
|
+
@key.get(nil).should == 'baz'
|
149
|
+
end
|
150
|
+
|
151
|
+
should "return value if not nil" do
|
152
|
+
@key.get('foobar').should == 'foobar'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "string key with '' default" do
|
157
|
+
setup do
|
158
|
+
@key = Key.new(:foo, String, :default => '')
|
159
|
+
end
|
160
|
+
|
161
|
+
should "return default value if value nil" do
|
162
|
+
@key.get(nil).should == ''
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "boolean key" do
|
167
|
+
should "with false default" do
|
168
|
+
Key.new(:active, Boolean, :default => false).get(nil).should be_false
|
169
|
+
end
|
170
|
+
|
171
|
+
should "with true default" do
|
172
|
+
Key.new(:active, Boolean, :default => true).get(nil).should be_true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end # KeyTest
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Address; end
|
4
|
+
|
5
|
+
class MongoMapperTest < Test::Unit::TestCase
|
6
|
+
should "be able to write and read connection" do
|
7
|
+
conn = Mongo::Connection.new
|
8
|
+
MongoMapper.connection = conn
|
9
|
+
MongoMapper.connection.should == conn
|
10
|
+
end
|
11
|
+
|
12
|
+
should "default connection to new mongo ruby driver" do
|
13
|
+
MongoMapper.connection = nil
|
14
|
+
MongoMapper.connection.should be_instance_of(Mongo::Connection)
|
15
|
+
end
|
16
|
+
|
17
|
+
should "be able to write and read default database" do
|
18
|
+
MongoMapper.database = DefaultDatabase
|
19
|
+
MongoMapper.database.should be_instance_of(Mongo::DB)
|
20
|
+
MongoMapper.database.name.should == DefaultDatabase
|
21
|
+
end
|
22
|
+
|
23
|
+
should "have document not found error" do
|
24
|
+
lambda {
|
25
|
+
MongoMapper::DocumentNotFound
|
26
|
+
}.should_not raise_error
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Comment
|
4
|
+
include MongoMapper::Document
|
5
|
+
|
6
|
+
key :name, String
|
7
|
+
key :body, String
|
8
|
+
|
9
|
+
attr_accessor :callers
|
10
|
+
before_validation :record_callers
|
11
|
+
|
12
|
+
def after_validation
|
13
|
+
record_callers
|
14
|
+
end
|
15
|
+
|
16
|
+
def record_callers
|
17
|
+
callers << self.class if callers
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Article
|
22
|
+
include MongoMapper::Document
|
23
|
+
|
24
|
+
key :title, String
|
25
|
+
key :body, String
|
26
|
+
end
|
27
|
+
|
28
|
+
class CommentObserver < MongoMapper::Observer
|
29
|
+
attr_accessor :callers
|
30
|
+
|
31
|
+
def after_validation(model)
|
32
|
+
callers << self.class if callers
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class AuditObserver < MongoMapper::Observer
|
37
|
+
observe Article, Comment
|
38
|
+
attr_reader :document
|
39
|
+
|
40
|
+
def after_validation(document)
|
41
|
+
@document = document
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class GlobalObserver < MongoMapper::Observer
|
46
|
+
observe Article, Comment
|
47
|
+
attr_reader :document
|
48
|
+
|
49
|
+
def before_save(document)
|
50
|
+
@document = document
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class NonAutomaticObserver < MongoMapper::Observer
|
55
|
+
observe Comment
|
56
|
+
attr_reader :comment
|
57
|
+
|
58
|
+
def after_validation(comment)
|
59
|
+
@comment = comment
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class ObserverTest < Test::Unit::TestCase
|
64
|
+
should "fire model callbacks before observer" do
|
65
|
+
callers = []
|
66
|
+
comment = Comment.new
|
67
|
+
comment.callers = callers
|
68
|
+
|
69
|
+
CommentObserver.instance.callers = callers
|
70
|
+
|
71
|
+
comment.valid?
|
72
|
+
callers.should == [Comment, Comment, CommentObserver]
|
73
|
+
end
|
74
|
+
|
75
|
+
should "automatically observe model based on name when possible" do
|
76
|
+
CommentObserver.observed_class.should == Comment
|
77
|
+
end
|
78
|
+
|
79
|
+
should "be able to observe other models using observe" do
|
80
|
+
obs = NonAutomaticObserver.instance
|
81
|
+
comment = Comment.new(:name => 'John Nunemaker', :body => 'is awesome')
|
82
|
+
comment.valid?
|
83
|
+
obs.comment.name.should == 'John Nunemaker'
|
84
|
+
obs.comment.body.should == 'is awesome'
|
85
|
+
end
|
86
|
+
|
87
|
+
should "be able to observe multiple models" do
|
88
|
+
obs = AuditObserver.instance
|
89
|
+
comment = Comment.new(:name => 'Steve Smith', :body => 'is awesome')
|
90
|
+
comment.valid?
|
91
|
+
|
92
|
+
obs.document.name.should == 'Steve Smith'
|
93
|
+
obs.document.body.should == 'is awesome'
|
94
|
+
|
95
|
+
article = Article.new(:title => 'Ordered List Is Awesome', :body => 'Learn to accept it!')
|
96
|
+
article.valid?
|
97
|
+
|
98
|
+
obs.document.title.should == 'Ordered List Is Awesome'
|
99
|
+
obs.document.body.should == 'Learn to accept it!'
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PaginationTest < Test::Unit::TestCase
|
4
|
+
context "Pagination proxy" do
|
5
|
+
include MongoMapper::Pagination
|
6
|
+
|
7
|
+
should "should have accessors for subject" do
|
8
|
+
subject = [1,2,3,4,5]
|
9
|
+
collection = PaginationProxy.new(25, 2)
|
10
|
+
collection.subject = subject
|
11
|
+
collection.subject.should == subject
|
12
|
+
end
|
13
|
+
|
14
|
+
should "delegate any methods not defined to the subject" do
|
15
|
+
subject = [1,2,3,4,5]
|
16
|
+
collection = PaginationProxy.new(25, 2, 10)
|
17
|
+
collection.subject = subject
|
18
|
+
collection.size.should == 5
|
19
|
+
collection.each_with_index do |value, i|
|
20
|
+
value.should == subject[i]
|
21
|
+
end
|
22
|
+
collection[0..2].should == [1,2,3]
|
23
|
+
collection.class.should == Array
|
24
|
+
end
|
25
|
+
|
26
|
+
should "return correct value for total_entries" do
|
27
|
+
PaginationProxy.new(25, 2, 10).total_entries.should == 25
|
28
|
+
PaginationProxy.new('25', 2, 10).total_entries.should == 25
|
29
|
+
end
|
30
|
+
|
31
|
+
should "return correct value for per_page" do
|
32
|
+
PaginationProxy.new(25, 2, 10).per_page.should == 10
|
33
|
+
PaginationProxy.new(25, 2, '10').per_page.should == 10
|
34
|
+
end
|
35
|
+
|
36
|
+
should "alias limit to per_page" do
|
37
|
+
PaginationProxy.new(100, 1, 300).limit.should == 300
|
38
|
+
end
|
39
|
+
|
40
|
+
should "set per_page to 25 if nil or blank" do
|
41
|
+
PaginationProxy.new(25, 2).per_page.should == 25
|
42
|
+
PaginationProxy.new(25, 2, '').per_page.should == 25
|
43
|
+
end
|
44
|
+
|
45
|
+
should "return correct value for current_page" do
|
46
|
+
PaginationProxy.new(25, 2, 10).current_page.should == 2
|
47
|
+
PaginationProxy.new(25, '2', 10).current_page.should == 2
|
48
|
+
end
|
49
|
+
|
50
|
+
should "not allow value less than 1 for current page" do
|
51
|
+
PaginationProxy.new(25, -1).current_page.should == 1
|
52
|
+
end
|
53
|
+
|
54
|
+
should "automatically calculate total_pages from total_entries and per page" do
|
55
|
+
PaginationProxy.new(25, 2, 10).total_pages.should == 3
|
56
|
+
end
|
57
|
+
|
58
|
+
should "know how many records to skip" do
|
59
|
+
PaginationProxy.new(25, 2, 10).skip.should == 10
|
60
|
+
end
|
61
|
+
|
62
|
+
context "previous_page" do
|
63
|
+
should "be nil if current page 1" do
|
64
|
+
PaginationProxy.new(25, 1, 10).previous_page.should be_nil
|
65
|
+
end
|
66
|
+
|
67
|
+
should "be one less than current page if current is > 1" do
|
68
|
+
PaginationProxy.new(25, 2, 10).previous_page.should == 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "next_page" do
|
73
|
+
should "be nil if current page is last page" do
|
74
|
+
PaginationProxy.new(25, 3, 10).next_page.should be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
should "work for any page that is not last" do
|
78
|
+
PaginationProxy.new(25, 1, 10).next_page.should == 2
|
79
|
+
PaginationProxy.new(25, 2, 10).next_page.should == 3
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "previous_page" do
|
84
|
+
should "be nil if current page is first page" do
|
85
|
+
PaginationProxy.new(25, 1, 10).previous_page.should be_nil
|
86
|
+
end
|
87
|
+
|
88
|
+
should "work for any page other than first" do
|
89
|
+
PaginationProxy.new(25, 2, 10).previous_page.should == 1
|
90
|
+
PaginationProxy.new(25, 3, 10).previous_page.should == 2
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "out_of_bounds?" do
|
95
|
+
should "be true if current_page is greater than total_pages" do
|
96
|
+
PaginationProxy.new(25, 10, 4).out_of_bounds?.should be_true
|
97
|
+
end
|
98
|
+
|
99
|
+
should "be false if current_page is less than total_pages" do
|
100
|
+
PaginationProxy.new(25, 10, 1).out_of_bounds?.should be_false
|
101
|
+
PaginationProxy.new(25, 2, 10).out_of_bounds?.should be_false
|
102
|
+
end
|
103
|
+
|
104
|
+
should "be false if current_page is equal to total_pages" do
|
105
|
+
PaginationProxy.new(25, 3, 10).out_of_bounds?.should be_false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end # end of pagination proxy
|
109
|
+
end # end of test case
|
@@ -0,0 +1,39 @@
|
|
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 FirstItem < Item
|
10
|
+
key :first_only, String
|
11
|
+
many :second_items
|
12
|
+
end
|
13
|
+
|
14
|
+
class SecondItem < Item
|
15
|
+
key :second_only, String
|
16
|
+
end
|
17
|
+
|
18
|
+
context "EmbeddedDocument" do
|
19
|
+
should "raise error for to_param as embedded do not have id's" do
|
20
|
+
lambda { Item.new.to_param }.should raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
should "alias many to has_many" do
|
24
|
+
FirstItem.should respond_to(:has_many)
|
25
|
+
FirstItem.method(:has_many).should == FirstItem.method(:many)
|
26
|
+
end
|
27
|
+
|
28
|
+
should "have column names" do
|
29
|
+
Item.column_names.sort.should == ['_id', 'for_all']
|
30
|
+
FirstItem.column_names.sort.should == ['_id', 'first_only', 'for_all']
|
31
|
+
SecondItem.column_names.sort.should == ['_id', 'for_all', 'second_only']
|
32
|
+
end
|
33
|
+
|
34
|
+
should "alias new to new_record?" do
|
35
|
+
instance = Item.new
|
36
|
+
instance.new_record?.should == instance.new?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SerializationTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@document = Class.new do
|
6
|
+
include MongoMapper::EmbeddedDocument
|
7
|
+
key :name, String
|
8
|
+
key :age, Integer
|
9
|
+
key :awesome, Boolean
|
10
|
+
key :preferences, Hash
|
11
|
+
key :created_at, Time
|
12
|
+
end
|
13
|
+
|
14
|
+
@instance = @document.new(
|
15
|
+
:name => 'John Doe',
|
16
|
+
:age => 25,
|
17
|
+
:awesome => true,
|
18
|
+
:preferences => {:language => 'Ruby'},
|
19
|
+
:created_at => Time.now.change(:usec => 0)
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
[:json].each do |format|
|
24
|
+
context format do
|
25
|
+
should "be reversable" do
|
26
|
+
serialized = @instance.send("to_#{format}")
|
27
|
+
unserialized = @document.new.send("from_#{format}", serialized)
|
28
|
+
|
29
|
+
assert_equal @instance, unserialized
|
30
|
+
end
|
31
|
+
|
32
|
+
should "allow attribute only filtering" do
|
33
|
+
serialized = @instance.send("to_#{format}", :only => [ :age, :name ])
|
34
|
+
unserialized = @document.new.send("from_#{format}", serialized)
|
35
|
+
|
36
|
+
assert_equal @instance.name, unserialized.name
|
37
|
+
assert_equal @instance.age, unserialized.age
|
38
|
+
assert ! unserialized.awesome
|
39
|
+
assert_nil unserialized.created_at
|
40
|
+
end
|
41
|
+
|
42
|
+
should "allow attribute except filtering" do
|
43
|
+
serialized = @instance.send("to_#{format}", :except => [ :age, :name ])
|
44
|
+
unserialized = @document.new.send("from_#{format}", serialized)
|
45
|
+
|
46
|
+
assert_nil unserialized.name
|
47
|
+
assert_nil unserialized.age
|
48
|
+
assert_equal @instance.awesome, unserialized.awesome
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|