[rspec-users] [RSpec] Cloning objects and leaking state

Nick Hoffman nick at deadorange.com
Wed Jan 28 12:41:54 EST 2009

On 28/01/2009, at 12:12 PM, Pat Maddox wrote:
> On Wed, Jan 28, 2009 at 8:30 AM, Nick Hoffman <nick at deadorange.com>  
> wrote:
>> On 28/01/2009, at 7:50 AM, Zach Dennis wrote:
>>> On Tue, Jan 27, 2009 at 2:48 PM, Nick Hoffman  
>>> <nick at deadorange.com> wrote:
>>>> G'day folks. I've been beating my head on this one problem for a  
>>>> couple
>>>> of
>>>> hours, and have managed to figure out what's causing it. However,  
>>>> I don't
>>>> understand why it's happening, nor do I know how to solve or get  
>>>> around
>>>> it.
>>>> One of my methods clones an arg, and it seems that doing so  
>>>> causes state
>>>> to
>>>> leak out. I discovered this because changing this:
>>>> new_subtitle = subtitle.clone
>>>> to this:
>>>> new_subtitle = subtitle
>>>> causes the problem to disappear.
>>>> Before we get into the code snippets, are there any known caveats,
>>>> warnings,
>>>> or problems with writing specs that cover the cloning or  
>>>> duplication of
>>>> objects?
>>>> Here's the code, specs, and spec output:
>>>> http://gist.github.com/53482
>>>> As you can see, in the "should clone ..." example, the  
>>>> expectation on
>>>> line
>>>> 24 succeeds, but the same expectation on line 28 fails. After  
>>>> that, the
>>>> same
>>>> expectation fails in the "should not leak state" example.
>>> What does your full SubtitleFile class look like? It looks like  
>>> there
>>> is an issue with how the #subtitles method is storing information.
>>> Since you're using ActiveRecord::BaseWithoutTable there are probably
>>> not going to be any unique primary keys amongst your SubtitleFiles  
>>> to
>>> help differentiate them. So if #subtitles is a has_many, every  
>>> call to
>>> SubtitleFile#subtitles may lookup Subtitles in the exact same way  
>>> w/o
>>> any unique key to use to differentiate which subtitles belong to  
>>> which
>>> subtitle files which would produce the results you are seeing.
>>> Is Subtitle a ActiveRecord::BaseWithoutTable or a real  
>>> ActiveRecord::Base
>>> model?
>> Hi Zach. Subtitle is an ActiveRecord::BaseWithoutTable model; it  
>> does not
>> inherit from ActiveRecord::Base .
>> The SubtitleFile "subtitles" attribute is actually just an Array. I  
>> didn't
>> bother to setup a has_many relationship with Subtitle.
>> SubtitleFile#subtitles is a standard getter method that  
>> ActiveRecord sets up
>> for me.
>> In my app's console, I tested out a has_many relationship between two
>> ActiveRecord::BaseWithoutTable models, and there weren't any mixups  
>> after
>> creating associations between different model instances.
>> Here's the source for the SubtitleFile model. The #add_subtitle! in  
>> question
>> starts on line 74:
>> http://gist.github.com/54028
> I'm not familiar with this library, so I can't say for sure, but the  
> line
> default :subtitles => []
> looks very suspicious to me.
> The underlying library code would have to do a .clone of that default
> value, otherwise all instances will share the same array (meaning if
> you push a value onto it, the next instance will have that array with
> one element).
> If it doesn't automatically clone (it may, I don't know), it probably
> should provide a lambda syntax so you can do:
> default :subtitles => lambda { [] }
> Pat

Pat, the lambda fixed the problem. That's a keen spidey sense you have  

To spell this out in more detail, having
   defaults :subtitles => []
causes the SubtitleFile class to initialise an Array when the class is  
defined. From then on, the "subtitles" attribute of all SubtitleFile  
instances will refer to that one specific array.

Thanks for your help with this, mate. It's much appreciated.

More information about the rspec-users mailing list