deferred_associations 0.5.5 → 0.5.6
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.
- 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
|