deferred_associations 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGELOG +5 -0
- data/Rakefile +27 -27
- data/Readme.markdown +84 -84
- data/deferred_associations.gemspec +61 -61
- data/init.rb +1 -1
- data/lib/has_and_belongs_to_many_with_deferred_save.rb +142 -142
- data/lib/has_many_with_deferred_save.rb +3 -3
- data/spec/db/database.yml +21 -21
- data/spec/db/schema.rb +40 -40
- data/spec/has_and_belongs_to_many_with_deferred_save_spec.rb +244 -236
- data/spec/models/door.rb +3 -3
- data/spec/models/person.rb +15 -15
- data/spec/models/room.rb +51 -51
- data/spec/spec_helper.rb +46 -46
- metadata +3 -9
@@ -1,236 +1,244 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require 'has_and_belongs_to_many_with_deferred_save'
|
3
|
-
|
4
|
-
describe "has_and_belongs_to_many_with_deferred_save" do
|
5
|
-
describe "room maximum_occupancy" do
|
6
|
-
before :all do
|
7
|
-
@people = []
|
8
|
-
@people << Person.create(:name => 'Filbert')
|
9
|
-
@people << Person.create(:name => 'Miguel')
|
10
|
-
@people << Person.create(:name => 'Rainer')
|
11
|
-
@room = Room.new(:maximum_occupancy => 2)
|
12
|
-
end
|
13
|
-
after :all do
|
14
|
-
Person.delete_all
|
15
|
-
Room.delete_all
|
16
|
-
end
|
17
|
-
|
18
|
-
it "passes initial checks" do
|
19
|
-
Room .count.should == 0
|
20
|
-
Person.count.should == 3
|
21
|
-
|
22
|
-
@room.people.should == []
|
23
|
-
@room.people_without_deferred_save.should == []
|
24
|
-
@room.people_without_deferred_save.object_id.should_not ==
|
25
|
-
@room.unsaved_people.object_id
|
26
|
-
end
|
27
|
-
|
28
|
-
it "after adding people to room, it should not have saved anything to the database" do
|
29
|
-
@room.people << @people[0]
|
30
|
-
@room.people << @people[1]
|
31
|
-
|
32
|
-
# Still not saved to the association table!
|
33
|
-
Room.count_by_sql("select count(*) from people_rooms").should == 0
|
34
|
-
@room.people_without_deferred_save.size. should == 0
|
35
|
-
end
|
36
|
-
|
37
|
-
it "but room.people.size should still report the current size of 2" do
|
38
|
-
@room.people.size.should == 2 # 2 because this looks at unsaved_people and not at the database
|
39
|
-
end
|
40
|
-
|
41
|
-
it "after saving the model, the association should be saved in the join table" do
|
42
|
-
@room.save # Only here is it actually saved to the association table!
|
43
|
-
@room.errors.full_messages.should == []
|
44
|
-
Room.count_by_sql("select count(*) from people_rooms").should == 2
|
45
|
-
@room.people.size. should == 2
|
46
|
-
@room.people_without_deferred_save.size. should == 2
|
47
|
-
end
|
48
|
-
|
49
|
-
it "when we try to add a 3rd person, it should add a validation error to the errors object like any other validation error" do
|
50
|
-
lambda { @room.people << @people[2] }.should_not raise_error
|
51
|
-
@room.people.size. should == 3
|
52
|
-
|
53
|
-
Room.count_by_sql("select count(*) from people_rooms").should == 2
|
54
|
-
@room.valid?
|
55
|
-
@room.get_error(:people).should == "This room has reached its maximum occupancy"
|
56
|
-
@room.people.size. should == 3 # Just like with normal attributes that fail validation... the attribute still contains the invalid data but we refuse to save until it is changed to something that is *valid*.
|
57
|
-
end
|
58
|
-
|
59
|
-
it "when we try to save, it should fail, because room.people is still invalid" do
|
60
|
-
@room.save.should == false
|
61
|
-
Room.count_by_sql("select count(*) from people_rooms").should == 2 # It's still not there, because it didn't pass the validation.
|
62
|
-
@room.get_error(:people).should == "This room has reached its maximum occupancy"
|
63
|
-
@room.people.size. should == 3
|
64
|
-
@people.map {|p| p.reload; p.rooms.size}.should == [1, 1, 0]
|
65
|
-
end
|
66
|
-
|
67
|
-
it "when we reload, it should go back to only having 2 people in the room" do
|
68
|
-
@room.reload
|
69
|
-
@room.people.size. should == 2
|
70
|
-
@room.people_without_deferred_save.size. should == 2
|
71
|
-
@people.map {|p| p.reload; p.rooms.size}. should == [1, 1, 0]
|
72
|
-
end
|
73
|
-
|
74
|
-
it "if they try to go around our accessors and use the original accessors, then (and only then) will the exception be raised in before_adding_person..." do
|
75
|
-
lambda do
|
76
|
-
@room.people_without_deferred_save << @people[2]
|
77
|
-
end.should raise_error(RuntimeError)
|
78
|
-
end
|
79
|
-
|
80
|
-
it "lets you bypass the validation on Room if we add the association from the other side (person.rooms <<)?" do
|
81
|
-
@people[2].rooms << @room
|
82
|
-
@people[2].rooms.size.should == 1
|
83
|
-
|
84
|
-
# Adding it from one direction does not add it to the other object's association (@room.people), so the validation passes.
|
85
|
-
@room.reload.people.size.should == 2
|
86
|
-
@people[2].valid?
|
87
|
-
@people[2].errors.full_messages.should == []
|
88
|
-
@people[2].save.should == true
|
89
|
-
|
90
|
-
# It is only after reloading that @room.people has this 3rd object, causing it to be invalid, and by then it's too late to do anything about it.
|
91
|
-
@room.reload.people.size.should == 3
|
92
|
-
@room.valid?.should == false
|
93
|
-
end
|
94
|
-
|
95
|
-
it "only if you add the validation to both sides, can you ensure that the size of the association does not exceed some limit" do
|
96
|
-
@room.reload.people.size.should == 3
|
97
|
-
@room.people.delete(@people[2])
|
98
|
-
@room.save.should == true
|
99
|
-
@room.reload.people.size.should == 2
|
100
|
-
@people[2].reload.rooms.size.should == 0
|
101
|
-
|
102
|
-
obj = @people[2]
|
103
|
-
obj.do_extra_validation = true
|
104
|
-
|
105
|
-
@people[2].rooms << @room
|
106
|
-
@people[2].rooms.size.should == 1
|
107
|
-
|
108
|
-
@room.reload.people.size.should == 2
|
109
|
-
@people[2].valid?.should be_false
|
110
|
-
@people[2].get_error(:rooms).should == "This room has reached its maximum occupancy"
|
111
|
-
@room.reload.people.size.should == 2
|
112
|
-
end
|
113
|
-
|
114
|
-
it "still lets you do find" do
|
115
|
-
if ar4?
|
116
|
-
@room.people2.where(:name => 'Filbert').first.should == @people[0]
|
117
|
-
@room.people_without_deferred_save.where(:name => 'Filbert').first.should == @people[0]
|
118
|
-
@room.people.where(:name => 'Filbert').first.should == @people[0]
|
119
|
-
else
|
120
|
-
@room.people2. find(:first, :conditions => {:name => 'Filbert'}).should == @people[0]
|
121
|
-
@room.people_without_deferred_save.find(:first, :conditions => {:name => 'Filbert'}).should == @people[0]
|
122
|
-
@room.people2.first(:conditions => {:name => 'Filbert'}).should == @people[0]
|
123
|
-
@room.people_without_deferred_save.first(:conditions => {:name => 'Filbert'}).should == @people[0]
|
124
|
-
|
125
|
-
@room.people.find(:first, :conditions => {:name => 'Filbert'}).should == @people[0]
|
126
|
-
@room.people.first(:conditions => {:name => 'Filbert'}). should == @people[0]
|
127
|
-
@room.people.last(:conditions => {:name => 'Filbert'}). should == @people[0]
|
128
|
-
end
|
129
|
-
|
130
|
-
@room.people.first. should == @people[0]
|
131
|
-
@room.people.last. should == @people[1] # @people[2] was removed before
|
132
|
-
@room.people.find_by_name('Filbert'). should == @people[0]
|
133
|
-
@room.people_without_deferred_save.find_by_name('Filbert').should == @people[0]
|
134
|
-
end
|
135
|
-
|
136
|
-
it "should be dumpable with Marshal" do
|
137
|
-
lambda { Marshal.dump(@room.people) }.should_not raise_exception
|
138
|
-
lambda { Marshal.dump(Room.new.people) }.should_not raise_exception
|
139
|
-
end
|
140
|
-
|
141
|
-
it "should detect difference in association" do
|
142
|
-
@room = Room.find(@room.id)
|
143
|
-
@room.bs_diff_before_module.should be_nil
|
144
|
-
@room.bs_diff_after_module.should be_nil
|
145
|
-
@room.bs_diff_method.should be_nil
|
146
|
-
|
147
|
-
@room.people.size.should == 2
|
148
|
-
@room.people = [@room.people[0]]
|
149
|
-
@room.save.should be_true
|
150
|
-
|
151
|
-
@room.bs_diff_before_module.should be_true
|
152
|
-
@room.bs_diff_after_module.should be_true
|
153
|
-
if ar2?
|
154
|
-
@room.bs_diff_method.should be_true
|
155
|
-
else
|
156
|
-
@room.bs_diff_method.should be_nil # Rails 3.2: nil (before_save filter is not supported)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
it "should act like original habtm when using ID array with array manipulation" do
|
161
|
-
@room = Room.find(@room.id)
|
162
|
-
@room.people = [@people[0]]
|
163
|
-
@room.save
|
164
|
-
@room = Room.find(@room.id) # we don't want to let id and object setters interfere with each other
|
165
|
-
@room.people2_ids << @people[1].id
|
166
|
-
@room.people2_ids.should == [@people[0].id] # ID array manipulation is ignored
|
167
|
-
|
168
|
-
@room.person_ids.size.should == 1
|
169
|
-
@room.person_ids << @people[1].id
|
170
|
-
@room.person_ids.should == [@people[0].id]
|
171
|
-
Room.find(@room.id).person_ids.should == [@people[0].id]
|
172
|
-
@room.save.should be_true
|
173
|
-
Room.find(@room.id).person_ids.should == [@people[0].id] # ID array manipulation is ignored, too
|
174
|
-
end
|
175
|
-
|
176
|
-
it "should work with id setters" do
|
177
|
-
@room = Room.find(@room.id)
|
178
|
-
@room.people = [@people[0], @people[1]]
|
179
|
-
@room.save
|
180
|
-
@room = Room.find(@room.id)
|
181
|
-
@room.person_ids.should == [@people[0].id, @people[1].id]
|
182
|
-
@room.person_ids = [@people[1].id]
|
183
|
-
@room.person_ids.should == [@people[1].id]
|
184
|
-
Room.find(@room.id).person_ids.should == [@people[0].id,@people[1].id]
|
185
|
-
@room.save.should be_true
|
186
|
-
Room.find(@room.id).person_ids.should == [@people[1].id]
|
187
|
-
end
|
188
|
-
|
189
|
-
it "should work with multiple id setters and object setters" do
|
190
|
-
@room = Room.find(@room.id)
|
191
|
-
@room.people = [@people[0]]
|
192
|
-
@room.person_ids = [@people[0].id, @people[1].id]
|
193
|
-
@room.people = [@people[1]]
|
194
|
-
@room.person_ids = [@people[0].id, @people[1].id]
|
195
|
-
@room.people = [@people[1]]
|
196
|
-
@room.save
|
197
|
-
@room = Room.find(@room.id)
|
198
|
-
@room.people.should == [@people[1]]
|
199
|
-
end
|
200
|
-
|
201
|
-
it "should give klass in AR 3/4" do
|
202
|
-
unless ar2?
|
203
|
-
@room.people.klass.should == Person
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
it "should give aliased_table_name in AR 2.3" do
|
208
|
-
if ar2?
|
209
|
-
@room.people.aliased_table_name.should == "people"
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
@
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
@
|
227
|
-
@door.
|
228
|
-
end
|
229
|
-
|
230
|
-
it "
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
end
|
1
|
+
require "spec_helper"
|
2
|
+
require 'has_and_belongs_to_many_with_deferred_save'
|
3
|
+
|
4
|
+
describe "has_and_belongs_to_many_with_deferred_save" do
|
5
|
+
describe "room maximum_occupancy" do
|
6
|
+
before :all do
|
7
|
+
@people = []
|
8
|
+
@people << Person.create(:name => 'Filbert')
|
9
|
+
@people << Person.create(:name => 'Miguel')
|
10
|
+
@people << Person.create(:name => 'Rainer')
|
11
|
+
@room = Room.new(:maximum_occupancy => 2)
|
12
|
+
end
|
13
|
+
after :all do
|
14
|
+
Person.delete_all
|
15
|
+
Room.delete_all
|
16
|
+
end
|
17
|
+
|
18
|
+
it "passes initial checks" do
|
19
|
+
Room .count.should == 0
|
20
|
+
Person.count.should == 3
|
21
|
+
|
22
|
+
@room.people.should == []
|
23
|
+
@room.people_without_deferred_save.should == []
|
24
|
+
@room.people_without_deferred_save.object_id.should_not ==
|
25
|
+
@room.unsaved_people.object_id
|
26
|
+
end
|
27
|
+
|
28
|
+
it "after adding people to room, it should not have saved anything to the database" do
|
29
|
+
@room.people << @people[0]
|
30
|
+
@room.people << @people[1]
|
31
|
+
|
32
|
+
# Still not saved to the association table!
|
33
|
+
Room.count_by_sql("select count(*) from people_rooms").should == 0
|
34
|
+
@room.people_without_deferred_save.size. should == 0
|
35
|
+
end
|
36
|
+
|
37
|
+
it "but room.people.size should still report the current size of 2" do
|
38
|
+
@room.people.size.should == 2 # 2 because this looks at unsaved_people and not at the database
|
39
|
+
end
|
40
|
+
|
41
|
+
it "after saving the model, the association should be saved in the join table" do
|
42
|
+
@room.save # Only here is it actually saved to the association table!
|
43
|
+
@room.errors.full_messages.should == []
|
44
|
+
Room.count_by_sql("select count(*) from people_rooms").should == 2
|
45
|
+
@room.people.size. should == 2
|
46
|
+
@room.people_without_deferred_save.size. should == 2
|
47
|
+
end
|
48
|
+
|
49
|
+
it "when we try to add a 3rd person, it should add a validation error to the errors object like any other validation error" do
|
50
|
+
lambda { @room.people << @people[2] }.should_not raise_error
|
51
|
+
@room.people.size. should == 3
|
52
|
+
|
53
|
+
Room.count_by_sql("select count(*) from people_rooms").should == 2
|
54
|
+
@room.valid?
|
55
|
+
@room.get_error(:people).should == "This room has reached its maximum occupancy"
|
56
|
+
@room.people.size. should == 3 # Just like with normal attributes that fail validation... the attribute still contains the invalid data but we refuse to save until it is changed to something that is *valid*.
|
57
|
+
end
|
58
|
+
|
59
|
+
it "when we try to save, it should fail, because room.people is still invalid" do
|
60
|
+
@room.save.should == false
|
61
|
+
Room.count_by_sql("select count(*) from people_rooms").should == 2 # It's still not there, because it didn't pass the validation.
|
62
|
+
@room.get_error(:people).should == "This room has reached its maximum occupancy"
|
63
|
+
@room.people.size. should == 3
|
64
|
+
@people.map {|p| p.reload; p.rooms.size}.should == [1, 1, 0]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "when we reload, it should go back to only having 2 people in the room" do
|
68
|
+
@room.reload
|
69
|
+
@room.people.size. should == 2
|
70
|
+
@room.people_without_deferred_save.size. should == 2
|
71
|
+
@people.map {|p| p.reload; p.rooms.size}. should == [1, 1, 0]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "if they try to go around our accessors and use the original accessors, then (and only then) will the exception be raised in before_adding_person..." do
|
75
|
+
lambda do
|
76
|
+
@room.people_without_deferred_save << @people[2]
|
77
|
+
end.should raise_error(RuntimeError)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "lets you bypass the validation on Room if we add the association from the other side (person.rooms <<)?" do
|
81
|
+
@people[2].rooms << @room
|
82
|
+
@people[2].rooms.size.should == 1
|
83
|
+
|
84
|
+
# Adding it from one direction does not add it to the other object's association (@room.people), so the validation passes.
|
85
|
+
@room.reload.people.size.should == 2
|
86
|
+
@people[2].valid?
|
87
|
+
@people[2].errors.full_messages.should == []
|
88
|
+
@people[2].save.should == true
|
89
|
+
|
90
|
+
# It is only after reloading that @room.people has this 3rd object, causing it to be invalid, and by then it's too late to do anything about it.
|
91
|
+
@room.reload.people.size.should == 3
|
92
|
+
@room.valid?.should == false
|
93
|
+
end
|
94
|
+
|
95
|
+
it "only if you add the validation to both sides, can you ensure that the size of the association does not exceed some limit" do
|
96
|
+
@room.reload.people.size.should == 3
|
97
|
+
@room.people.delete(@people[2])
|
98
|
+
@room.save.should == true
|
99
|
+
@room.reload.people.size.should == 2
|
100
|
+
@people[2].reload.rooms.size.should == 0
|
101
|
+
|
102
|
+
obj = @people[2]
|
103
|
+
obj.do_extra_validation = true
|
104
|
+
|
105
|
+
@people[2].rooms << @room
|
106
|
+
@people[2].rooms.size.should == 1
|
107
|
+
|
108
|
+
@room.reload.people.size.should == 2
|
109
|
+
@people[2].valid?.should be_false
|
110
|
+
@people[2].get_error(:rooms).should == "This room has reached its maximum occupancy"
|
111
|
+
@room.reload.people.size.should == 2
|
112
|
+
end
|
113
|
+
|
114
|
+
it "still lets you do find" do
|
115
|
+
if ar4?
|
116
|
+
@room.people2.where(:name => 'Filbert').first.should == @people[0]
|
117
|
+
@room.people_without_deferred_save.where(:name => 'Filbert').first.should == @people[0]
|
118
|
+
@room.people.where(:name => 'Filbert').first.should == @people[0]
|
119
|
+
else
|
120
|
+
@room.people2. find(:first, :conditions => {:name => 'Filbert'}).should == @people[0]
|
121
|
+
@room.people_without_deferred_save.find(:first, :conditions => {:name => 'Filbert'}).should == @people[0]
|
122
|
+
@room.people2.first(:conditions => {:name => 'Filbert'}).should == @people[0]
|
123
|
+
@room.people_without_deferred_save.first(:conditions => {:name => 'Filbert'}).should == @people[0]
|
124
|
+
|
125
|
+
@room.people.find(:first, :conditions => {:name => 'Filbert'}).should == @people[0]
|
126
|
+
@room.people.first(:conditions => {:name => 'Filbert'}). should == @people[0]
|
127
|
+
@room.people.last(:conditions => {:name => 'Filbert'}). should == @people[0]
|
128
|
+
end
|
129
|
+
|
130
|
+
@room.people.first. should == @people[0]
|
131
|
+
@room.people.last. should == @people[1] # @people[2] was removed before
|
132
|
+
@room.people.find_by_name('Filbert'). should == @people[0]
|
133
|
+
@room.people_without_deferred_save.find_by_name('Filbert').should == @people[0]
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should be dumpable with Marshal" do
|
137
|
+
lambda { Marshal.dump(@room.people) }.should_not raise_exception
|
138
|
+
lambda { Marshal.dump(Room.new.people) }.should_not raise_exception
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should detect difference in association" do
|
142
|
+
@room = Room.find(@room.id)
|
143
|
+
@room.bs_diff_before_module.should be_nil
|
144
|
+
@room.bs_diff_after_module.should be_nil
|
145
|
+
@room.bs_diff_method.should be_nil
|
146
|
+
|
147
|
+
@room.people.size.should == 2
|
148
|
+
@room.people = [@room.people[0]]
|
149
|
+
@room.save.should be_true
|
150
|
+
|
151
|
+
@room.bs_diff_before_module.should be_true
|
152
|
+
@room.bs_diff_after_module.should be_true
|
153
|
+
if ar2?
|
154
|
+
@room.bs_diff_method.should be_true
|
155
|
+
else
|
156
|
+
@room.bs_diff_method.should be_nil # Rails 3.2: nil (before_save filter is not supported)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should act like original habtm when using ID array with array manipulation" do
|
161
|
+
@room = Room.find(@room.id)
|
162
|
+
@room.people = [@people[0]]
|
163
|
+
@room.save
|
164
|
+
@room = Room.find(@room.id) # we don't want to let id and object setters interfere with each other
|
165
|
+
@room.people2_ids << @people[1].id
|
166
|
+
@room.people2_ids.should == [@people[0].id] # ID array manipulation is ignored
|
167
|
+
|
168
|
+
@room.person_ids.size.should == 1
|
169
|
+
@room.person_ids << @people[1].id
|
170
|
+
@room.person_ids.should == [@people[0].id]
|
171
|
+
Room.find(@room.id).person_ids.should == [@people[0].id]
|
172
|
+
@room.save.should be_true
|
173
|
+
Room.find(@room.id).person_ids.should == [@people[0].id] # ID array manipulation is ignored, too
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should work with id setters" do
|
177
|
+
@room = Room.find(@room.id)
|
178
|
+
@room.people = [@people[0], @people[1]]
|
179
|
+
@room.save
|
180
|
+
@room = Room.find(@room.id)
|
181
|
+
@room.person_ids.should == [@people[0].id, @people[1].id]
|
182
|
+
@room.person_ids = [@people[1].id]
|
183
|
+
@room.person_ids.should == [@people[1].id]
|
184
|
+
Room.find(@room.id).person_ids.should == [@people[0].id,@people[1].id]
|
185
|
+
@room.save.should be_true
|
186
|
+
Room.find(@room.id).person_ids.should == [@people[1].id]
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should work with multiple id setters and object setters" do
|
190
|
+
@room = Room.find(@room.id)
|
191
|
+
@room.people = [@people[0]]
|
192
|
+
@room.person_ids = [@people[0].id, @people[1].id]
|
193
|
+
@room.people = [@people[1]]
|
194
|
+
@room.person_ids = [@people[0].id, @people[1].id]
|
195
|
+
@room.people = [@people[1]]
|
196
|
+
@room.save
|
197
|
+
@room = Room.find(@room.id)
|
198
|
+
@room.people.should == [@people[1]]
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should give klass in AR 3/4" do
|
202
|
+
unless ar2?
|
203
|
+
@room.people.klass.should == Person
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should give aliased_table_name in AR 2.3" do
|
208
|
+
if ar2?
|
209
|
+
@room.people.aliased_table_name.should == "people"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should support reload both with and without params" do
|
214
|
+
# find options are deprecated with AR 4, but reload still
|
215
|
+
# supports them
|
216
|
+
@room.reload.id.should == @room.id
|
217
|
+
with_param = @room.reload(:select => 'id')
|
218
|
+
with_param.id.should == @room.id
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe "doors" do
|
223
|
+
before :all do
|
224
|
+
@rooms = []
|
225
|
+
@rooms << Room.create(:name => 'Kitchen', :maximum_occupancy => 1)
|
226
|
+
@rooms << Room.create(:name => 'Dining room', :maximum_occupancy => 10)
|
227
|
+
@door = Door.new(:name => 'Kitchen-Dining-room door')
|
228
|
+
end
|
229
|
+
|
230
|
+
it "passes initial checks" do
|
231
|
+
Room.count.should == 2
|
232
|
+
Door.count.should == 0
|
233
|
+
|
234
|
+
@door.rooms.should == []
|
235
|
+
@door.rooms_without_deferred_save.should == []
|
236
|
+
end
|
237
|
+
|
238
|
+
it "the association has an include? method" do
|
239
|
+
@door.rooms << @rooms[0]
|
240
|
+
@door.rooms.include?(@rooms[0]).should be_true
|
241
|
+
@door.rooms.include?(@rooms[1]).should be_false
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
data/spec/models/door.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
class Door < ActiveRecord::Base
|
2
|
-
has_and_belongs_to_many_with_deferred_save :rooms
|
3
|
-
end
|
1
|
+
class Door < ActiveRecord::Base
|
2
|
+
has_and_belongs_to_many_with_deferred_save :rooms
|
3
|
+
end
|
data/spec/models/person.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
class Person < ActiveRecord::Base
|
2
|
-
has_and_belongs_to_many_with_deferred_save :rooms, :validate => true
|
3
|
-
|
4
|
-
attr_accessor :do_extra_validation
|
5
|
-
validate :extra_validation, :if => :do_extra_validation
|
6
|
-
|
7
|
-
def extra_validation
|
8
|
-
rooms.each do |room|
|
9
|
-
this_room_unsaved = rooms_without_deferred_save.include?(room) ? 0 : 1
|
10
|
-
if room.people.size + this_room_unsaved > room.maximum_occupancy
|
11
|
-
errors.add :rooms, "This room has reached its maximum occupancy"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
1
|
+
class Person < ActiveRecord::Base
|
2
|
+
has_and_belongs_to_many_with_deferred_save :rooms, :validate => true
|
3
|
+
|
4
|
+
attr_accessor :do_extra_validation
|
5
|
+
validate :extra_validation, :if => :do_extra_validation
|
6
|
+
|
7
|
+
def extra_validation
|
8
|
+
rooms.each do |room|
|
9
|
+
this_room_unsaved = rooms_without_deferred_save.include?(room) ? 0 : 1
|
10
|
+
if room.people.size + this_room_unsaved > room.maximum_occupancy
|
11
|
+
errors.add :rooms, "This room has reached its maximum occupancy"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/spec/models/room.rb
CHANGED
@@ -1,51 +1,51 @@
|
|
1
|
-
class Room < ActiveRecord::Base
|
2
|
-
|
3
|
-
attr_accessor :bs_diff_before_module
|
4
|
-
attr_accessor :bs_diff_after_module
|
5
|
-
attr_accessor :bs_diff_method
|
6
|
-
|
7
|
-
before_save :diff_before_module
|
8
|
-
|
9
|
-
has_and_belongs_to_many_with_deferred_save :people, :before_add => :before_adding_person
|
10
|
-
has_and_belongs_to_many :people2, :class_name => 'Person'
|
11
|
-
has_and_belongs_to_many_with_deferred_save :doors
|
12
|
-
|
13
|
-
has_many_with_deferred_save :tables
|
14
|
-
has_many_with_deferred_save :chairs, :through => :tables #TODO test compatibility with through associations
|
15
|
-
|
16
|
-
before_save :diff_after_module
|
17
|
-
|
18
|
-
validate :people_count
|
19
|
-
|
20
|
-
def people_count
|
21
|
-
if people.size > maximum_occupancy
|
22
|
-
errors.add :people, "This room has reached its maximum occupancy"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Just in case they try to bypass our new accessor and call people_without_deferred_save directly...
|
27
|
-
# (This should never be necessary; it is for demonstration purposes only...)
|
28
|
-
def before_adding_person(person)
|
29
|
-
if self.people_without_deferred_save.size + [person].size > maximum_occupancy
|
30
|
-
raise "There are too many people in this room"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def diff_before_module
|
35
|
-
#should detect the changes
|
36
|
-
self.bs_diff_before_module = (people.size - people_without_deferred_save.size) != 0
|
37
|
-
true
|
38
|
-
end
|
39
|
-
|
40
|
-
def diff_after_module
|
41
|
-
# should not detect the changes
|
42
|
-
self.bs_diff_after_module = (people.size - people_without_deferred_save.size) != 0
|
43
|
-
true
|
44
|
-
end
|
45
|
-
|
46
|
-
def before_save
|
47
|
-
# old_style, should not detect the changes
|
48
|
-
self.bs_diff_method = (people.size - people_without_deferred_save.size) != 0
|
49
|
-
true
|
50
|
-
end
|
51
|
-
end
|
1
|
+
class Room < ActiveRecord::Base
|
2
|
+
|
3
|
+
attr_accessor :bs_diff_before_module
|
4
|
+
attr_accessor :bs_diff_after_module
|
5
|
+
attr_accessor :bs_diff_method
|
6
|
+
|
7
|
+
before_save :diff_before_module
|
8
|
+
|
9
|
+
has_and_belongs_to_many_with_deferred_save :people, :before_add => :before_adding_person
|
10
|
+
has_and_belongs_to_many :people2, :class_name => 'Person'
|
11
|
+
has_and_belongs_to_many_with_deferred_save :doors
|
12
|
+
|
13
|
+
has_many_with_deferred_save :tables
|
14
|
+
has_many_with_deferred_save :chairs, :through => :tables #TODO test compatibility with through associations
|
15
|
+
|
16
|
+
before_save :diff_after_module
|
17
|
+
|
18
|
+
validate :people_count
|
19
|
+
|
20
|
+
def people_count
|
21
|
+
if people.size > maximum_occupancy
|
22
|
+
errors.add :people, "This room has reached its maximum occupancy"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Just in case they try to bypass our new accessor and call people_without_deferred_save directly...
|
27
|
+
# (This should never be necessary; it is for demonstration purposes only...)
|
28
|
+
def before_adding_person(person)
|
29
|
+
if self.people_without_deferred_save.size + [person].size > maximum_occupancy
|
30
|
+
raise "There are too many people in this room"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def diff_before_module
|
35
|
+
#should detect the changes
|
36
|
+
self.bs_diff_before_module = (people.size - people_without_deferred_save.size) != 0
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def diff_after_module
|
41
|
+
# should not detect the changes
|
42
|
+
self.bs_diff_after_module = (people.size - people_without_deferred_save.size) != 0
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def before_save
|
47
|
+
# old_style, should not detect the changes
|
48
|
+
self.bs_diff_method = (people.size - people_without_deferred_save.size) != 0
|
49
|
+
true
|
50
|
+
end
|
51
|
+
end
|