Let's take the following code:
f = Foo.new
f.bars.build
f.bars.empty?
pp f.bars
What do you think will be printed out when we
pp f.bars?Well, if you're like me, you'd think it would return an array with one Bar in it. And, if you were like me, you'd be wrong.
Turns out that the call to
f.bars.empty? doesn't realize you've ever added a new Bar to the collection of bars. Therefore, it will go into the database and do a select count(*) to determine the size of the collection. It will return zero, because at this point you haven't saved anything into the database. Not only is going to the database to determine the size of the collection wrong (in the line above, I've added a Bar though build so empty? should know there's at least one), but empty? in the process is caching the empty collection!Because of this caching, our last line of code here is printing out an empty array. This effectively deletes the original Bar we added via
build.This has to be a bug. In fact, I'm filing a bug at Rails' Trac system.
How do you work around this? Just change your usage of
empty? to length.zero?:
f = Foo.new
f.bars.build
f.bars.length.zero?
pp f.bars
The above code will work just fine!
Many thanks to Wenyi for researching this with me.
0 comments:
Post a Comment