mongo_mapper 0.6.10 → 0.7.0
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/README.rdoc +5 -14
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/mongo_mapper.rb +48 -56
- data/lib/mongo_mapper/document.rb +136 -164
- data/lib/mongo_mapper/embedded_document.rb +29 -354
- data/lib/mongo_mapper/plugins.rb +31 -0
- data/lib/mongo_mapper/plugins/associations.rb +105 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
- data/lib/mongo_mapper/plugins/clone.rb +13 -0
- data/lib/mongo_mapper/plugins/descendants.rb +16 -0
- data/lib/mongo_mapper/plugins/dirty.rb +119 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
- data/lib/mongo_mapper/plugins/inspect.rb +14 -0
- data/lib/mongo_mapper/plugins/keys.rb +324 -0
- data/lib/mongo_mapper/plugins/logger.rb +17 -0
- data/lib/mongo_mapper/plugins/pagination.rb +24 -0
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/rails.rb +45 -0
- data/lib/mongo_mapper/plugins/serialization.rb +105 -0
- data/lib/mongo_mapper/plugins/validations.rb +46 -0
- data/lib/mongo_mapper/query.rb +130 -0
- data/lib/mongo_mapper/support.rb +40 -17
- data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
- data/lib/mongo_mapper/support/find.rb +77 -0
- data/mongo_mapper.gemspec +55 -38
- data/performance/read_write.rb +52 -0
- data/specs.watchr +23 -2
- data/test/functional/associations/test_belongs_to_proxy.rb +12 -10
- data/test/functional/associations/test_many_documents_as_proxy.rb +4 -21
- data/test/functional/associations/test_many_documents_proxy.rb +2 -8
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +59 -39
- data/test/functional/associations/test_many_embedded_proxy.rb +145 -81
- data/test/functional/associations/test_many_polymorphic_proxy.rb +2 -40
- data/test/functional/associations/test_one_proxy.rb +25 -10
- data/test/functional/test_binary.rb +2 -8
- data/test/functional/test_callbacks.rb +1 -5
- data/test/functional/test_dirty.rb +27 -23
- data/test/functional/test_document.rb +224 -165
- data/test/functional/test_embedded_document.rb +72 -82
- data/test/functional/test_identity_map.rb +508 -0
- data/test/functional/test_modifiers.rb +15 -5
- data/test/functional/test_pagination.rb +1 -3
- data/test/functional/test_protected.rb +155 -0
- data/test/functional/test_string_id_compatibility.rb +7 -12
- data/test/functional/test_validations.rb +26 -58
- data/test/models.rb +0 -39
- data/test/test_helper.rb +37 -3
- data/test/unit/associations/test_base.rb +5 -5
- data/test/unit/associations/test_proxy.rb +8 -6
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +71 -76
- data/test/unit/test_dynamic_finder.rb +27 -29
- data/test/unit/test_embedded_document.rb +555 -601
- data/test/unit/{test_key.rb → test_keys.rb} +2 -5
- data/test/unit/test_mongo_mapper.rb +69 -9
- data/test/unit/test_pagination.rb +40 -32
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/{test_finder_options.rb → test_query.rb} +74 -65
- data/test/unit/test_rails.rb +123 -0
- data/test/unit/{test_serializations.rb → test_serialization.rb} +1 -2
- data/test/unit/test_support.rb +23 -7
- data/test/unit/test_time_zones.rb +3 -4
- data/test/unit/test_validations.rb +58 -17
- metadata +53 -36
- data/lib/mongo_mapper/associations.rb +0 -78
- data/lib/mongo_mapper/associations/base.rb +0 -119
- data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
- data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
- data/lib/mongo_mapper/associations/collection.rb +0 -19
- data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
- data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
- data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
- data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
- data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
- data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
- data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
- data/lib/mongo_mapper/associations/proxy.rb +0 -116
- data/lib/mongo_mapper/callbacks.rb +0 -61
- data/lib/mongo_mapper/dirty.rb +0 -117
- data/lib/mongo_mapper/dynamic_finder.rb +0 -74
- data/lib/mongo_mapper/finder_options.rb +0 -145
- data/lib/mongo_mapper/key.rb +0 -36
- data/lib/mongo_mapper/mongo_mapper.rb +0 -125
- data/lib/mongo_mapper/pagination.rb +0 -66
- data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
- data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
- data/lib/mongo_mapper/serialization.rb +0 -54
- data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
- data/lib/mongo_mapper/validations.rb +0 -39
- data/test/functional/test_rails_compatibility.rb +0 -25
@@ -20,7 +20,7 @@ class FooType < Struct.new(:bar)
|
|
20
20
|
end
|
21
21
|
|
22
22
|
class KeyTest < Test::Unit::TestCase
|
23
|
-
include MongoMapper
|
23
|
+
include MongoMapper::Plugins::Keys
|
24
24
|
|
25
25
|
context "Initializing a new key" do
|
26
26
|
should "allow setting the name" do
|
@@ -82,10 +82,7 @@ class KeyTest < Test::Unit::TestCase
|
|
82
82
|
end
|
83
83
|
|
84
84
|
should "know if it is a embedded_document" do
|
85
|
-
|
86
|
-
include MongoMapper::EmbeddedDocument
|
87
|
-
end
|
88
|
-
Key.new(:name, klass).embeddable?.should be_true
|
85
|
+
Key.new(:name, EDoc()).embeddable?.should be_true
|
89
86
|
end
|
90
87
|
|
91
88
|
should "know if it is not a embedded_document" do
|
@@ -8,58 +8,118 @@ class MongoMapperTest < Test::Unit::TestCase
|
|
8
8
|
MongoMapper.connection = conn
|
9
9
|
MongoMapper.connection.should == conn
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
should "default connection to new mongo ruby driver" do
|
13
13
|
MongoMapper.connection = nil
|
14
14
|
MongoMapper.connection.should be_instance_of(Mongo::Connection)
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
should "be able to write and read default database" do
|
18
18
|
MongoMapper.database = 'test'
|
19
19
|
MongoMapper.database.should be_instance_of(Mongo::DB)
|
20
20
|
MongoMapper.database.name.should == 'test'
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
should "have document not found error" do
|
24
24
|
lambda {
|
25
25
|
MongoMapper::DocumentNotFound
|
26
26
|
}.should_not raise_error
|
27
27
|
end
|
28
|
+
|
29
|
+
should "be able to read/write config" do
|
30
|
+
config = {
|
31
|
+
'development' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test'},
|
32
|
+
'production' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test-prod'}
|
33
|
+
}
|
34
|
+
|
35
|
+
MongoMapper.config = config
|
36
|
+
MongoMapper.config.should == config
|
37
|
+
end
|
38
|
+
|
39
|
+
context "connecting to environment from config" do
|
40
|
+
should "work without authentication" do
|
41
|
+
MongoMapper.config = {
|
42
|
+
'development' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test'}
|
43
|
+
}
|
44
|
+
|
45
|
+
Mongo::Connection.expects(:new).with('127.0.0.1', 27017, {})
|
46
|
+
MongoMapper.expects(:database=).with('test')
|
47
|
+
Mongo::DB.any_instance.expects(:authenticate).never
|
48
|
+
MongoMapper.connect('development')
|
49
|
+
end
|
50
|
+
|
51
|
+
should "work with options" do
|
52
|
+
MongoMapper.config = {
|
53
|
+
'development' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test'}
|
54
|
+
}
|
55
|
+
|
56
|
+
connection, logger = mock('connection'), mock('logger')
|
57
|
+
Mongo::Connection.expects(:new).with('127.0.0.1', 27017, :logger => logger)
|
58
|
+
MongoMapper.connect('development', :logger => logger)
|
59
|
+
end
|
60
|
+
|
61
|
+
should "work with authentication" do
|
62
|
+
MongoMapper.config = {
|
63
|
+
'development' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test', 'username' => 'john', 'password' => 'secret'}
|
64
|
+
}
|
65
|
+
|
66
|
+
Mongo::DB.any_instance.expects(:authenticate).with('john', 'secret')
|
67
|
+
MongoMapper.connect('development')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "setup" do
|
72
|
+
should "work as shortcut for setting config, environment and options" do
|
73
|
+
config, logger = mock('config'), mock('logger')
|
74
|
+
MongoMapper.expects(:config=).with(config)
|
75
|
+
MongoMapper.expects(:connect).with('development', :logger => logger)
|
76
|
+
MongoMapper.expects(:handle_passenger_forking).never
|
77
|
+
MongoMapper.setup(config, 'development', :logger => logger)
|
78
|
+
end
|
79
|
+
|
80
|
+
should "handle passenger if option present" do
|
81
|
+
config, logger = mock('config'), mock('logger')
|
82
|
+
MongoMapper.expects(:config=).with(config)
|
83
|
+
MongoMapper.expects(:connect).with('development', :logger => logger)
|
84
|
+
MongoMapper.expects(:handle_passenger_forking)
|
85
|
+
MongoMapper.setup(config, 'development', :logger => logger, :passenger => true)
|
86
|
+
end
|
87
|
+
end
|
28
88
|
|
89
|
+
|
29
90
|
context "use_time_zone?" do
|
30
91
|
should "be true if Time.zone set" do
|
31
92
|
Time.zone = 'Hawaii'
|
32
93
|
MongoMapper.use_time_zone?.should be_true
|
33
94
|
Time.zone = nil
|
34
95
|
end
|
35
|
-
|
96
|
+
|
36
97
|
should "be false if Time.zone not set" do
|
37
98
|
MongoMapper.use_time_zone?.should be_false
|
38
99
|
end
|
39
100
|
end
|
40
|
-
|
101
|
+
|
41
102
|
context "time_class" do
|
42
103
|
should "be Time.zone if using time zones" do
|
43
104
|
Time.zone = 'Hawaii'
|
44
105
|
MongoMapper.time_class.should == Time.zone
|
45
106
|
Time.zone = nil
|
46
107
|
end
|
47
|
-
|
108
|
+
|
48
109
|
should "be Time if not using time zones" do
|
49
110
|
MongoMapper.time_class.should == Time
|
50
111
|
end
|
51
112
|
end
|
52
|
-
|
113
|
+
|
53
114
|
context "normalize_object_id" do
|
54
115
|
should "turn string into object id" do
|
55
116
|
id = Mongo::ObjectID.new
|
56
117
|
MongoMapper.normalize_object_id(id.to_s).should == id
|
57
118
|
end
|
58
|
-
|
119
|
+
|
59
120
|
should "leave object id alone" do
|
60
121
|
id = Mongo::ObjectID.new
|
61
122
|
MongoMapper.normalize_object_id(id).should == id
|
62
123
|
end
|
63
124
|
end
|
64
|
-
|
65
125
|
end
|
@@ -1,19 +1,27 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class PaginationTest < Test::Unit::TestCase
|
3
|
+
class PaginationTest < Test::Unit::TestCase
|
4
|
+
should "default per_page to 25" do
|
5
|
+
Doc().per_page.should == 25
|
6
|
+
end
|
7
|
+
|
8
|
+
should "allow overriding per_page" do
|
9
|
+
Doc() { def self.per_page; 1 end }.per_page.should == 1
|
10
|
+
end
|
11
|
+
|
4
12
|
context "Pagination proxy" do
|
5
|
-
include MongoMapper::Pagination
|
13
|
+
include MongoMapper::Plugins::Pagination
|
6
14
|
|
7
15
|
should "should have accessors for subject" do
|
8
16
|
subject = [1,2,3,4,5]
|
9
|
-
collection =
|
17
|
+
collection = Proxy.new(25, 2)
|
10
18
|
collection.subject = subject
|
11
19
|
collection.subject.should == subject
|
12
20
|
end
|
13
21
|
|
14
22
|
should "delegate any methods not defined to the subject" do
|
15
23
|
subject = [1,2,3,4,5]
|
16
|
-
collection =
|
24
|
+
collection = Proxy.new(25, 2, 10)
|
17
25
|
collection.subject = subject
|
18
26
|
collection.size.should == 5
|
19
27
|
collection.each_with_index do |value, i|
|
@@ -24,96 +32,96 @@ class PaginationTest < Test::Unit::TestCase
|
|
24
32
|
end
|
25
33
|
|
26
34
|
should "return correct value for total_entries" do
|
27
|
-
|
28
|
-
|
35
|
+
Proxy.new(25, 2, 10).total_entries.should == 25
|
36
|
+
Proxy.new('25', 2, 10).total_entries.should == 25
|
29
37
|
end
|
30
38
|
|
31
39
|
should "return correct value for per_page" do
|
32
|
-
|
33
|
-
|
40
|
+
Proxy.new(25, 2, 10).per_page.should == 10
|
41
|
+
Proxy.new(25, 2, '10').per_page.should == 10
|
34
42
|
end
|
35
43
|
|
36
44
|
should "alias limit to per_page" do
|
37
|
-
|
45
|
+
Proxy.new(100, 1, 300).limit.should == 300
|
38
46
|
end
|
39
47
|
|
40
48
|
should "set per_page to 25 if nil or blank" do
|
41
|
-
|
42
|
-
|
49
|
+
Proxy.new(25, 2).per_page.should == 25
|
50
|
+
Proxy.new(25, 2, '').per_page.should == 25
|
43
51
|
end
|
44
52
|
|
45
53
|
should "return correct value for current_page" do
|
46
|
-
|
47
|
-
|
54
|
+
Proxy.new(25, 2, 10).current_page.should == 2
|
55
|
+
Proxy.new(25, '2', 10).current_page.should == 2
|
48
56
|
end
|
49
57
|
|
50
58
|
should "not allow value less than 1 for current page" do
|
51
|
-
|
59
|
+
Proxy.new(25, -1).current_page.should == 1
|
52
60
|
end
|
53
61
|
|
54
62
|
should "automatically calculate total_pages from total_entries and per page" do
|
55
|
-
|
63
|
+
Proxy.new(25, 2, 10).total_pages.should == 3
|
56
64
|
end
|
57
65
|
|
58
66
|
should "know how many records to skip" do
|
59
|
-
|
67
|
+
Proxy.new(25, 2, 10).skip.should == 10
|
60
68
|
end
|
61
69
|
|
62
70
|
should "alias offset to skip" do
|
63
|
-
|
71
|
+
Proxy.new(25, 2, 10).offset.should == 10
|
64
72
|
end
|
65
73
|
|
66
74
|
should "return true for === Array" do
|
67
|
-
collection =
|
75
|
+
collection = Proxy.new(25, 2, 10)
|
68
76
|
collection.subject = [1, 2]
|
69
77
|
collection.should === Array
|
70
78
|
end
|
71
79
|
|
72
80
|
context "previous_page" do
|
73
81
|
should "be nil if current page 1" do
|
74
|
-
|
82
|
+
Proxy.new(25, 1, 10).previous_page.should be_nil
|
75
83
|
end
|
76
84
|
|
77
85
|
should "be one less than current page if current is > 1" do
|
78
|
-
|
86
|
+
Proxy.new(25, 2, 10).previous_page.should == 1
|
79
87
|
end
|
80
88
|
end
|
81
89
|
|
82
90
|
context "next_page" do
|
83
91
|
should "be nil if current page is last page" do
|
84
|
-
|
92
|
+
Proxy.new(25, 3, 10).next_page.should be_nil
|
85
93
|
end
|
86
94
|
|
87
95
|
should "work for any page that is not last" do
|
88
|
-
|
89
|
-
|
96
|
+
Proxy.new(25, 1, 10).next_page.should == 2
|
97
|
+
Proxy.new(25, 2, 10).next_page.should == 3
|
90
98
|
end
|
91
99
|
end
|
92
100
|
|
93
101
|
context "previous_page" do
|
94
102
|
should "be nil if current page is first page" do
|
95
|
-
|
103
|
+
Proxy.new(25, 1, 10).previous_page.should be_nil
|
96
104
|
end
|
97
105
|
|
98
106
|
should "work for any page other than first" do
|
99
|
-
|
100
|
-
|
107
|
+
Proxy.new(25, 2, 10).previous_page.should == 1
|
108
|
+
Proxy.new(25, 3, 10).previous_page.should == 2
|
101
109
|
end
|
102
110
|
end
|
103
111
|
|
104
112
|
context "out_of_bounds?" do
|
105
113
|
should "be true if current_page is greater than total_pages" do
|
106
|
-
|
114
|
+
Proxy.new(25, 10, 4).out_of_bounds?.should be_true
|
107
115
|
end
|
108
116
|
|
109
117
|
should "be false if current_page is less than total_pages" do
|
110
|
-
|
111
|
-
|
118
|
+
Proxy.new(25, 10, 1).out_of_bounds?.should be_false
|
119
|
+
Proxy.new(25, 2, 10).out_of_bounds?.should be_false
|
112
120
|
end
|
113
121
|
|
114
122
|
should "be false if current_page is equal to total_pages" do
|
115
|
-
|
123
|
+
Proxy.new(25, 3, 10).out_of_bounds?.should be_false
|
116
124
|
end
|
117
125
|
end
|
118
|
-
end
|
119
|
-
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MyPlugin
|
4
|
+
def self.configure(model)
|
5
|
+
model.class_eval { attr_accessor :from_configure }
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def class_foo
|
10
|
+
'class_foo'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
def instance_foo
|
16
|
+
'instance_foo'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class PluginsTest < Test::Unit::TestCase
|
22
|
+
context "plugin" do
|
23
|
+
setup do
|
24
|
+
@document = Class.new do
|
25
|
+
extend MongoMapper::Plugins
|
26
|
+
plugin MyPlugin
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
should "include instance methods" do
|
31
|
+
@document.new.instance_foo.should == 'instance_foo'
|
32
|
+
end
|
33
|
+
|
34
|
+
should "extend class methods" do
|
35
|
+
@document.class_foo.should == 'class_foo'
|
36
|
+
end
|
37
|
+
|
38
|
+
should "pass model to configure" do
|
39
|
+
@document.new.should respond_to(:from_configure)
|
40
|
+
end
|
41
|
+
|
42
|
+
should "default plugins to empty array" do
|
43
|
+
Class.new { extend MongoMapper::Plugins }.plugins.should == []
|
44
|
+
end
|
45
|
+
|
46
|
+
should "add plugin to plugins" do
|
47
|
+
@document.plugins.should include(MyPlugin)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,29 +1,29 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'models'
|
3
3
|
|
4
|
-
class
|
4
|
+
class QueryTest < Test::Unit::TestCase
|
5
5
|
include MongoMapper
|
6
6
|
|
7
7
|
should "raise error if provided something other than a hash" do
|
8
|
-
lambda {
|
9
|
-
lambda {
|
8
|
+
lambda { Query.new(Room) }.should raise_error(ArgumentError)
|
9
|
+
lambda { Query.new(Room, 1) }.should raise_error(ArgumentError)
|
10
10
|
end
|
11
11
|
|
12
12
|
should "symbolize the keys of the hash provided" do
|
13
|
-
|
13
|
+
Query.new(Room, 'offset' => 1).options.keys.map do |key|
|
14
14
|
key.should be_instance_of(Symbol)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
context "Converting conditions to criteria" do
|
19
19
|
should "not add _type to query if model does not have superclass that is single collection inherited" do
|
20
|
-
|
20
|
+
Query.new(Message, :foo => 'bar').criteria.should == {
|
21
21
|
:foo => 'bar'
|
22
22
|
}
|
23
23
|
end
|
24
24
|
|
25
25
|
should "not add _type to nested conditions" do
|
26
|
-
|
26
|
+
Query.new(Enter, :foo => 'bar', :age => {'$gt' => 21}).criteria.should == {
|
27
27
|
:foo => 'bar',
|
28
28
|
:age => {'$gt' => 21},
|
29
29
|
:_type => 'Enter'
|
@@ -31,26 +31,32 @@ class FinderOptionsTest < Test::Unit::TestCase
|
|
31
31
|
end
|
32
32
|
|
33
33
|
should "automatically add _type to query if model is single collection inherited" do
|
34
|
-
|
34
|
+
Query.new(Enter, :foo => 'bar').criteria.should == {
|
35
35
|
:foo => 'bar',
|
36
36
|
:_type => 'Enter'
|
37
37
|
}
|
38
38
|
end
|
39
39
|
|
40
|
-
%w{gt lt gte lte ne in nin mod size where exists}.each do |operator|
|
40
|
+
%w{gt lt gte lte ne in nin mod all size where exists}.each do |operator|
|
41
41
|
should "convert #{operator} conditions" do
|
42
|
-
|
42
|
+
Query.new(Room, :age.send(operator) => 21).criteria.should == {
|
43
43
|
:age => {"$#{operator}" => 21}
|
44
44
|
}
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
should "normalize value when using symbol operators" do
|
49
|
+
time = Time.now.in_time_zone('Indiana (East)')
|
50
|
+
criteria = Query.new(Room, :created_at.gt => time).criteria
|
51
|
+
criteria[:created_at]['$gt'].should be_utc
|
52
|
+
end
|
53
|
+
|
48
54
|
should "work with simple criteria" do
|
49
|
-
|
55
|
+
Query.new(Room, :foo => 'bar').criteria.should == {
|
50
56
|
:foo => 'bar'
|
51
57
|
}
|
52
58
|
|
53
|
-
|
59
|
+
Query.new(Room, :foo => 'bar', :baz => 'wick').criteria.should == {
|
54
60
|
:foo => 'bar',
|
55
61
|
:baz => 'wick'
|
56
62
|
}
|
@@ -58,71 +64,71 @@ class FinderOptionsTest < Test::Unit::TestCase
|
|
58
64
|
|
59
65
|
should "convert id to _id" do
|
60
66
|
id = Mongo::ObjectID.new
|
61
|
-
|
67
|
+
Query.new(Room, :id => id).criteria.should == {:_id => id}
|
62
68
|
end
|
63
69
|
|
64
70
|
should "convert id with symbol operator to _id with modifier" do
|
65
71
|
id = Mongo::ObjectID.new
|
66
|
-
|
72
|
+
Query.new(Room, :id.ne => id).criteria.should == {
|
67
73
|
:_id => {'$ne' => id}
|
68
74
|
}
|
69
75
|
end
|
70
76
|
|
71
77
|
should "make sure that _id's are object ids" do
|
72
78
|
id = Mongo::ObjectID.new
|
73
|
-
|
79
|
+
Query.new(Room, :_id => id.to_s).criteria.should == {:_id => id}
|
74
80
|
end
|
75
81
|
|
76
82
|
should "work fine with _id's that are object ids" do
|
77
83
|
id = Mongo::ObjectID.new
|
78
|
-
|
84
|
+
Query.new(Room, :_id => id).criteria.should == {:_id => id}
|
79
85
|
end
|
80
86
|
|
81
87
|
should "make sure other object id typed keys get converted" do
|
82
88
|
id = Mongo::ObjectID.new
|
83
|
-
|
89
|
+
Query.new(Message, :room_id => id.to_s).criteria.should == {:room_id => id}
|
84
90
|
end
|
85
91
|
|
86
92
|
should "work fine with object ids for object id typed keys" do
|
87
93
|
id = Mongo::ObjectID.new
|
88
|
-
|
94
|
+
Query.new(Message, :room_id => id).criteria.should == {:room_id => id}
|
89
95
|
end
|
90
96
|
|
91
97
|
should "convert times to utc if they aren't already" do
|
92
98
|
time = Time.now.in_time_zone('Indiana (East)')
|
93
|
-
criteria =
|
99
|
+
criteria = Query.new(Room, :created_at => time).criteria
|
94
100
|
criteria[:created_at].utc?.should be_true
|
95
101
|
end
|
96
102
|
|
97
103
|
should "not funk with times already in utc" do
|
98
104
|
time = Time.now.utc
|
99
|
-
criteria =
|
105
|
+
criteria = Query.new(Room, :created_at => time).criteria
|
100
106
|
criteria[:created_at].utc?.should be_true
|
101
107
|
criteria[:created_at].should == time
|
102
108
|
end
|
103
109
|
|
104
110
|
should "use $in for arrays" do
|
105
|
-
|
111
|
+
Query.new(Room, :foo => [1,2,3]).criteria.should == {
|
106
112
|
:foo => {'$in' => [1,2,3]}
|
107
113
|
}
|
108
114
|
end
|
109
115
|
|
110
116
|
should "not use $in for arrays if already using array operator" do
|
111
|
-
|
117
|
+
Query.new(Room, :foo => {'$all' => [1,2,3]}).criteria.should == {
|
112
118
|
:foo => {'$all' => [1,2,3]}
|
113
119
|
}
|
114
120
|
|
115
|
-
|
121
|
+
Query.new(Room, :foo => {'$any' => [1,2,3]}).criteria.should == {
|
116
122
|
:foo => {'$any' => [1,2,3]}
|
117
123
|
}
|
118
124
|
end
|
119
125
|
|
120
126
|
should "work arbitrarily deep" do
|
121
|
-
|
127
|
+
Query.new(Room, :foo => {:bar => [1,2,3]}).criteria.should == {
|
122
128
|
:foo => {:bar => {'$in' => [1,2,3]}}
|
123
129
|
}
|
124
130
|
|
125
|
-
|
131
|
+
Query.new(Room, :foo => {:bar => {'$any' => [1,2,3]}}).criteria.should == {
|
126
132
|
:foo => {:bar => {'$any' => [1,2,3]}}
|
127
133
|
}
|
128
134
|
end
|
@@ -131,175 +137,179 @@ class FinderOptionsTest < Test::Unit::TestCase
|
|
131
137
|
context "ordering" do
|
132
138
|
should "single field with ascending direction" do
|
133
139
|
sort = [['foo', 1]]
|
134
|
-
|
135
|
-
|
140
|
+
Query.new(Room, :order => 'foo asc').options[:sort].should == sort
|
141
|
+
Query.new(Room, :order => 'foo ASC').options[:sort].should == sort
|
136
142
|
end
|
137
143
|
|
138
144
|
should "single field with descending direction" do
|
139
145
|
sort = [['foo', -1]]
|
140
|
-
|
141
|
-
|
146
|
+
Query.new(Room, :order => 'foo desc').options[:sort].should == sort
|
147
|
+
Query.new(Room, :order => 'foo DESC').options[:sort].should == sort
|
142
148
|
end
|
143
149
|
|
144
150
|
should "convert order operators to mongo sort" do
|
145
|
-
|
146
|
-
|
151
|
+
Query.new(Room, :order => :foo.asc).options[:sort].should == [['foo', 1]]
|
152
|
+
Query.new(Room, :order => :foo.desc).options[:sort].should == [['foo', -1]]
|
147
153
|
end
|
148
154
|
|
149
155
|
should "convert array of order operators to mongo sort" do
|
150
|
-
|
156
|
+
Query.new(Room, :order => [:foo.asc, :bar.desc]).options[:sort].should == [['foo', 1], ['bar', -1]]
|
151
157
|
end
|
152
158
|
|
153
159
|
should "convert field without direction to ascending" do
|
154
160
|
sort = [['foo', 1]]
|
155
|
-
|
161
|
+
Query.new(Room, :order => 'foo').options[:sort].should == sort
|
156
162
|
end
|
157
163
|
|
158
164
|
should "convert multiple fields with directions" do
|
159
165
|
sort = [['foo', -1], ['bar', 1], ['baz', -1]]
|
160
|
-
|
166
|
+
Query.new(Room, :order => 'foo desc, bar asc, baz desc').options[:sort].should == sort
|
161
167
|
end
|
162
168
|
|
163
169
|
should "convert multiple fields with some missing directions" do
|
164
170
|
sort = [['foo', -1], ['bar', 1], ['baz', 1]]
|
165
|
-
|
171
|
+
Query.new(Room, :order => 'foo desc, bar, baz').options[:sort].should == sort
|
166
172
|
end
|
167
173
|
|
168
174
|
should "just use sort if sort and order are present" do
|
169
175
|
sort = [['$natural', 1]]
|
170
|
-
|
176
|
+
Query.new(Room, :sort => sort, :order => 'foo asc').options[:sort].should == sort
|
171
177
|
end
|
172
178
|
|
173
179
|
should "convert natural in order to proper" do
|
174
180
|
sort = [['$natural', 1]]
|
175
|
-
|
181
|
+
Query.new(Room, :order => '$natural asc').options[:sort].should == sort
|
176
182
|
sort = [['$natural', -1]]
|
177
|
-
|
183
|
+
Query.new(Room, :order => '$natural desc').options[:sort].should == sort
|
178
184
|
end
|
179
185
|
|
180
186
|
should "work for natural order ascending" do
|
181
|
-
|
187
|
+
Query.new(Room, :sort => {'$natural' => 1}).options[:sort]['$natural'].should == 1
|
182
188
|
end
|
183
189
|
|
184
190
|
should "work for natural order descending" do
|
185
|
-
|
191
|
+
Query.new(Room, :sort => {'$natural' => -1}).options[:sort]['$natural'].should == -1
|
186
192
|
end
|
187
193
|
end
|
188
194
|
|
189
195
|
context "skip" do
|
190
196
|
should "default to 0" do
|
191
|
-
|
197
|
+
Query.new(Room, {}).options[:skip].should == 0
|
192
198
|
end
|
193
199
|
|
194
200
|
should "use skip provided" do
|
195
|
-
|
201
|
+
Query.new(Room, :skip => 2).options[:skip].should == 2
|
196
202
|
end
|
197
203
|
|
198
204
|
should "covert string to integer" do
|
199
|
-
|
205
|
+
Query.new(Room, :skip => '2').options[:skip].should == 2
|
200
206
|
end
|
201
207
|
|
202
208
|
should "convert offset to skip" do
|
203
|
-
|
209
|
+
Query.new(Room, :offset => 1).options[:skip].should == 1
|
204
210
|
end
|
205
211
|
end
|
206
212
|
|
207
213
|
context "limit" do
|
208
214
|
should "default to 0" do
|
209
|
-
|
215
|
+
Query.new(Room, {}).options[:limit].should == 0
|
210
216
|
end
|
211
217
|
|
212
218
|
should "use limit provided" do
|
213
|
-
|
219
|
+
Query.new(Room, :limit => 2).options[:limit].should == 2
|
214
220
|
end
|
215
221
|
|
216
222
|
should "covert string to integer" do
|
217
|
-
|
223
|
+
Query.new(Room, :limit => '2').options[:limit].should == 2
|
218
224
|
end
|
219
225
|
end
|
220
226
|
|
221
227
|
context "fields" do
|
222
228
|
should "default to nil" do
|
223
|
-
|
229
|
+
Query.new(Room, {}).options[:fields].should be(nil)
|
224
230
|
end
|
225
231
|
|
226
232
|
should "be converted to nil if empty string" do
|
227
|
-
|
233
|
+
Query.new(Room, :fields => '').options[:fields].should be(nil)
|
228
234
|
end
|
229
235
|
|
230
236
|
should "be converted to nil if []" do
|
231
|
-
|
237
|
+
Query.new(Room, :fields => []).options[:fields].should be(nil)
|
232
238
|
end
|
233
239
|
|
234
240
|
should "should work with array" do
|
235
|
-
|
241
|
+
Query.new(Room, {:fields => %w(a b)}).options[:fields].should == %w(a b)
|
236
242
|
end
|
237
243
|
|
238
244
|
should "convert comma separated list to array" do
|
239
|
-
|
245
|
+
Query.new(Room, {:fields => 'a, b'}).options[:fields].should == %w(a b)
|
240
246
|
end
|
241
247
|
|
242
248
|
should "also work as select" do
|
243
|
-
|
249
|
+
Query.new(Room, :select => %w(a b)).options[:fields].should == %w(a b)
|
250
|
+
end
|
251
|
+
|
252
|
+
should "also work with select as array of symbols" do
|
253
|
+
Query.new(Room, :select => [:a, :b]).options[:fields].should == [:a, :b]
|
244
254
|
end
|
245
255
|
end
|
246
256
|
|
247
257
|
context "Condition auto-detection" do
|
248
258
|
should "know :conditions are criteria" do
|
249
|
-
finder =
|
259
|
+
finder = Query.new(Room, :conditions => {:foo => 'bar'})
|
250
260
|
finder.criteria.should == {:foo => 'bar'}
|
251
261
|
finder.options.keys.should_not include(:conditions)
|
252
262
|
end
|
253
263
|
|
254
264
|
should "know fields is an option" do
|
255
|
-
finder =
|
265
|
+
finder = Query.new(Room, :fields => ['foo'])
|
256
266
|
finder.options[:fields].should == ['foo']
|
257
267
|
finder.criteria.keys.should_not include(:fields)
|
258
268
|
end
|
259
269
|
|
260
270
|
# select gets converted to fields so just checking keys
|
261
271
|
should "know select is an option" do
|
262
|
-
finder =
|
272
|
+
finder = Query.new(Room, :select => 'foo')
|
263
273
|
finder.options.keys.should include(:sort)
|
264
274
|
finder.criteria.keys.should_not include(:select)
|
265
275
|
finder.criteria.keys.should_not include(:fields)
|
266
276
|
end
|
267
277
|
|
268
278
|
should "know skip is an option" do
|
269
|
-
finder =
|
279
|
+
finder = Query.new(Room, :skip => 10)
|
270
280
|
finder.options[:skip].should == 10
|
271
281
|
finder.criteria.keys.should_not include(:skip)
|
272
282
|
end
|
273
283
|
|
274
284
|
# offset gets converted to skip so just checking keys
|
275
285
|
should "know offset is an option" do
|
276
|
-
finder =
|
286
|
+
finder = Query.new(Room, :offset => 10)
|
277
287
|
finder.options.keys.should include(:skip)
|
278
288
|
finder.criteria.keys.should_not include(:skip)
|
279
289
|
finder.criteria.keys.should_not include(:offset)
|
280
290
|
end
|
281
291
|
|
282
292
|
should "know limit is an option" do
|
283
|
-
finder =
|
293
|
+
finder = Query.new(Room, :limit => 10)
|
284
294
|
finder.options[:limit].should == 10
|
285
295
|
finder.criteria.keys.should_not include(:limit)
|
286
296
|
end
|
287
297
|
|
288
298
|
should "know sort is an option" do
|
289
|
-
finder =
|
299
|
+
finder = Query.new(Room, :sort => [['foo', 1]])
|
290
300
|
finder.options[:sort].should == [['foo', 1]]
|
291
301
|
finder.criteria.keys.should_not include(:sort)
|
292
302
|
end
|
293
303
|
|
294
304
|
# order gets converted to sort so just checking keys
|
295
305
|
should "know order is an option" do
|
296
|
-
finder =
|
306
|
+
finder = Query.new(Room, :order => 'foo')
|
297
307
|
finder.options.keys.should include(:sort)
|
298
308
|
finder.criteria.keys.should_not include(:sort)
|
299
309
|
end
|
300
310
|
|
301
311
|
should "work with full range of things" do
|
302
|
-
|
312
|
+
query_options = Query.new(Room, {
|
303
313
|
:foo => 'bar',
|
304
314
|
:baz => true,
|
305
315
|
:sort => [['foo', 1]],
|
@@ -308,12 +318,12 @@ class FinderOptionsTest < Test::Unit::TestCase
|
|
308
318
|
:skip => 10,
|
309
319
|
})
|
310
320
|
|
311
|
-
|
321
|
+
query_options.criteria.should == {
|
312
322
|
:foo => 'bar',
|
313
323
|
:baz => true,
|
314
324
|
}
|
315
325
|
|
316
|
-
|
326
|
+
query_options.options.should == {
|
317
327
|
:sort => [['foo', 1]],
|
318
328
|
:fields => ['foo', 'baz'],
|
319
329
|
:limit => 10,
|
@@ -321,5 +331,4 @@ class FinderOptionsTest < Test::Unit::TestCase
|
|
321
331
|
}
|
322
332
|
end
|
323
333
|
end
|
324
|
-
|
325
|
-
end # FinderOptionsTest
|
334
|
+
end
|