mongo_mapper-unstable 2010.1.27 → 2010.1.28
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/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/mongo_mapper/document.rb +17 -12
- data/lib/mongo_mapper/embedded_document.rb +12 -5
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +1 -0
- data/lib/mongo_mapper/plugins/keys.rb +9 -1
- data/lib/mongo_mapper/plugins/protected.rb +41 -0
- data/lib/mongo_mapper/support.rb +2 -1
- data/lib/mongo_mapper.rb +2 -1
- data/test/functional/associations/test_many_embedded_proxy.rb +38 -0
- data/test/functional/test_document.rb +91 -73
- data/test/functional/test_protected.rb +139 -0
- data/test/test_helper.rb +11 -17
- data/test/unit/test_embedded_document.rb +544 -533
- data/test/unit/test_support.rb +5 -1
- data/test/unit/test_validations.rb +55 -3
- metadata +6 -3
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ Jeweler::Tasks.new do |gem|
|
|
12
12
|
gem.authors = ["John Nunemaker"]
|
13
13
|
|
14
14
|
gem.add_dependency('activesupport', '>= 2.3')
|
15
|
-
gem.add_dependency('mongo', '0.18.
|
15
|
+
gem.add_dependency('mongo', '0.18.3')
|
16
16
|
gem.add_dependency('jnunemaker-validatable', '1.8.1')
|
17
17
|
|
18
18
|
gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2010.01.
|
1
|
+
2010.01.28
|
@@ -7,8 +7,8 @@ module MongoMapper
|
|
7
7
|
include InstanceMethods
|
8
8
|
extend ClassMethods
|
9
9
|
extend Finders
|
10
|
-
|
11
10
|
extend Plugins
|
11
|
+
|
12
12
|
plugin Plugins::Associations
|
13
13
|
plugin Plugins::Clone
|
14
14
|
plugin Plugins::Descendants
|
@@ -18,6 +18,7 @@ module MongoMapper
|
|
18
18
|
plugin Plugins::Dirty # for now dirty needs to be after keys
|
19
19
|
plugin Plugins::Logger
|
20
20
|
plugin Plugins::Pagination
|
21
|
+
plugin Plugins::Protected
|
21
22
|
plugin Plugins::Rails
|
22
23
|
plugin Plugins::Serialization
|
23
24
|
plugin Plugins::Validations
|
@@ -69,6 +70,21 @@ module MongoMapper
|
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
73
|
+
def find_or_create(arg)
|
74
|
+
first(arg) || create(arg)
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_each(options={})
|
78
|
+
criteria, options = to_finder_options(options)
|
79
|
+
collection.find(criteria, options).each do |doc|
|
80
|
+
yield load(doc)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def find_by_id(id)
|
85
|
+
find(id)
|
86
|
+
end
|
87
|
+
|
72
88
|
def first(options={})
|
73
89
|
find_one(options)
|
74
90
|
end
|
@@ -82,21 +98,10 @@ module MongoMapper
|
|
82
98
|
find_many(options)
|
83
99
|
end
|
84
100
|
|
85
|
-
def find_by_id(id)
|
86
|
-
find(id)
|
87
|
-
end
|
88
|
-
|
89
101
|
def count(options={})
|
90
102
|
collection.find(to_criteria(options)).count
|
91
103
|
end
|
92
104
|
|
93
|
-
def find_each(options={})
|
94
|
-
criteria, options = to_finder_options(options)
|
95
|
-
collection.find(criteria, options).each do |doc|
|
96
|
-
yield load(doc)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
105
|
def exists?(options={})
|
101
106
|
!count(options).zero?
|
102
107
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module MongoMapper
|
2
2
|
module EmbeddedDocument
|
3
3
|
extend DescendantAppends
|
4
|
-
|
4
|
+
|
5
5
|
def self.included(model)
|
6
6
|
model.class_eval do
|
7
7
|
include InstanceMethods
|
8
8
|
extend ClassMethods
|
9
|
-
|
10
9
|
extend Plugins
|
10
|
+
|
11
11
|
plugin Plugins::Associations
|
12
12
|
plugin Plugins::Clone
|
13
13
|
plugin Plugins::Descendants
|
@@ -15,13 +15,14 @@ module MongoMapper
|
|
15
15
|
plugin Plugins::Inspect
|
16
16
|
plugin Plugins::Keys
|
17
17
|
plugin Plugins::Logger
|
18
|
+
plugin Plugins::Protected
|
18
19
|
plugin Plugins::Rails
|
19
20
|
plugin Plugins::Serialization
|
20
21
|
plugin Plugins::Validations
|
21
22
|
|
22
|
-
attr_accessor :_root_document
|
23
|
+
attr_accessor :_root_document, :_parent_document
|
23
24
|
end
|
24
|
-
|
25
|
+
|
25
26
|
super
|
26
27
|
end
|
27
28
|
|
@@ -29,6 +30,12 @@ module MongoMapper
|
|
29
30
|
def embeddable?
|
30
31
|
true
|
31
32
|
end
|
33
|
+
|
34
|
+
def embedded_in(owner_name)
|
35
|
+
define_method(owner_name) do
|
36
|
+
self._parent_document
|
37
|
+
end
|
38
|
+
end
|
32
39
|
end
|
33
40
|
|
34
41
|
module InstanceMethods
|
@@ -38,7 +45,7 @@ module MongoMapper
|
|
38
45
|
end
|
39
46
|
result
|
40
47
|
end
|
41
|
-
|
48
|
+
|
42
49
|
def save!(options={})
|
43
50
|
if result = _root_document.try(:save!, options)
|
44
51
|
@new = false
|
@@ -122,6 +122,14 @@ module MongoMapper
|
|
122
122
|
validates_format_of(attribute, :with => key.options[:format])
|
123
123
|
end
|
124
124
|
|
125
|
+
if key.options[:in]
|
126
|
+
validates_inclusion_of(attribute, :within => key.options[:in])
|
127
|
+
end
|
128
|
+
|
129
|
+
if key.options[:not_in]
|
130
|
+
validates_exclusion_of(attribute, :within => key.options[:not_in])
|
131
|
+
end
|
132
|
+
|
125
133
|
if key.options[:length]
|
126
134
|
length_options = case key.options[:length]
|
127
135
|
when Integer
|
@@ -289,4 +297,4 @@ module MongoMapper
|
|
289
297
|
end
|
290
298
|
end
|
291
299
|
end
|
292
|
-
end
|
300
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
module Plugins
|
3
|
+
module Protected
|
4
|
+
module ClassMethods
|
5
|
+
def attr_protected(*attrs)
|
6
|
+
self.write_inheritable_attribute(:attr_protected, Set.new(attrs) + (protected_attributes || []))
|
7
|
+
end
|
8
|
+
|
9
|
+
def protected_attributes
|
10
|
+
self.read_inheritable_attribute(:attr_protected)
|
11
|
+
end
|
12
|
+
|
13
|
+
def key(*args)
|
14
|
+
key = super
|
15
|
+
attr_protected key.name.to_sym if key.options[:protected]
|
16
|
+
key
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module InstanceMethods
|
21
|
+
def update_attributes(attrs={})
|
22
|
+
super(filter_protected_attrs(attrs))
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_attributes!(attrs={})
|
26
|
+
super(filter_protected_attrs(attrs))
|
27
|
+
end
|
28
|
+
|
29
|
+
def protected_attributes
|
30
|
+
self.class.protected_attributes
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
def filter_protected_attrs(attrs)
|
35
|
+
return attrs if protected_attributes.blank?
|
36
|
+
attrs.dup.delete_if { |key, val| protected_attributes.include?(key) }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/mongo_mapper/support.rb
CHANGED
data/lib/mongo_mapper.rb
CHANGED
@@ -6,7 +6,7 @@ require 'set'
|
|
6
6
|
# if there is a better way to do this, please enlighten me!
|
7
7
|
if self.class.const_defined?(:Gem)
|
8
8
|
gem 'activesupport', '>= 2.3'
|
9
|
-
gem 'mongo', '0.18.
|
9
|
+
gem 'mongo', '0.18.3'
|
10
10
|
gem 'jnunemaker-validatable', '1.8.1'
|
11
11
|
end
|
12
12
|
|
@@ -117,6 +117,7 @@ require 'mongo_mapper/plugins/inspect'
|
|
117
117
|
require 'mongo_mapper/plugins/keys'
|
118
118
|
require 'mongo_mapper/plugins/logger'
|
119
119
|
require 'mongo_mapper/plugins/pagination'
|
120
|
+
require 'mongo_mapper/plugins/protected'
|
120
121
|
require 'mongo_mapper/plugins/rails'
|
121
122
|
require 'mongo_mapper/plugins/serialization'
|
122
123
|
require 'mongo_mapper/plugins/validations'
|
@@ -15,6 +15,7 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
|
|
15
15
|
@pet_class = EDoc do
|
16
16
|
key :name, String
|
17
17
|
end
|
18
|
+
@pet_class.embedded_in :person
|
18
19
|
@person_class = EDoc do
|
19
20
|
key :name, String
|
20
21
|
end
|
@@ -133,6 +134,17 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
|
|
133
134
|
doc.people.first._root_document.should == doc
|
134
135
|
doc.people.first.pets.first._root_document.should == doc
|
135
136
|
end
|
137
|
+
should "create a reference to the owning document for all embedded documents before save" do
|
138
|
+
doc = @klass.new
|
139
|
+
meg = @person_class.new(:name => 'Meg')
|
140
|
+
pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
|
141
|
+
|
142
|
+
doc.people << meg
|
143
|
+
meg.pets << pet
|
144
|
+
|
145
|
+
doc.people.first._parent_document.should == doc
|
146
|
+
doc.people.first.pets.first._parent_document.should == doc.people.first
|
147
|
+
end
|
136
148
|
|
137
149
|
should "create a reference to the root document for all embedded documents" do
|
138
150
|
sparky = @pet_class.new(:name => 'Sparky', :species => 'Dog')
|
@@ -145,6 +157,32 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
|
|
145
157
|
doc.people.first._root_document.should == doc
|
146
158
|
doc.people.first.pets.first._root_document.should == doc
|
147
159
|
end
|
160
|
+
should "create a reference to the owning document for all embedded documents" do
|
161
|
+
doc = @klass.new
|
162
|
+
meg = @person_class.new(:name => 'Meg')
|
163
|
+
pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
|
164
|
+
|
165
|
+
doc.people << meg
|
166
|
+
meg.pets << pet
|
167
|
+
doc.save
|
168
|
+
|
169
|
+
doc.reload
|
170
|
+
doc.people.first._parent_document.should == doc
|
171
|
+
doc.people.first.pets.first._parent_document.should == doc.people.first
|
172
|
+
end
|
173
|
+
|
174
|
+
should "create embedded_in relationship for embedded docs" do
|
175
|
+
doc = @klass.new
|
176
|
+
meg = @person_class.new(:name => 'Meg')
|
177
|
+
pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
|
178
|
+
|
179
|
+
doc.people << meg
|
180
|
+
meg.pets << pet
|
181
|
+
doc.save
|
182
|
+
|
183
|
+
doc.reload
|
184
|
+
doc.people.first.pets.first.person.should == doc.people.first
|
185
|
+
end
|
148
186
|
end
|
149
187
|
|
150
188
|
should "allow finding by id" do
|
@@ -13,7 +13,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
context "
|
16
|
+
context "array key" do
|
17
17
|
setup do
|
18
18
|
@document.key :tags, Array
|
19
19
|
end
|
@@ -60,7 +60,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
context "
|
63
|
+
context "hash key" do
|
64
64
|
setup do
|
65
65
|
@document.key :foo, Hash
|
66
66
|
end
|
@@ -95,7 +95,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
context "
|
98
|
+
context "custom type key with default" do
|
99
99
|
setup do
|
100
100
|
@document.key :window, WindowSize, :default => WindowSize.new(600, 480)
|
101
101
|
end
|
@@ -407,6 +407,24 @@ class DocumentTest < Test::Unit::TestCase
|
|
407
407
|
end
|
408
408
|
end
|
409
409
|
|
410
|
+
context "find_or_create" do
|
411
|
+
should "find if exists" do
|
412
|
+
created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
|
413
|
+
lambda {
|
414
|
+
found = @document.find_or_create(:first_name => 'John', :last_name => 'Nunemaker')
|
415
|
+
found.should == created
|
416
|
+
}.should_not change { @document.count }
|
417
|
+
end
|
418
|
+
|
419
|
+
should "create if not found" do
|
420
|
+
lambda {
|
421
|
+
created = @document.find_or_create(:first_name => 'John', :last_name => 'Nunemaker')
|
422
|
+
created.first_name.should == 'John'
|
423
|
+
created.last_name.should == 'Nunemaker'
|
424
|
+
}.should change { @document.count }.by(1)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
410
428
|
context "ClassMethods#delete (single document)" do
|
411
429
|
setup do
|
412
430
|
@doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
|
@@ -568,10 +586,10 @@ class DocumentTest < Test::Unit::TestCase
|
|
568
586
|
@document.new.database.should == @document.database
|
569
587
|
end
|
570
588
|
|
571
|
-
context "#
|
589
|
+
context "#update_attributes (new document)" do
|
572
590
|
setup do
|
573
591
|
@doc = @document.new(:first_name => 'John', :age => '27')
|
574
|
-
@doc.
|
592
|
+
@doc.update_attributes(:first_name => 'Johnny', :age => 30)
|
575
593
|
end
|
576
594
|
|
577
595
|
should "insert document into the collection" do
|
@@ -583,54 +601,27 @@ class DocumentTest < Test::Unit::TestCase
|
|
583
601
|
end
|
584
602
|
|
585
603
|
should "save attributes" do
|
586
|
-
@doc.first_name.should == '
|
587
|
-
@doc.age.should ==
|
604
|
+
@doc.first_name.should == 'Johnny'
|
605
|
+
@doc.age.should == 30
|
588
606
|
end
|
589
607
|
|
590
608
|
should "update attributes in the database" do
|
591
609
|
doc = @doc.reload
|
592
610
|
doc.should == @doc
|
593
|
-
doc.first_name.should == '
|
594
|
-
doc.age.should ==
|
595
|
-
end
|
596
|
-
|
597
|
-
should "allow to add custom attributes to the document" do
|
598
|
-
@doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male', :tags => [1, "2"])
|
599
|
-
@doc.save
|
600
|
-
doc = @doc.reload
|
601
|
-
doc.gender.should == 'male'
|
602
|
-
doc.tags.should == [1, "2"]
|
603
|
-
end
|
604
|
-
|
605
|
-
should "allow to use custom methods to assign properties" do
|
606
|
-
klass = Doc do
|
607
|
-
key :name, String
|
608
|
-
|
609
|
-
def realname=(value)
|
610
|
-
self.name = value
|
611
|
-
end
|
612
|
-
end
|
613
|
-
|
614
|
-
person = klass.new(:realname => 'David')
|
615
|
-
person.save
|
616
|
-
person.reload.name.should == 'David'
|
611
|
+
doc.first_name.should == 'Johnny'
|
612
|
+
doc.age.should == 30
|
617
613
|
end
|
618
614
|
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
doc.save
|
623
|
-
doc.date.should == Date.new(2009, 12, 1)
|
624
|
-
end
|
615
|
+
should "allow updating custom attributes" do
|
616
|
+
@doc.update_attributes(:gender => 'mALe')
|
617
|
+
@doc.reload.gender.should == 'mALe'
|
625
618
|
end
|
626
619
|
end
|
627
620
|
|
628
|
-
context "#
|
621
|
+
context "#update_attributes (existing document)" do
|
629
622
|
setup do
|
630
623
|
@doc = @document.create(:first_name => 'John', :age => '27')
|
631
|
-
@doc.first_name
|
632
|
-
@doc.age = 30
|
633
|
-
@doc.save
|
624
|
+
@doc.update_attributes(:first_name => 'Johnny', :age => 30)
|
634
625
|
end
|
635
626
|
|
636
627
|
should "not insert document into collection" do
|
@@ -647,19 +638,26 @@ class DocumentTest < Test::Unit::TestCase
|
|
647
638
|
doc.first_name.should == 'Johnny'
|
648
639
|
doc.age.should == 30
|
649
640
|
end
|
641
|
+
end
|
650
642
|
|
651
|
-
|
652
|
-
|
653
|
-
@
|
654
|
-
@doc.save
|
655
|
-
@doc.reload.gender.should == 'Male'
|
643
|
+
context "#update_attributes (return value)" do
|
644
|
+
setup do
|
645
|
+
@document.key :foo, String, :required => true
|
656
646
|
end
|
657
|
-
end
|
658
647
|
|
659
|
-
|
648
|
+
should "be true if document valid" do
|
649
|
+
@document.new.update_attributes(:foo => 'bar').should be_true
|
650
|
+
end
|
651
|
+
|
652
|
+
should "be false if document not valid" do
|
653
|
+
@document.new.update_attributes({}).should be_false
|
654
|
+
end
|
655
|
+
end
|
656
|
+
|
657
|
+
context "#save (new document)" do
|
660
658
|
setup do
|
661
659
|
@doc = @document.new(:first_name => 'John', :age => '27')
|
662
|
-
@doc.
|
660
|
+
@doc.save
|
663
661
|
end
|
664
662
|
|
665
663
|
should "insert document into the collection" do
|
@@ -671,27 +669,54 @@ class DocumentTest < Test::Unit::TestCase
|
|
671
669
|
end
|
672
670
|
|
673
671
|
should "save attributes" do
|
674
|
-
@doc.first_name.should == '
|
675
|
-
@doc.age.should ==
|
672
|
+
@doc.first_name.should == 'John'
|
673
|
+
@doc.age.should == 27
|
676
674
|
end
|
677
675
|
|
678
676
|
should "update attributes in the database" do
|
679
677
|
doc = @doc.reload
|
680
678
|
doc.should == @doc
|
681
|
-
doc.first_name.should == '
|
682
|
-
doc.age.should ==
|
679
|
+
doc.first_name.should == 'John'
|
680
|
+
doc.age.should == 27
|
683
681
|
end
|
684
682
|
|
685
|
-
should "allow
|
686
|
-
@doc.
|
687
|
-
@doc.
|
683
|
+
should "allow to add custom attributes to the document" do
|
684
|
+
@doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male', :tags => [1, "2"])
|
685
|
+
@doc.save
|
686
|
+
doc = @doc.reload
|
687
|
+
doc.gender.should == 'male'
|
688
|
+
doc.tags.should == [1, "2"]
|
689
|
+
end
|
690
|
+
|
691
|
+
should "allow to use custom methods to assign properties" do
|
692
|
+
klass = Doc do
|
693
|
+
key :name, String
|
694
|
+
|
695
|
+
def realname=(value)
|
696
|
+
self.name = value
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
person = klass.new(:realname => 'David')
|
701
|
+
person.save
|
702
|
+
person.reload.name.should == 'David'
|
703
|
+
end
|
704
|
+
|
705
|
+
context "with key of type date" do
|
706
|
+
should "save the date value as a Time object" do
|
707
|
+
doc = @document.new(:first_name => 'John', :age => '27', :date => "12/01/2009")
|
708
|
+
doc.save
|
709
|
+
doc.date.should == Date.new(2009, 12, 1)
|
710
|
+
end
|
688
711
|
end
|
689
712
|
end
|
690
713
|
|
691
|
-
context "#
|
714
|
+
context "#save (existing document)" do
|
692
715
|
setup do
|
693
716
|
@doc = @document.create(:first_name => 'John', :age => '27')
|
694
|
-
@doc.
|
717
|
+
@doc.first_name = 'Johnny'
|
718
|
+
@doc.age = 30
|
719
|
+
@doc.save
|
695
720
|
end
|
696
721
|
|
697
722
|
should "not insert document into collection" do
|
@@ -708,22 +733,15 @@ class DocumentTest < Test::Unit::TestCase
|
|
708
733
|
doc.first_name.should == 'Johnny'
|
709
734
|
doc.age.should == 30
|
710
735
|
end
|
711
|
-
end
|
712
|
-
|
713
|
-
context "#update_attributes" do
|
714
|
-
setup do
|
715
|
-
@document.key :foo, String, :required => true
|
716
|
-
end
|
717
|
-
|
718
|
-
should "return true if document valid" do
|
719
|
-
@document.new.update_attributes(:foo => 'bar').should be_true
|
720
|
-
end
|
721
736
|
|
722
|
-
should "
|
723
|
-
@document.new
|
737
|
+
should "allow updating custom attributes" do
|
738
|
+
@doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male')
|
739
|
+
@doc.gender = 'Male'
|
740
|
+
@doc.save
|
741
|
+
@doc.reload.gender.should == 'Male'
|
724
742
|
end
|
725
743
|
end
|
726
|
-
|
744
|
+
|
727
745
|
context "#save (with validations off)" do
|
728
746
|
setup do
|
729
747
|
@document = Doc do
|
@@ -1091,7 +1109,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
1091
1109
|
end
|
1092
1110
|
end
|
1093
1111
|
|
1094
|
-
context "#
|
1112
|
+
context "#exists?" do
|
1095
1113
|
setup do
|
1096
1114
|
@doc = @document.create(:first_name => "James", :age => 27)
|
1097
1115
|
end
|
@@ -1162,7 +1180,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
1162
1180
|
end
|
1163
1181
|
end
|
1164
1182
|
|
1165
|
-
context "
|
1183
|
+
context "database has keys not defined in model" do
|
1166
1184
|
setup do
|
1167
1185
|
@id = Mongo::ObjectID.new
|
1168
1186
|
@document.collection.insert({
|