djsun-mongomapper 0.3.5.5 → 0.4.1.2
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 +38 -38
- data/Rakefile +87 -73
- data/VERSION +1 -1
- data/lib/mongomapper.rb +67 -71
- data/lib/mongomapper/associations.rb +86 -84
- data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +34 -34
- data/lib/mongomapper/associations/many_embedded_proxy.rb +67 -17
- data/lib/mongomapper/associations/proxy.rb +74 -73
- data/lib/mongomapper/document.rb +342 -348
- data/lib/mongomapper/embedded_document.rb +354 -274
- data/lib/mongomapper/finder_options.rb +84 -84
- data/lib/mongomapper/key.rb +32 -76
- data/lib/mongomapper/rails_compatibility/document.rb +14 -14
- data/lib/mongomapper/rails_compatibility/embedded_document.rb +26 -24
- data/lib/mongomapper/support.rb +156 -29
- data/lib/mongomapper/validations.rb +69 -47
- data/test/custom_matchers.rb +48 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +53 -56
- data/test/functional/associations/test_belongs_to_proxy.rb +48 -49
- data/test/functional/associations/test_many_documents_as_proxy.rb +208 -253
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +130 -130
- data/test/functional/associations/test_many_embedded_proxy.rb +168 -106
- data/test/functional/associations/test_many_polymorphic_proxy.rb +261 -262
- data/test/functional/test_binary.rb +21 -0
- data/test/functional/test_document.rb +946 -952
- data/test/functional/test_embedded_document.rb +98 -0
- data/test/functional/test_pagination.rb +87 -80
- data/test/functional/test_rails_compatibility.rb +29 -29
- data/test/functional/test_validations.rb +262 -172
- data/test/models.rb +169 -169
- data/test/test_helper.rb +28 -66
- data/test/unit/serializers/test_json_serializer.rb +193 -193
- data/test/unit/test_document.rb +161 -123
- data/test/unit/test_embedded_document.rb +643 -547
- data/test/unit/test_finder_options.rb +183 -183
- data/test/unit/test_key.rb +175 -247
- data/test/unit/test_rails_compatibility.rb +38 -33
- data/test/unit/test_serializations.rb +52 -52
- data/test/unit/test_support.rb +268 -0
- data/test/unit/test_time_zones.rb +40 -0
- data/test/unit/test_validations.rb +499 -258
- metadata +22 -12
- data/History +0 -76
- data/mongomapper.gemspec +0 -145
data/test/models.rb
CHANGED
@@ -1,169 +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
|
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
|
data/test/test_helper.rb
CHANGED
@@ -1,67 +1,29 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
require 'pp'
|
3
|
-
require 'rubygems'
|
4
|
-
require '
|
5
|
-
|
6
|
-
|
7
|
-
gem '
|
8
|
-
|
9
|
-
|
10
|
-
require '
|
11
|
-
require '
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
1
|
+
require 'pathname'
|
2
|
+
require 'pp'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'shoulda'
|
5
|
+
|
6
|
+
gem 'mocha', '0.9.4'
|
7
|
+
gem 'jnunemaker-matchy', '0.4.0'
|
8
|
+
|
9
|
+
require 'matchy'
|
10
|
+
require 'mocha'
|
11
|
+
require 'custom_matchers'
|
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
|
+
include CustomMatchers
|
19
|
+
|
20
|
+
def clear_all_collections
|
21
|
+
MongoMapper::Document.descendants.map { |d| d.collection.clear }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
DefaultDatabase = 'test' unless defined?(DefaultDatabase)
|
26
|
+
AlternateDatabase = 'test2' unless defined?(AlternateDatabase)
|
27
|
+
|
28
|
+
MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017)
|
67
29
|
MongoMapper.database = DefaultDatabase
|
@@ -1,193 +1,193 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class JsonSerializationTest < Test::Unit::TestCase
|
4
|
-
class Tag
|
5
|
-
include MongoMapper::EmbeddedDocument
|
6
|
-
key :name, String
|
7
|
-
end
|
8
|
-
|
9
|
-
class Contact
|
10
|
-
include MongoMapper::Document
|
11
|
-
key :name, String
|
12
|
-
key :age, Integer
|
13
|
-
key :created_at, Time
|
14
|
-
key :awesome, Boolean
|
15
|
-
key :preferences, Hash
|
16
|
-
key :hiding, String
|
17
|
-
|
18
|
-
many :tags, :class_name => 'JsonSerializationTest::Tag'
|
19
|
-
end
|
20
|
-
|
21
|
-
def setup
|
22
|
-
Contact.include_root_in_json = false
|
23
|
-
@contact = Contact.new(
|
24
|
-
:name => 'Konata Izumi',
|
25
|
-
:age => 16,
|
26
|
-
:created_at => Time.utc(2006, 8, 1),
|
27
|
-
:awesome => true,
|
28
|
-
:preferences => { :shows => 'anime' }
|
29
|
-
)
|
30
|
-
end
|
31
|
-
|
32
|
-
should "include demodulized root" do
|
33
|
-
Contact.include_root_in_json = true
|
34
|
-
assert_match %r{^\{"contact": \{}, @contact.to_json
|
35
|
-
end
|
36
|
-
|
37
|
-
should "encode all encodable attributes" do
|
38
|
-
json = @contact.to_json
|
39
|
-
|
40
|
-
assert_no_match %r{"_id"}, json
|
41
|
-
assert_match %r{"name":"Konata Izumi"}, json
|
42
|
-
assert_match %r{"age":16}, json
|
43
|
-
assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
|
44
|
-
assert_match %r{"awesome":true}, json
|
45
|
-
assert_match %r{"preferences":\{"shows":"anime"\}}, json
|
46
|
-
assert_match %r{"hiding":null}, json
|
47
|
-
end
|
48
|
-
|
49
|
-
should "allow attribute filtering with only" do
|
50
|
-
json = @contact.to_json(:only => [:name, :age])
|
51
|
-
|
52
|
-
assert_no_match %r{"_id"}, json
|
53
|
-
assert_match %r{"name":"Konata Izumi"}, json
|
54
|
-
assert_match %r{"age":16}, json
|
55
|
-
assert_no_match %r{"awesome"}, json
|
56
|
-
assert_no_match %r{"created_at"}, json
|
57
|
-
assert_no_match %r{"preferences"}, json
|
58
|
-
assert_no_match %r{"hiding"}, json
|
59
|
-
end
|
60
|
-
|
61
|
-
should "allow attribute filtering with except" do
|
62
|
-
json = @contact.to_json(:except => [:name, :age])
|
63
|
-
|
64
|
-
assert_no_match %r{"_id"}, json
|
65
|
-
assert_no_match %r{"name"}, json
|
66
|
-
assert_no_match %r{"age"}, json
|
67
|
-
assert_match %r{"awesome"}, json
|
68
|
-
assert_match %r{"created_at"}, json
|
69
|
-
assert_match %r{"preferences"}, json
|
70
|
-
assert_match %r{"hiding"}, json
|
71
|
-
end
|
72
|
-
|
73
|
-
context "_id key" do
|
74
|
-
should "not be included by default" do
|
75
|
-
json = @contact.to_json
|
76
|
-
assert_no_match %r{"_id":}, json
|
77
|
-
end
|
78
|
-
|
79
|
-
should "not be included even if :except is used" do
|
80
|
-
json = @contact.to_json(:except => :name)
|
81
|
-
assert_no_match %r{"_id":}, json
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context "id method" do
|
86
|
-
setup do
|
87
|
-
def @contact.label; "Has cheezburger"; end
|
88
|
-
def @contact.favorite_quote; "Constraints are liberating"; end
|
89
|
-
end
|
90
|
-
|
91
|
-
should "be included by default" do
|
92
|
-
json = @contact.to_json
|
93
|
-
assert_match %r{"id"}, json
|
94
|
-
end
|
95
|
-
|
96
|
-
should "be included when single method included" do
|
97
|
-
json = @contact.to_json(:methods => :label)
|
98
|
-
assert_match %r{"id"}, json
|
99
|
-
assert_match %r{"label":"Has cheezburger"}, json
|
100
|
-
assert_match %r{"name":"Konata Izumi"}, json
|
101
|
-
assert_no_match %r{"favorite_quote":"Constraints are liberating"}, json
|
102
|
-
end
|
103
|
-
|
104
|
-
should "be included when multiple methods included" do
|
105
|
-
json = @contact.to_json(:methods => [:label, :favorite_quote])
|
106
|
-
assert_match %r{"id"}, json
|
107
|
-
assert_match %r{"label":"Has cheezburger"}, json
|
108
|
-
assert_match %r{"favorite_quote":"Constraints are liberating"}, json
|
109
|
-
assert_match %r{"name":"Konata Izumi"}, json
|
110
|
-
end
|
111
|
-
|
112
|
-
should "not be included if :only is present" do
|
113
|
-
json = @contact.to_json(:only => :name)
|
114
|
-
assert_no_match %r{"id":}, json
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
context "including methods" do
|
119
|
-
setup do
|
120
|
-
def @contact.label; "Has cheezburger"; end
|
121
|
-
def @contact.favorite_quote; "Constraints are liberating"; end
|
122
|
-
end
|
123
|
-
|
124
|
-
should "include single method" do
|
125
|
-
json = @contact.to_json(:methods => :label)
|
126
|
-
assert_match %r{"label":"Has cheezburger"}, json
|
127
|
-
end
|
128
|
-
|
129
|
-
should "include multiple methods" do
|
130
|
-
json = @contact.to_json(:only => :name, :methods => [:label, :favorite_quote])
|
131
|
-
assert_match %r{"label":"Has cheezburger"}, json
|
132
|
-
assert_match %r{"favorite_quote":"Constraints are liberating"}, json
|
133
|
-
assert_match %r{"name":"Konata Izumi"}, json
|
134
|
-
assert_no_match %r{"age":16}, json
|
135
|
-
assert_no_match %r{"awesome"}, json
|
136
|
-
assert_no_match %r{"created_at"}, json
|
137
|
-
assert_no_match %r{"preferences"}, json
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
context "array of records" do
|
142
|
-
setup do
|
143
|
-
@contacts = [
|
144
|
-
Contact.new(:name => 'David', :age => 39),
|
145
|
-
Contact.new(:name => 'Mary', :age => 14)
|
146
|
-
]
|
147
|
-
end
|
148
|
-
|
149
|
-
should "allow attribute filtering with only" do
|
150
|
-
json = @contacts.to_json(:only => :name)
|
151
|
-
assert_match %r{\{"name":"David"\}}, json
|
152
|
-
assert_match %r{\{"name":"Mary"\}}, json
|
153
|
-
end
|
154
|
-
|
155
|
-
should "allow attribute filtering with except" do
|
156
|
-
json = @contacts.to_json(:except => [:name, :preferences, :awesome, :created_at, :updated_at])
|
157
|
-
assert_match %r{"age":39}, json
|
158
|
-
assert_match %r{"age":14}, json
|
159
|
-
assert_no_match %r{"name":}, json
|
160
|
-
assert_no_match %r{"preferences":}, json
|
161
|
-
assert_no_match %r{"awesome":}, json
|
162
|
-
assert_no_match %r{"created_at":}, json
|
163
|
-
assert_no_match %r{"updated_at":}, json
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
should "allow options for hash of records" do
|
168
|
-
contacts = {
|
169
|
-
1 => Contact.new(:name => 'David', :age => 39),
|
170
|
-
2 => Contact.new(:name => 'Mary', :age => 14)
|
171
|
-
}
|
172
|
-
json = contacts.to_json(:only => [1, :name])
|
173
|
-
assert_match %r{"1":}, json
|
174
|
-
assert_match %r{\{"name":"David"\}}, json
|
175
|
-
assert_no_match %r{"2":}, json
|
176
|
-
end
|
177
|
-
|
178
|
-
should "include embedded attributes" do
|
179
|
-
contact = Contact.new(:name => 'John', :age => 27)
|
180
|
-
contact.tags = [Tag.new(:name => 'awesome'), Tag.new(:name => 'ruby')]
|
181
|
-
json = contact.to_json
|
182
|
-
assert_match %r{"tags":}, json
|
183
|
-
assert_match %r{"name":"awesome"}, json
|
184
|
-
assert_match %r{"name":"ruby"}, json
|
185
|
-
end
|
186
|
-
|
187
|
-
should "include dynamic attributes" do
|
188
|
-
contact = Contact.new(:name => 'John', :age => 27, :foo => 'bar')
|
189
|
-
contact['smell'] = 'stinky'
|
190
|
-
json = contact.to_json
|
191
|
-
assert_match %r{"smell":"stinky"}, json
|
192
|
-
end
|
193
|
-
end
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class JsonSerializationTest < Test::Unit::TestCase
|
4
|
+
class Tag
|
5
|
+
include MongoMapper::EmbeddedDocument
|
6
|
+
key :name, String
|
7
|
+
end
|
8
|
+
|
9
|
+
class Contact
|
10
|
+
include MongoMapper::Document
|
11
|
+
key :name, String
|
12
|
+
key :age, Integer
|
13
|
+
key :created_at, Time
|
14
|
+
key :awesome, Boolean
|
15
|
+
key :preferences, Hash
|
16
|
+
key :hiding, String
|
17
|
+
|
18
|
+
many :tags, :class_name => 'JsonSerializationTest::Tag'
|
19
|
+
end
|
20
|
+
|
21
|
+
def setup
|
22
|
+
Contact.include_root_in_json = false
|
23
|
+
@contact = Contact.new(
|
24
|
+
:name => 'Konata Izumi',
|
25
|
+
:age => 16,
|
26
|
+
:created_at => Time.utc(2006, 8, 1),
|
27
|
+
:awesome => true,
|
28
|
+
:preferences => { :shows => 'anime' }
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
should "include demodulized root" do
|
33
|
+
Contact.include_root_in_json = true
|
34
|
+
assert_match %r{^\{"contact": \{}, @contact.to_json
|
35
|
+
end
|
36
|
+
|
37
|
+
should "encode all encodable attributes" do
|
38
|
+
json = @contact.to_json
|
39
|
+
|
40
|
+
assert_no_match %r{"_id"}, json
|
41
|
+
assert_match %r{"name":"Konata Izumi"}, json
|
42
|
+
assert_match %r{"age":16}, json
|
43
|
+
assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
|
44
|
+
assert_match %r{"awesome":true}, json
|
45
|
+
assert_match %r{"preferences":\{"shows":"anime"\}}, json
|
46
|
+
assert_match %r{"hiding":null}, json
|
47
|
+
end
|
48
|
+
|
49
|
+
should "allow attribute filtering with only" do
|
50
|
+
json = @contact.to_json(:only => [:name, :age])
|
51
|
+
|
52
|
+
assert_no_match %r{"_id"}, json
|
53
|
+
assert_match %r{"name":"Konata Izumi"}, json
|
54
|
+
assert_match %r{"age":16}, json
|
55
|
+
assert_no_match %r{"awesome"}, json
|
56
|
+
assert_no_match %r{"created_at"}, json
|
57
|
+
assert_no_match %r{"preferences"}, json
|
58
|
+
assert_no_match %r{"hiding"}, json
|
59
|
+
end
|
60
|
+
|
61
|
+
should "allow attribute filtering with except" do
|
62
|
+
json = @contact.to_json(:except => [:name, :age])
|
63
|
+
|
64
|
+
assert_no_match %r{"_id"}, json
|
65
|
+
assert_no_match %r{"name"}, json
|
66
|
+
assert_no_match %r{"age"}, json
|
67
|
+
assert_match %r{"awesome"}, json
|
68
|
+
assert_match %r{"created_at"}, json
|
69
|
+
assert_match %r{"preferences"}, json
|
70
|
+
assert_match %r{"hiding"}, json
|
71
|
+
end
|
72
|
+
|
73
|
+
context "_id key" do
|
74
|
+
should "not be included by default" do
|
75
|
+
json = @contact.to_json
|
76
|
+
assert_no_match %r{"_id":}, json
|
77
|
+
end
|
78
|
+
|
79
|
+
should "not be included even if :except is used" do
|
80
|
+
json = @contact.to_json(:except => :name)
|
81
|
+
assert_no_match %r{"_id":}, json
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "id method" do
|
86
|
+
setup do
|
87
|
+
def @contact.label; "Has cheezburger"; end
|
88
|
+
def @contact.favorite_quote; "Constraints are liberating"; end
|
89
|
+
end
|
90
|
+
|
91
|
+
should "be included by default" do
|
92
|
+
json = @contact.to_json
|
93
|
+
assert_match %r{"id"}, json
|
94
|
+
end
|
95
|
+
|
96
|
+
should "be included when single method included" do
|
97
|
+
json = @contact.to_json(:methods => :label)
|
98
|
+
assert_match %r{"id"}, json
|
99
|
+
assert_match %r{"label":"Has cheezburger"}, json
|
100
|
+
assert_match %r{"name":"Konata Izumi"}, json
|
101
|
+
assert_no_match %r{"favorite_quote":"Constraints are liberating"}, json
|
102
|
+
end
|
103
|
+
|
104
|
+
should "be included when multiple methods included" do
|
105
|
+
json = @contact.to_json(:methods => [:label, :favorite_quote])
|
106
|
+
assert_match %r{"id"}, json
|
107
|
+
assert_match %r{"label":"Has cheezburger"}, json
|
108
|
+
assert_match %r{"favorite_quote":"Constraints are liberating"}, json
|
109
|
+
assert_match %r{"name":"Konata Izumi"}, json
|
110
|
+
end
|
111
|
+
|
112
|
+
should "not be included if :only is present" do
|
113
|
+
json = @contact.to_json(:only => :name)
|
114
|
+
assert_no_match %r{"id":}, json
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context "including methods" do
|
119
|
+
setup do
|
120
|
+
def @contact.label; "Has cheezburger"; end
|
121
|
+
def @contact.favorite_quote; "Constraints are liberating"; end
|
122
|
+
end
|
123
|
+
|
124
|
+
should "include single method" do
|
125
|
+
json = @contact.to_json(:methods => :label)
|
126
|
+
assert_match %r{"label":"Has cheezburger"}, json
|
127
|
+
end
|
128
|
+
|
129
|
+
should "include multiple methods" do
|
130
|
+
json = @contact.to_json(:only => :name, :methods => [:label, :favorite_quote])
|
131
|
+
assert_match %r{"label":"Has cheezburger"}, json
|
132
|
+
assert_match %r{"favorite_quote":"Constraints are liberating"}, json
|
133
|
+
assert_match %r{"name":"Konata Izumi"}, json
|
134
|
+
assert_no_match %r{"age":16}, json
|
135
|
+
assert_no_match %r{"awesome"}, json
|
136
|
+
assert_no_match %r{"created_at"}, json
|
137
|
+
assert_no_match %r{"preferences"}, json
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "array of records" do
|
142
|
+
setup do
|
143
|
+
@contacts = [
|
144
|
+
Contact.new(:name => 'David', :age => 39),
|
145
|
+
Contact.new(:name => 'Mary', :age => 14)
|
146
|
+
]
|
147
|
+
end
|
148
|
+
|
149
|
+
should "allow attribute filtering with only" do
|
150
|
+
json = @contacts.to_json(:only => :name)
|
151
|
+
assert_match %r{\{"name":"David"\}}, json
|
152
|
+
assert_match %r{\{"name":"Mary"\}}, json
|
153
|
+
end
|
154
|
+
|
155
|
+
should "allow attribute filtering with except" do
|
156
|
+
json = @contacts.to_json(:except => [:name, :preferences, :awesome, :created_at, :updated_at])
|
157
|
+
assert_match %r{"age":39}, json
|
158
|
+
assert_match %r{"age":14}, json
|
159
|
+
assert_no_match %r{"name":}, json
|
160
|
+
assert_no_match %r{"preferences":}, json
|
161
|
+
assert_no_match %r{"awesome":}, json
|
162
|
+
assert_no_match %r{"created_at":}, json
|
163
|
+
assert_no_match %r{"updated_at":}, json
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
should "allow options for hash of records" do
|
168
|
+
contacts = {
|
169
|
+
1 => Contact.new(:name => 'David', :age => 39),
|
170
|
+
2 => Contact.new(:name => 'Mary', :age => 14)
|
171
|
+
}
|
172
|
+
json = contacts.to_json(:only => [1, :name])
|
173
|
+
assert_match %r{"1":}, json
|
174
|
+
assert_match %r{\{"name":"David"\}}, json
|
175
|
+
assert_no_match %r{"2":}, json
|
176
|
+
end
|
177
|
+
|
178
|
+
should "include embedded attributes" do
|
179
|
+
contact = Contact.new(:name => 'John', :age => 27)
|
180
|
+
contact.tags = [Tag.new(:name => 'awesome'), Tag.new(:name => 'ruby')]
|
181
|
+
json = contact.to_json
|
182
|
+
assert_match %r{"tags":}, json
|
183
|
+
assert_match %r{"name":"awesome"}, json
|
184
|
+
assert_match %r{"name":"ruby"}, json
|
185
|
+
end
|
186
|
+
|
187
|
+
should "include dynamic attributes" do
|
188
|
+
contact = Contact.new(:name => 'John', :age => 27, :foo => 'bar')
|
189
|
+
contact['smell'] = 'stinky'
|
190
|
+
json = contact.to_json
|
191
|
+
assert_match %r{"smell":"stinky"}, json
|
192
|
+
end
|
193
|
+
end
|