jmonteiro-mongo_mapper 0.1.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/.gitignore +10 -0
- data/LICENSE +20 -0
- data/README.rdoc +38 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/bin/mmconsole +60 -0
- data/jmonteiro-mongo_mapper.gemspec +195 -0
- data/lib/mongo_mapper.rb +128 -0
- data/lib/mongo_mapper/descendant_appends.rb +44 -0
- data/lib/mongo_mapper/document.rb +402 -0
- data/lib/mongo_mapper/dynamic_finder.rb +74 -0
- data/lib/mongo_mapper/embedded_document.rb +61 -0
- data/lib/mongo_mapper/finder_options.rb +127 -0
- data/lib/mongo_mapper/plugins.rb +19 -0
- data/lib/mongo_mapper/plugins/associations.rb +104 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +121 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +23 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +49 -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 +66 -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 +11 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +66 -0
- data/lib/mongo_mapper/plugins/inspect.rb +14 -0
- data/lib/mongo_mapper/plugins/keys.rb +295 -0
- data/lib/mongo_mapper/plugins/logger.rb +17 -0
- data/lib/mongo_mapper/plugins/pagination.rb +85 -0
- data/lib/mongo_mapper/plugins/protected.rb +31 -0
- data/lib/mongo_mapper/plugins/rails.rb +80 -0
- data/lib/mongo_mapper/plugins/serialization.rb +109 -0
- data/lib/mongo_mapper/plugins/validations.rb +48 -0
- data/lib/mongo_mapper/support.rb +213 -0
- data/performance/read_write.rb +52 -0
- data/specs.watchr +51 -0
- data/test/NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +93 -0
- data/test/functional/associations/test_in_array_proxy.rb +309 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +246 -0
- data/test/functional/associations/test_many_documents_proxy.rb +437 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +175 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +216 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +340 -0
- data/test/functional/associations/test_one_proxy.rb +149 -0
- data/test/functional/test_associations.rb +44 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_callbacks.rb +81 -0
- data/test/functional/test_dirty.rb +156 -0
- data/test/functional/test_document.rb +1171 -0
- data/test/functional/test_embedded_document.rb +125 -0
- data/test/functional/test_identity_map.rb +233 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +252 -0
- data/test/functional/test_pagination.rb +93 -0
- data/test/functional/test_protected.rb +41 -0
- data/test/functional/test_string_id_compatibility.rb +67 -0
- data/test/functional/test_validations.rb +329 -0
- data/test/models.rb +232 -0
- data/test/support/custom_matchers.rb +55 -0
- data/test/support/timing.rb +16 -0
- data/test/test_helper.rb +60 -0
- data/test/unit/associations/test_base.rb +207 -0
- data/test/unit/associations/test_proxy.rb +103 -0
- data/test/unit/serializers/test_json_serializer.rb +189 -0
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +203 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +628 -0
- data/test/unit/test_finder_options.rb +325 -0
- data/test/unit/test_keys.rb +169 -0
- data/test/unit/test_mongo_mapper.rb +65 -0
- data/test/unit/test_pagination.rb +127 -0
- data/test/unit/test_plugins.rb +42 -0
- data/test/unit/test_rails.rb +139 -0
- data/test/unit/test_rails_compatibility.rb +42 -0
- data/test/unit/test_serialization.rb +51 -0
- data/test/unit/test_support.rb +350 -0
- data/test/unit/test_time_zones.rb +39 -0
- data/test/unit/test_validations.rb +492 -0
- metadata +260 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PaginationTest < Test::Unit::TestCase
|
4
|
+
context "Paginating" do
|
5
|
+
setup do
|
6
|
+
@document = Doc do
|
7
|
+
set_collection_name 'users'
|
8
|
+
|
9
|
+
key :first_name, String
|
10
|
+
key :last_name, String
|
11
|
+
key :age, Integer
|
12
|
+
|
13
|
+
def self.per_page; 1 end
|
14
|
+
end
|
15
|
+
|
16
|
+
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
17
|
+
@doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
|
18
|
+
@doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
|
19
|
+
end
|
20
|
+
|
21
|
+
should "return the total pages" do
|
22
|
+
result = @document.paginate(:per_page => 2, :page => 1)
|
23
|
+
result.total_pages.should == 2
|
24
|
+
end
|
25
|
+
|
26
|
+
should "return the total pages when defaulting to the document class per_page" do
|
27
|
+
result = @document.paginate(:page => 1)
|
28
|
+
result.total_pages.should == 3
|
29
|
+
end
|
30
|
+
|
31
|
+
should "return the total of records" do
|
32
|
+
result = @document.paginate(:per_page => 2, :page => 1)
|
33
|
+
result.total_entries.should == 3
|
34
|
+
end
|
35
|
+
|
36
|
+
should "return the items" do
|
37
|
+
result = @document.paginate(:per_page => 2, :page => 1, :order => 'first_name')
|
38
|
+
result.size.should == 2
|
39
|
+
result.should == [@doc1, @doc3]
|
40
|
+
end
|
41
|
+
|
42
|
+
should "accept conditions" do
|
43
|
+
result = @document.paginate({
|
44
|
+
:last_name => 'Nunemaker',
|
45
|
+
:order => "age DESC",
|
46
|
+
:per_page => 2,
|
47
|
+
:page => 1,
|
48
|
+
})
|
49
|
+
result.should == [@doc1, @doc3]
|
50
|
+
result.first.age.should == 27
|
51
|
+
|
52
|
+
result = @document.paginate({
|
53
|
+
:conditions => {:last_name => 'Nunemaker'},
|
54
|
+
:order => "age DESC",
|
55
|
+
:per_page => 2,
|
56
|
+
:page => 1} )
|
57
|
+
result.should == [@doc1, @doc3]
|
58
|
+
result.first.age.should == 27
|
59
|
+
end
|
60
|
+
|
61
|
+
should "withstand rigor" do
|
62
|
+
result = @document.paginate({
|
63
|
+
:per_page => 1,
|
64
|
+
:page => 1,
|
65
|
+
:order => 'age desc',
|
66
|
+
:last_name => 'Nunemaker'
|
67
|
+
})
|
68
|
+
result.should == [@doc1]
|
69
|
+
result.total_entries.should == 2
|
70
|
+
result.total_pages.should == 2
|
71
|
+
|
72
|
+
result = @document.paginate({
|
73
|
+
:per_page => 1,
|
74
|
+
:page => 2,
|
75
|
+
:order => 'age desc',
|
76
|
+
:last_name => 'Nunemaker'
|
77
|
+
})
|
78
|
+
result.should == [@doc3]
|
79
|
+
result.total_entries.should == 2
|
80
|
+
result.total_pages.should == 2
|
81
|
+
|
82
|
+
result = @document.paginate({
|
83
|
+
:per_page => 2,
|
84
|
+
:page => 1,
|
85
|
+
:order => 'age desc',
|
86
|
+
:last_name => 'Nunemaker'
|
87
|
+
})
|
88
|
+
result.should == [@doc1, @doc3]
|
89
|
+
result.total_entries.should == 2
|
90
|
+
result.total_pages.should == 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ProtectedTest < Test::Unit::TestCase
|
4
|
+
context 'A document with protected attributes' do
|
5
|
+
setup do
|
6
|
+
@doc_class = Doc do
|
7
|
+
set_collection_name 'users'
|
8
|
+
key :name, String
|
9
|
+
key :admin, Boolean
|
10
|
+
|
11
|
+
attr_protected :admin
|
12
|
+
end
|
13
|
+
|
14
|
+
@doc = @doc_class.create( :name => 'Steve Sloan', :admin => false )
|
15
|
+
@doc.admin.should == false
|
16
|
+
end
|
17
|
+
|
18
|
+
should 'have protected attributes' do
|
19
|
+
@doc_class.protected_attributes.to_a.should == [:admin]
|
20
|
+
@doc.class.protected_attributes.to_a.should == [:admin]
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'assign protected attribute through accessor' do
|
24
|
+
@doc.admin = true
|
25
|
+
@doc.save!
|
26
|
+
@doc.admin.should == true
|
27
|
+
end
|
28
|
+
|
29
|
+
should 'ignore protected attribute on #update_attributes' do
|
30
|
+
@doc.update_attributes( :name => 'Ren Hoek', :admin => true )
|
31
|
+
@doc.name.should == 'Ren Hoek'
|
32
|
+
@doc.admin.should == false
|
33
|
+
end
|
34
|
+
|
35
|
+
should 'ignore protected attribute on #update_attributes!' do
|
36
|
+
@doc.update_attributes!( :name => 'Stimpson J. Cat', :admin => true )
|
37
|
+
@doc.name.should == 'Stimpson J. Cat'
|
38
|
+
@doc.admin.should == false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class StringIdCompatibilityTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@note_class = EDoc do
|
6
|
+
key :_id, String
|
7
|
+
end
|
8
|
+
|
9
|
+
@task_class = Doc do
|
10
|
+
key :_id, String
|
11
|
+
key :project_id, String
|
12
|
+
belongs_to :project
|
13
|
+
end
|
14
|
+
|
15
|
+
@project_class = Doc do
|
16
|
+
include MongoMapper::Document
|
17
|
+
key :_id, String
|
18
|
+
end
|
19
|
+
|
20
|
+
@task_class.belongs_to :project, :class => @project_class
|
21
|
+
@project_class.many :notes, :class => @note_class
|
22
|
+
@project_class.many :tasks, :class => @task_class, :foreign_key => 'project_id', :order => :position.asc
|
23
|
+
end
|
24
|
+
|
25
|
+
should "assign correct _id for documents" do
|
26
|
+
project = @project_class.create
|
27
|
+
project._id.should == project.id
|
28
|
+
project._id.should be_instance_of(String)
|
29
|
+
project.id.size.should == 24
|
30
|
+
lambda {
|
31
|
+
Mongo::ObjectID.from_string(project.id)
|
32
|
+
}.should_not raise_error
|
33
|
+
end
|
34
|
+
|
35
|
+
should "assign correct _id for embedded documents" do
|
36
|
+
note = @note_class.new
|
37
|
+
note.id.should == note._id
|
38
|
+
note.id.size.should == 24
|
39
|
+
end
|
40
|
+
|
41
|
+
should "find records" do
|
42
|
+
project = @project_class.create
|
43
|
+
@project_class.find(project.id).should == project
|
44
|
+
end
|
45
|
+
|
46
|
+
should "save embedded docs" do
|
47
|
+
n1 = @note_class.new
|
48
|
+
n2 = @note_class.new
|
49
|
+
n3 = @note_class.new
|
50
|
+
project = @project_class.create(:notes => [n1, n2, n3])
|
51
|
+
|
52
|
+
project = project.reload
|
53
|
+
project.notes.size.should == 3
|
54
|
+
project.notes.should == [n1, n2, n3]
|
55
|
+
end
|
56
|
+
|
57
|
+
should "be able to associate records" do
|
58
|
+
t1 = @task_class.new(:body => 'First task', :position => 1)
|
59
|
+
t2 = @task_class.new(:body => 'Second task', :position => 2)
|
60
|
+
t3 = @task_class.new(:body => 'Third task', :position => 3)
|
61
|
+
project = @project_class.create(:name => 'MM', :tasks => [t1, t2, t3])
|
62
|
+
|
63
|
+
project = project.reload
|
64
|
+
project.tasks.count.should == 3
|
65
|
+
project.tasks.should == [t1, t2, t3]
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,329 @@
|
|
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 = Doc do
|
7
|
+
key :name, String, :required => true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
should "not insert document" do
|
12
|
+
doc = @document.new
|
13
|
+
doc.save
|
14
|
+
@document.count.should == 0
|
15
|
+
end
|
16
|
+
|
17
|
+
should "populate document's errors" do
|
18
|
+
doc = @document.new
|
19
|
+
doc.errors.size.should == 0
|
20
|
+
doc.save
|
21
|
+
doc.errors.full_messages.should == ["Name can't be empty"]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "Saving a document that is invalid (destructive)" do
|
26
|
+
setup do
|
27
|
+
@document = Doc do
|
28
|
+
key :name, String, :required => true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
should "raise error" do
|
33
|
+
doc = @document.new
|
34
|
+
lambda { doc.save! }.should raise_error(MongoMapper::DocumentNotValid)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "Creating a document that is invalid (destructive)" do
|
39
|
+
setup do
|
40
|
+
@document = Doc do
|
41
|
+
key :name, String, :required => true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
should "raise error" do
|
46
|
+
lambda { @document.create! }.should raise_error(MongoMapper::DocumentNotValid)
|
47
|
+
end
|
48
|
+
|
49
|
+
should "create a new document" do
|
50
|
+
instance = @document.create!(:name => "James")
|
51
|
+
instance.new_record?.should be_false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "Saving an existing document that is invalid" do
|
56
|
+
setup do
|
57
|
+
@document = Doc do
|
58
|
+
key :name, String, :required => true
|
59
|
+
end
|
60
|
+
|
61
|
+
@doc = @document.create(:name => 'John Nunemaker')
|
62
|
+
end
|
63
|
+
|
64
|
+
should "not update document" do
|
65
|
+
@doc.name = nil
|
66
|
+
@doc.save
|
67
|
+
@doc.reload.name.should == 'John Nunemaker'
|
68
|
+
end
|
69
|
+
|
70
|
+
should "populate document's errors" do
|
71
|
+
@doc.name = nil
|
72
|
+
@doc.save
|
73
|
+
@doc.errors.full_messages.should == ["Name can't be empty"]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "Adding validation errors" do
|
78
|
+
setup do
|
79
|
+
@document = Doc do
|
80
|
+
key :action, String
|
81
|
+
def action_present
|
82
|
+
errors.add(:action, 'is invalid') if action.blank?
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
should "work with validate_on_create callback" do
|
88
|
+
@document.validate_on_create :action_present
|
89
|
+
|
90
|
+
doc = @document.new
|
91
|
+
doc.action = nil
|
92
|
+
doc.should have_error_on(:action)
|
93
|
+
|
94
|
+
doc.action = 'kick'
|
95
|
+
doc.should_not have_error_on(:action)
|
96
|
+
doc.save
|
97
|
+
|
98
|
+
doc.action = nil
|
99
|
+
doc.should_not have_error_on(:action)
|
100
|
+
end
|
101
|
+
|
102
|
+
should "work with validate_on_update callback" do
|
103
|
+
@document.validate_on_update :action_present
|
104
|
+
|
105
|
+
doc = @document.new
|
106
|
+
doc.action = nil
|
107
|
+
doc.should_not have_error_on(:action)
|
108
|
+
doc.save
|
109
|
+
|
110
|
+
doc.action = nil
|
111
|
+
doc.should have_error_on(:action)
|
112
|
+
|
113
|
+
doc.action = 'kick'
|
114
|
+
doc.should_not have_error_on(:action)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context "validating uniqueness of" do
|
119
|
+
setup do
|
120
|
+
@document = Doc do
|
121
|
+
key :name, String
|
122
|
+
validates_uniqueness_of :name
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
should "not fail if object is new" do
|
127
|
+
doc = @document.new
|
128
|
+
doc.should_not have_error_on(:name)
|
129
|
+
end
|
130
|
+
|
131
|
+
should "not fail when new object is out of scope" do
|
132
|
+
document = Doc do
|
133
|
+
key :name
|
134
|
+
key :adult
|
135
|
+
validates_uniqueness_of :name, :scope => :adult
|
136
|
+
end
|
137
|
+
doc = document.new("name" => "joe", :adult => true)
|
138
|
+
doc.save.should be_true
|
139
|
+
|
140
|
+
doc2 = document.new("name" => "joe", :adult => false)
|
141
|
+
doc2.should be_valid
|
142
|
+
end
|
143
|
+
|
144
|
+
should "allow to update an object" do
|
145
|
+
doc = @document.new("name" => "joe")
|
146
|
+
doc.save.should be_true
|
147
|
+
|
148
|
+
@document \
|
149
|
+
.stubs(:first) \
|
150
|
+
.with(:name => 'joe') \
|
151
|
+
.returns(doc)
|
152
|
+
|
153
|
+
doc.name = "joe"
|
154
|
+
doc.valid?.should be_true
|
155
|
+
doc.should_not have_error_on(:name)
|
156
|
+
end
|
157
|
+
|
158
|
+
should "fail if object name is not unique" do
|
159
|
+
doc = @document.new("name" => "joe")
|
160
|
+
doc.save.should be_true
|
161
|
+
|
162
|
+
@document \
|
163
|
+
.stubs(:first) \
|
164
|
+
.with(:name => 'joe') \
|
165
|
+
.returns(doc)
|
166
|
+
|
167
|
+
doc2 = @document.new("name" => "joe")
|
168
|
+
doc2.should have_error_on(:name)
|
169
|
+
end
|
170
|
+
|
171
|
+
should "allow multiple blank entries if :allow_blank => true" do
|
172
|
+
document = Doc do
|
173
|
+
key :name
|
174
|
+
validates_uniqueness_of :name, :allow_blank => :true
|
175
|
+
end
|
176
|
+
|
177
|
+
doc = document.new("name" => "")
|
178
|
+
doc.save.should be_true
|
179
|
+
|
180
|
+
document \
|
181
|
+
.stubs(:first) \
|
182
|
+
.with(:name => '') \
|
183
|
+
.returns(doc)
|
184
|
+
|
185
|
+
doc2 = document.new("name" => "")
|
186
|
+
doc2.should_not have_error_on(:name)
|
187
|
+
end
|
188
|
+
|
189
|
+
should "allow multiple nil entries if :allow_nil => true" do
|
190
|
+
document = Doc do
|
191
|
+
key :name
|
192
|
+
validates_uniqueness_of :name, :allow_nil => :true
|
193
|
+
end
|
194
|
+
|
195
|
+
doc = document.new('name' => nil)
|
196
|
+
doc.save.should be_true
|
197
|
+
|
198
|
+
doc2 = document.new('name' => nil)
|
199
|
+
doc2.should_not have_error_on(:name)
|
200
|
+
end
|
201
|
+
|
202
|
+
should "allow entries that differ only in case by default" do
|
203
|
+
document = Doc do
|
204
|
+
key :name
|
205
|
+
validates_uniqueness_of :name
|
206
|
+
end
|
207
|
+
|
208
|
+
doc = document.new("name" => "BLAMMO")
|
209
|
+
doc.save.should be_true
|
210
|
+
|
211
|
+
doc2 = document.new("name" => "blammo")
|
212
|
+
doc2.should_not have_error_on(:name)
|
213
|
+
end
|
214
|
+
|
215
|
+
context "with :case_sensitive => false" do
|
216
|
+
setup do
|
217
|
+
@document = Doc do
|
218
|
+
key :name
|
219
|
+
validates_uniqueness_of :name, :case_sensitive => false
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
should "fail on entries that differ only in case" do
|
224
|
+
doc = @document.new("name" => "BLAMMO")
|
225
|
+
doc.save.should be_true
|
226
|
+
|
227
|
+
doc2 = @document.new("name" => "blammo")
|
228
|
+
doc2.should have_error_on(:name)
|
229
|
+
end
|
230
|
+
|
231
|
+
should "not raise an error if value is nil" do
|
232
|
+
doc = @document.new("name" => nil)
|
233
|
+
lambda { doc.valid? }.should_not raise_error
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context "scoped by a single attribute" do
|
238
|
+
setup do
|
239
|
+
@document = Doc do
|
240
|
+
key :name, String
|
241
|
+
key :scope, String
|
242
|
+
validates_uniqueness_of :name, :scope => :scope
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
should "fail if the same name exists in the scope" do
|
247
|
+
doc = @document.new("name" => "joe", "scope" => "one")
|
248
|
+
doc.save.should be_true
|
249
|
+
|
250
|
+
@document \
|
251
|
+
.stubs(:first) \
|
252
|
+
.with(:name => 'joe', :scope => "one") \
|
253
|
+
.returns(doc)
|
254
|
+
|
255
|
+
doc2 = @document.new("name" => "joe", "scope" => "one")
|
256
|
+
doc2.should have_error_on(:name)
|
257
|
+
end
|
258
|
+
|
259
|
+
should "pass if the same name exists in a different scope" do
|
260
|
+
doc = @document.new("name" => "joe", "scope" => "one")
|
261
|
+
doc.save.should be_true
|
262
|
+
|
263
|
+
@document \
|
264
|
+
.stubs(:first) \
|
265
|
+
.with(:name => 'joe', :scope => 'two') \
|
266
|
+
.returns(nil)
|
267
|
+
|
268
|
+
doc2 = @document.new("name" => "joe", "scope" => "two")
|
269
|
+
doc2.should_not have_error_on(:name)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context "scoped by a multiple attributes" do
|
274
|
+
setup do
|
275
|
+
@document = Doc do
|
276
|
+
key :name, String
|
277
|
+
key :first_scope, String
|
278
|
+
key :second_scope, String
|
279
|
+
validates_uniqueness_of :name, :scope => [:first_scope, :second_scope]
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
should "fail if the same name exists in the scope" do
|
284
|
+
doc = @document.new("name" => "joe", "first_scope" => "one", "second_scope" => "two")
|
285
|
+
doc.save.should be_true
|
286
|
+
|
287
|
+
@document \
|
288
|
+
.stubs(:first) \
|
289
|
+
.with(:name => 'joe', :first_scope => 'one', :second_scope => 'two') \
|
290
|
+
.returns(doc)
|
291
|
+
|
292
|
+
doc2 = @document.new("name" => "joe", "first_scope" => "one", "second_scope" => "two")
|
293
|
+
doc2.should have_error_on(:name)
|
294
|
+
end
|
295
|
+
|
296
|
+
should "pass if the same name exists in a different scope" do
|
297
|
+
doc = @document.new("name" => "joe", "first_scope" => "one", "second_scope" => "two")
|
298
|
+
doc.save.should be_true
|
299
|
+
|
300
|
+
@document \
|
301
|
+
.stubs(:first) \
|
302
|
+
.with(:name => 'joe', :first_scope => 'one', :second_scope => 'one') \
|
303
|
+
.returns(nil)
|
304
|
+
|
305
|
+
doc2 = @document.new("name" => "joe", "first_scope" => "one", "second_scope" => "one")
|
306
|
+
doc2.should_not have_error_on(:name)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context "validates uniqueness of with :unique shortcut" do
|
312
|
+
should "work" do
|
313
|
+
@document = Doc do
|
314
|
+
key :name, String, :unique => true
|
315
|
+
end
|
316
|
+
|
317
|
+
doc = @document.create(:name => 'John')
|
318
|
+
doc.should_not have_error_on(:name)
|
319
|
+
|
320
|
+
@document \
|
321
|
+
.stubs(:first) \
|
322
|
+
.with(:name => 'John') \
|
323
|
+
.returns(doc)
|
324
|
+
|
325
|
+
second_john = @document.create(:name => 'John')
|
326
|
+
second_john.should have_error_on(:name, 'has already been taken')
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|