couchobject 0.5.0 → 0.6.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/History.txt +10 -0
- data/Manifest.txt +30 -6
- data/README.txt +580 -42
- data/TODO +2 -2
- data/config/hoe.rb +1 -1
- data/lib/couch_object.rb +7 -2
- data/lib/couch_object/database.rb +19 -34
- data/lib/couch_object/document.rb +13 -6
- data/lib/couch_object/error_classes.rb +110 -0
- data/lib/couch_object/persistable.rb +954 -36
- data/lib/couch_object/persistable/has_many_relations_array.rb +91 -0
- data/lib/couch_object/persistable/meta_classes.rb +568 -0
- data/lib/couch_object/persistable/overloaded_methods.rb +209 -0
- data/lib/couch_object/server.rb +1 -1
- data/lib/couch_object/utils.rb +44 -0
- data/lib/couch_object/version.rb +1 -1
- data/lib/couch_object/view.rb +129 -6
- data/script/console +0 -0
- data/script/destroy +0 -0
- data/script/generate +0 -0
- data/script/txt2html +0 -0
- data/spec/database_spec.rb +23 -31
- data/spec/database_spec.rb.orig +173 -0
- data/spec/document_spec.rb +21 -3
- data/spec/integration/database_integration_spec.rb +46 -15
- data/spec/integration/integration_helper.rb +3 -3
- data/spec/persistable/callback.rb +44 -0
- data/spec/persistable/callback_spec.rb +44 -0
- data/spec/persistable/cloning.rb +77 -0
- data/spec/persistable/cloning_spec.rb +77 -0
- data/spec/persistable/comparing_objects.rb +350 -0
- data/spec/persistable/comparing_objects_spec.rb +350 -0
- data/spec/persistable/deleting.rb +113 -0
- data/spec/persistable/deleting_spec.rb +113 -0
- data/spec/persistable/error_messages.rb +32 -0
- data/spec/persistable/error_messages_spec.rb +32 -0
- data/spec/persistable/loading.rb +339 -0
- data/spec/persistable/loading_spec.rb +339 -0
- data/spec/persistable/new_methods.rb +70 -0
- data/spec/persistable/new_methods_spec.rb +70 -0
- data/spec/persistable/persistable_helper.rb +194 -0
- data/spec/persistable/relations.rb +470 -0
- data/spec/persistable/relations_spec.rb +470 -0
- data/spec/persistable/saving.rb +137 -0
- data/spec/persistable/saving_spec.rb +137 -0
- data/spec/persistable/setting_storage_location.rb +65 -0
- data/spec/persistable/setting_storage_location_spec.rb +65 -0
- data/spec/persistable/timestamps.rb +76 -0
- data/spec/persistable/timestamps_spec.rb +76 -0
- data/spec/persistable/unsaved_changes.rb +211 -0
- data/spec/persistable/unsaved_changes_spec.rb +211 -0
- data/spec/server_spec.rb +5 -5
- data/spec/utils_spec.rb +60 -0
- data/spec/view_spec.rb +40 -7
- data/website/index.html +22 -7
- data/website/index.txt +13 -5
- metadata +93 -61
- data/bin/couch_ruby_view_requestor +0 -81
- data/lib/couch_object/model.rb +0 -5
- data/lib/couch_object/proc_condition.rb +0 -14
- data/spec/model_spec.rb +0 -5
- data/spec/persistable_spec.rb +0 -91
- data/spec/proc_condition_spec.rb +0 -26
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/persistable_helper.rb'
|
2
|
+
|
3
|
+
describe CouchObject::Persistable, "timestamp related actions:" do
|
4
|
+
before(:each) do
|
5
|
+
@bike = Bike.new
|
6
|
+
@timestampclass = WithTimeStamp.new
|
7
|
+
|
8
|
+
@db = mock("mock db")
|
9
|
+
|
10
|
+
content = HTTPResponse.new(JSON.unparse({
|
11
|
+
"_id" => "123BAC",
|
12
|
+
"_rev" => "946B7D1C",
|
13
|
+
"created_at" => Time.new,
|
14
|
+
"updated_at" => Time.new,
|
15
|
+
"class" => "WithTimeStamp",
|
16
|
+
"attributes" => {
|
17
|
+
"wheels" => 3
|
18
|
+
}
|
19
|
+
}))
|
20
|
+
|
21
|
+
CouchObject::Response.stub!(:body).and_return(content)
|
22
|
+
|
23
|
+
@empty_response = {}
|
24
|
+
@ok_response = {"ok" => true}
|
25
|
+
@document_response = CouchObject::Response.new(content)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "timestamps should be nil for classes that don't include them" do
|
29
|
+
@bike.created_at.should == nil
|
30
|
+
@bike.updated_at.should == nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it "timestamps should be set when saving an object" do
|
34
|
+
CouchObject::Database.should_receive(:open).and_return(@db)
|
35
|
+
timestampclass_json = @timestampclass.to_json
|
36
|
+
|
37
|
+
@timestampclass.stub!(:to_json).and_return(timestampclass_json)
|
38
|
+
@db.should_receive(:post).
|
39
|
+
with("", timestampclass_json).and_return(@document_response)
|
40
|
+
|
41
|
+
@timestampclass.save("foo")
|
42
|
+
|
43
|
+
@timestampclass.created_at.should_not == nil
|
44
|
+
@timestampclass.updated_at.should_not == nil
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should update updated_at when saving an object again" do
|
48
|
+
CouchObject::Database.stub!(:open).and_return(@db)
|
49
|
+
timestampclass_json = @timestampclass.to_json
|
50
|
+
|
51
|
+
@timestampclass.stub!(:to_json).and_return(timestampclass_json)
|
52
|
+
@db.should_receive(:post).
|
53
|
+
with("", timestampclass_json).and_return(@document_response)
|
54
|
+
@db.should_receive(:put).
|
55
|
+
with("123BAC", timestampclass_json).and_return(@document_response)
|
56
|
+
|
57
|
+
@timestampclass.save("foo")
|
58
|
+
updated_at = @timestampclass.updated_at
|
59
|
+
|
60
|
+
@timestampclass.save
|
61
|
+
|
62
|
+
@timestampclass.updated_at.should_not == updated_at
|
63
|
+
end
|
64
|
+
|
65
|
+
it "loaded object should have their timestamps set" do
|
66
|
+
CouchObject::Database.should_receive(:open).and_return(@db)
|
67
|
+
@db.should_receive(:get).with("123BAC").and_return(@document_response)
|
68
|
+
|
69
|
+
timestampclass = WithTimeStamp.get_by_id("123BAC", "foo")
|
70
|
+
|
71
|
+
timestampclass.class.should == WithTimeStamp
|
72
|
+
timestampclass.created_at.should_not == nil
|
73
|
+
timestampclass.updated_at.should_not == nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/persistable_helper.rb'
|
2
|
+
|
3
|
+
describe CouchObject::Persistable, "for loading objects:" do
|
4
|
+
before(:each) do
|
5
|
+
@bike = Bike.new
|
6
|
+
@with_location = WithStorageLocation.new
|
7
|
+
|
8
|
+
@db = mock("mock db")
|
9
|
+
|
10
|
+
@content_motor_bike = %{
|
11
|
+
{
|
12
|
+
"_id":"123BAC",
|
13
|
+
"_rev":"946B7D1C",
|
14
|
+
"class":"OtherMotorBike",
|
15
|
+
"attributes":
|
16
|
+
{
|
17
|
+
"wheels":2
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
@normal_content_motor_bike = %{
|
23
|
+
{
|
24
|
+
"_id":"123BAC",
|
25
|
+
"_rev":"946B7D1C",
|
26
|
+
"class":"MotorBike",
|
27
|
+
"attributes":
|
28
|
+
{
|
29
|
+
"wheels":2
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
content = HTTPResponse.new(JSON.unparse({
|
35
|
+
"_id" => "123BAC",
|
36
|
+
"_rev" => "946B7D1C",
|
37
|
+
}))
|
38
|
+
@document_response = CouchObject::Response.new(content)
|
39
|
+
|
40
|
+
@apartment_building_content = %{ {"_id":"A26EDC59D99D50C2CB2615404D357E49","_rev":"1756574922","class":"OtherApartmentBuilding","attributes":{}}
|
41
|
+
}
|
42
|
+
|
43
|
+
@apartment_building_inhabitants = %{{"total_rows":2,"offset":0,"rows":[{"id":"241757E4D7D2272C78048B4007399837","key":["12A64B5156002BFD66F23F559C5AD5FA","inhabitants"],"value":{"_id":"241757E4D7D2272C78048B4007399837","_rev":"2508041460","class":"OtherInhabitant","attributes":{},"belongs_to":{"inhabitants":"A26EDC59D99D50C2CB2615404D357E49"}}},{"id":"E94C93DEDB94BFC30B9AB396D4874D52","key":["12A64B5156002BFD66F23F559C5AD5FA","inhabitants"],"value":{"_id":"E94C93DEDB94BFC30B9AB396D4874D52","_rev":"960098874","class":"OtherInhabitant","attributes":{},"belongs_to":{"inhabitants":"A26EDC59D99D50C2CB2615404D357E49"}}}]}
|
44
|
+
}
|
45
|
+
|
46
|
+
CouchObject::Database.stub!(:open).and_return(@db)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return true for new objects" do
|
50
|
+
mbike = OtherMotorBike.new
|
51
|
+
mbike.unsaved_changes?.should == true
|
52
|
+
mbike.use_smart_save.should == true
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return true for new objects that haven't activated the smart save feature" do
|
56
|
+
mbike = MotorBike.new
|
57
|
+
mbike.unsaved_changes?.should == true
|
58
|
+
mbike.use_smart_save.should == false
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should know if an object has unsaved changes" do
|
62
|
+
response = HTTPResponse.new(@content_motor_bike)
|
63
|
+
|
64
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
65
|
+
|
66
|
+
mbike = MotorBike.get_by_id("123BAC", "foo")
|
67
|
+
mbike.id.should == "123BAC"
|
68
|
+
mbike.use_smart_save.should == true
|
69
|
+
|
70
|
+
mbike.unsaved_changes?.should == false
|
71
|
+
mbike.wheels = 3
|
72
|
+
mbike.unsaved_changes?.should == true
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should know if an object has unsaved for an object where the instance is forced into smart save mode" do
|
77
|
+
response = HTTPResponse.new(@normal_content_motor_bike)
|
78
|
+
|
79
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
80
|
+
|
81
|
+
mbike = MotorBike.get_with_smart_save("123BAC", "foo")
|
82
|
+
mbike.id.should == "123BAC"
|
83
|
+
mbike.use_smart_save.should == true
|
84
|
+
|
85
|
+
mbike.unsaved_changes?.should == false
|
86
|
+
mbike.wheels = 3
|
87
|
+
mbike.unsaved_changes?.should == true
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should save an object that does not unsaved changes if it hasn't activated smart_save" do
|
92
|
+
response = HTTPResponse.new(@normal_content_motor_bike)
|
93
|
+
|
94
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
95
|
+
@db.should_receive(:put).and_return(@document_response)
|
96
|
+
|
97
|
+
mbike = MotorBike.get_by_id("123BAC", "foo")
|
98
|
+
mbike.use_smart_save.should == false
|
99
|
+
|
100
|
+
# unsaved_changes should always be true for classes that don't have
|
101
|
+
# smart_save activated
|
102
|
+
mbike.unsaved_changes?.should == true
|
103
|
+
mbike.save
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should not save an object that does not have unsaved changes" do
|
108
|
+
response = HTTPResponse.new(@content_motor_bike)
|
109
|
+
|
110
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
111
|
+
@db.should_not_receive(:put)
|
112
|
+
|
113
|
+
mbike = OtherMotorBike.get_by_id("123BAC", "foo")
|
114
|
+
|
115
|
+
mbike.unsaved_changes?.should == false
|
116
|
+
mbike.save
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should not have unsaved_changes after having been saved" do
|
121
|
+
response = HTTPResponse.new(@content_motor_bike)
|
122
|
+
|
123
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
124
|
+
@db.should_receive(:put).and_return(@document_response)
|
125
|
+
|
126
|
+
mbike = OtherMotorBike.get_by_id("123BAC", "foo")
|
127
|
+
|
128
|
+
mbike.unsaved_changes?.should == false
|
129
|
+
mbike.wheels = 3
|
130
|
+
mbike.unsaved_changes?.should == true
|
131
|
+
mbike.save
|
132
|
+
mbike.unsaved_changes?.should == false
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should only save relations that need to be saved" do
|
137
|
+
|
138
|
+
response = HTTPResponse.new(@apartment_building_content)
|
139
|
+
response_relation = HTTPResponse.new(@apartment_building_inhabitants)
|
140
|
+
|
141
|
+
CouchObject::Database.should_receive(:open).exactly(3).and_return(@db)
|
142
|
+
|
143
|
+
@db.should_receive(:get).with("foo").and_return(response)
|
144
|
+
|
145
|
+
# has_many relations are loaded
|
146
|
+
@db.should_receive(:get).
|
147
|
+
with("_view/couch_object_has_many_relations/related_documents?" + \
|
148
|
+
"key=[%22A26EDC59D99D50C2CB2615404D357E49%22,%22inhabitants%22]").
|
149
|
+
and_return(response_relation)
|
150
|
+
|
151
|
+
@db.should_receive(:put).once.and_return(@document_response)
|
152
|
+
|
153
|
+
|
154
|
+
apartment_building = OtherApartmentBuilding.get_by_id("foo")
|
155
|
+
apartment_building.location.should_not == nil
|
156
|
+
|
157
|
+
# The content should be loaded on first request!
|
158
|
+
apartment_building.inhabitants.size.should == 2
|
159
|
+
apartment_building.inhabitants.first.change
|
160
|
+
apartment_building.inhabitants.first.unsaved_changes?.should == true
|
161
|
+
apartment_building.inhabitants.last.unsaved_changes?.should == false
|
162
|
+
apartment_building.unsaved_changes?.should == false
|
163
|
+
apartment_building.save
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
it "a class in a belongs_to relationship should notice if its parent changes" do
|
168
|
+
|
169
|
+
response = HTTPResponse.new(@apartment_building_content)
|
170
|
+
response_relation = HTTPResponse.new(@apartment_building_inhabitants)
|
171
|
+
|
172
|
+
CouchObject::Database.should_receive(:open).exactly(4).and_return(@db)
|
173
|
+
|
174
|
+
@db.should_receive(:get).with("foo").and_return(response)
|
175
|
+
|
176
|
+
# has_many relations are loaded
|
177
|
+
@db.should_receive(:get).
|
178
|
+
with("_view/couch_object_has_many_relations/related_documents?" + \
|
179
|
+
"key=[%22A26EDC59D99D50C2CB2615404D357E49%22,%22inhabitants%22]").
|
180
|
+
and_return(response_relation)
|
181
|
+
|
182
|
+
# For the second apartment building
|
183
|
+
@db.should_receive(:post).once.and_return(@document_response)
|
184
|
+
# And it's inhabitant which should be updated with the new parent
|
185
|
+
@db.should_receive(:put).once.and_return(@document_response)
|
186
|
+
|
187
|
+
apartment_building = OtherApartmentBuilding.get_by_id("foo")
|
188
|
+
second_apartment_building = OtherApartmentBuilding.new
|
189
|
+
second_apartment_building.unsaved_changes?.should == true
|
190
|
+
|
191
|
+
# The content should be loaded on first request!
|
192
|
+
apartment_building.inhabitants.size.should == 2
|
193
|
+
apartment_building.inhabitants.first.unsaved_changes?.should == false
|
194
|
+
apartment_building.inhabitants.last.unsaved_changes?.should == false
|
195
|
+
apartment_building.unsaved_changes?.should == false
|
196
|
+
|
197
|
+
second_apartment_building.inhabitants << apartment_building.inhabitants.first
|
198
|
+
second_apartment_building.inhabitants.size.should == 1
|
199
|
+
apartment_building.inhabitants.size.should == 1
|
200
|
+
apartment_building.inhabitants.first.unsaved_changes?.should == false
|
201
|
+
second_apartment_building.inhabitants.first.unsaved_changes?.should == true
|
202
|
+
|
203
|
+
# Should not save anything at all...
|
204
|
+
apartment_building.save
|
205
|
+
|
206
|
+
# Should save both documents
|
207
|
+
second_apartment_building.save
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/persistable_helper.rb'
|
2
|
+
|
3
|
+
describe CouchObject::Persistable, "for loading objects:" do
|
4
|
+
before(:each) do
|
5
|
+
@bike = Bike.new
|
6
|
+
@with_location = WithStorageLocation.new
|
7
|
+
|
8
|
+
@db = mock("mock db")
|
9
|
+
|
10
|
+
@content_motor_bike = %{
|
11
|
+
{
|
12
|
+
"_id":"123BAC",
|
13
|
+
"_rev":"946B7D1C",
|
14
|
+
"class":"OtherMotorBike",
|
15
|
+
"attributes":
|
16
|
+
{
|
17
|
+
"wheels":2
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
@normal_content_motor_bike = %{
|
23
|
+
{
|
24
|
+
"_id":"123BAC",
|
25
|
+
"_rev":"946B7D1C",
|
26
|
+
"class":"MotorBike",
|
27
|
+
"attributes":
|
28
|
+
{
|
29
|
+
"wheels":2
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
content = HTTPResponse.new(JSON.unparse({
|
35
|
+
"_id" => "123BAC",
|
36
|
+
"_rev" => "946B7D1C",
|
37
|
+
}))
|
38
|
+
@document_response = CouchObject::Response.new(content)
|
39
|
+
|
40
|
+
@apartment_building_content = %{ {"_id":"A26EDC59D99D50C2CB2615404D357E49","_rev":"1756574922","class":"OtherApartmentBuilding","attributes":{}}
|
41
|
+
}
|
42
|
+
|
43
|
+
@apartment_building_inhabitants = %{{"total_rows":2,"offset":0,"rows":[{"id":"241757E4D7D2272C78048B4007399837","key":["12A64B5156002BFD66F23F559C5AD5FA","inhabitants"],"value":{"_id":"241757E4D7D2272C78048B4007399837","_rev":"2508041460","class":"OtherInhabitant","attributes":{},"belongs_to":{"inhabitants":"A26EDC59D99D50C2CB2615404D357E49"}}},{"id":"E94C93DEDB94BFC30B9AB396D4874D52","key":["12A64B5156002BFD66F23F559C5AD5FA","inhabitants"],"value":{"_id":"E94C93DEDB94BFC30B9AB396D4874D52","_rev":"960098874","class":"OtherInhabitant","attributes":{},"belongs_to":{"inhabitants":"A26EDC59D99D50C2CB2615404D357E49"}}}]}
|
44
|
+
}
|
45
|
+
|
46
|
+
CouchObject::Database.stub!(:open).and_return(@db)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return true for new objects" do
|
50
|
+
mbike = OtherMotorBike.new
|
51
|
+
mbike.unsaved_changes?.should == true
|
52
|
+
mbike.use_smart_save.should == true
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return true for new objects that haven't activated the smart save feature" do
|
56
|
+
mbike = MotorBike.new
|
57
|
+
mbike.unsaved_changes?.should == true
|
58
|
+
mbike.use_smart_save.should == false
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should know if an object has unsaved changes" do
|
62
|
+
response = HTTPResponse.new(@content_motor_bike)
|
63
|
+
|
64
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
65
|
+
|
66
|
+
mbike = MotorBike.get_by_id("123BAC", "foo")
|
67
|
+
mbike.id.should == "123BAC"
|
68
|
+
mbike.use_smart_save.should == true
|
69
|
+
|
70
|
+
mbike.unsaved_changes?.should == false
|
71
|
+
mbike.wheels = 3
|
72
|
+
mbike.unsaved_changes?.should == true
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should know if an object has unsaved for an object where the instance is forced into smart save mode" do
|
77
|
+
response = HTTPResponse.new(@normal_content_motor_bike)
|
78
|
+
|
79
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
80
|
+
|
81
|
+
mbike = MotorBike.get_with_smart_save("123BAC", "foo")
|
82
|
+
mbike.id.should == "123BAC"
|
83
|
+
mbike.use_smart_save.should == true
|
84
|
+
|
85
|
+
mbike.unsaved_changes?.should == false
|
86
|
+
mbike.wheels = 3
|
87
|
+
mbike.unsaved_changes?.should == true
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should save an object that does not unsaved changes if it hasn't activated smart_save" do
|
92
|
+
response = HTTPResponse.new(@normal_content_motor_bike)
|
93
|
+
|
94
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
95
|
+
@db.should_receive(:put).and_return(@document_response)
|
96
|
+
|
97
|
+
mbike = MotorBike.get_by_id("123BAC", "foo")
|
98
|
+
mbike.use_smart_save.should == false
|
99
|
+
|
100
|
+
# unsaved_changes should always be true for classes that don't have
|
101
|
+
# smart_save activated
|
102
|
+
mbike.unsaved_changes?.should == true
|
103
|
+
mbike.save
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should not save an object that does not have unsaved changes" do
|
108
|
+
response = HTTPResponse.new(@content_motor_bike)
|
109
|
+
|
110
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
111
|
+
@db.should_not_receive(:put)
|
112
|
+
|
113
|
+
mbike = OtherMotorBike.get_by_id("123BAC", "foo")
|
114
|
+
|
115
|
+
mbike.unsaved_changes?.should == false
|
116
|
+
mbike.save
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should not have unsaved_changes after having been saved" do
|
121
|
+
response = HTTPResponse.new(@content_motor_bike)
|
122
|
+
|
123
|
+
@db.should_receive(:get).with("123BAC").and_return(response)
|
124
|
+
@db.should_receive(:put).and_return(@document_response)
|
125
|
+
|
126
|
+
mbike = OtherMotorBike.get_by_id("123BAC", "foo")
|
127
|
+
|
128
|
+
mbike.unsaved_changes?.should == false
|
129
|
+
mbike.wheels = 3
|
130
|
+
mbike.unsaved_changes?.should == true
|
131
|
+
mbike.save
|
132
|
+
mbike.unsaved_changes?.should == false
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should only save relations that need to be saved" do
|
137
|
+
|
138
|
+
response = HTTPResponse.new(@apartment_building_content)
|
139
|
+
response_relation = HTTPResponse.new(@apartment_building_inhabitants)
|
140
|
+
|
141
|
+
CouchObject::Database.should_receive(:open).exactly(3).and_return(@db)
|
142
|
+
|
143
|
+
@db.should_receive(:get).with("foo").and_return(response)
|
144
|
+
|
145
|
+
# has_many relations are loaded
|
146
|
+
@db.should_receive(:get).
|
147
|
+
with("_view/couch_object_has_many_relations/related_documents?" + \
|
148
|
+
"key=[%22A26EDC59D99D50C2CB2615404D357E49%22,%22inhabitants%22]").
|
149
|
+
and_return(response_relation)
|
150
|
+
|
151
|
+
@db.should_receive(:put).once.and_return(@document_response)
|
152
|
+
|
153
|
+
|
154
|
+
apartment_building = OtherApartmentBuilding.get_by_id("foo")
|
155
|
+
apartment_building.location.should_not == nil
|
156
|
+
|
157
|
+
# The content should be loaded on first request!
|
158
|
+
apartment_building.inhabitants.size.should == 2
|
159
|
+
apartment_building.inhabitants.first.change
|
160
|
+
apartment_building.inhabitants.first.unsaved_changes?.should == true
|
161
|
+
apartment_building.inhabitants.last.unsaved_changes?.should == false
|
162
|
+
apartment_building.unsaved_changes?.should == false
|
163
|
+
apartment_building.save
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
it "a class in a belongs_to relationship should notice if its parent changes" do
|
168
|
+
|
169
|
+
response = HTTPResponse.new(@apartment_building_content)
|
170
|
+
response_relation = HTTPResponse.new(@apartment_building_inhabitants)
|
171
|
+
|
172
|
+
CouchObject::Database.should_receive(:open).exactly(4).and_return(@db)
|
173
|
+
|
174
|
+
@db.should_receive(:get).with("foo").and_return(response)
|
175
|
+
|
176
|
+
# has_many relations are loaded
|
177
|
+
@db.should_receive(:get).
|
178
|
+
with("_view/couch_object_has_many_relations/related_documents?" + \
|
179
|
+
"key=[%22A26EDC59D99D50C2CB2615404D357E49%22,%22inhabitants%22]").
|
180
|
+
and_return(response_relation)
|
181
|
+
|
182
|
+
# For the second apartment building
|
183
|
+
@db.should_receive(:post).once.and_return(@document_response)
|
184
|
+
# And it's inhabitant which should be updated with the new parent
|
185
|
+
@db.should_receive(:put).once.and_return(@document_response)
|
186
|
+
|
187
|
+
apartment_building = OtherApartmentBuilding.get_by_id("foo")
|
188
|
+
second_apartment_building = OtherApartmentBuilding.new
|
189
|
+
second_apartment_building.unsaved_changes?.should == true
|
190
|
+
|
191
|
+
# The content should be loaded on first request!
|
192
|
+
apartment_building.inhabitants.size.should == 2
|
193
|
+
apartment_building.inhabitants.first.unsaved_changes?.should == false
|
194
|
+
apartment_building.inhabitants.last.unsaved_changes?.should == false
|
195
|
+
apartment_building.unsaved_changes?.should == false
|
196
|
+
|
197
|
+
second_apartment_building.inhabitants << apartment_building.inhabitants.first
|
198
|
+
second_apartment_building.inhabitants.size.should == 1
|
199
|
+
apartment_building.inhabitants.size.should == 1
|
200
|
+
apartment_building.inhabitants.first.unsaved_changes?.should == false
|
201
|
+
second_apartment_building.inhabitants.first.unsaved_changes?.should == true
|
202
|
+
|
203
|
+
# Should not save anything at all...
|
204
|
+
apartment_building.save
|
205
|
+
|
206
|
+
# Should save both documents
|
207
|
+
second_apartment_building.save
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|