<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Moves On Rails: Tag attr_accessor_with_default</title>
    <link>http://www.movesonrails.com/articles/tag/attr_accessor_with_default?tag=attr_accessor_with_default</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>New ways to look at software</description>
    <item>
      <title>attr_accessor_with_default</title>
      <description>&lt;p&gt;What a marvelous feature, but be wary! It can cause some unexpected behavior if you don't know what you are doing.&lt;/p&gt;

&lt;p&gt;This morning we found a rather suspicious bug that lead to unexpected things. Here is an example:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;code&gt;
    class Person ; attr_accessor_with_default :things, {} ; end&lt;br/&gt;
    john = Person.new&lt;br/&gt;
    john.things[:table] = true&lt;br/&gt;
    ...&lt;br/&gt;
    jim = Person.new&lt;br/&gt;
    jim.things =&gt; {:table =&gt; true} # huh??&lt;br/&gt;
    &lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As it would seem attr_accessor_with_default has some problems with collections. Since we are sharing the instance over the entire class. Peter Williams noted this problem several month ago in his &lt;a href="http://pezra.barelyenough.org/blog/2007/09/things-to-be-suspicious-of-attr_accessor_with_default-with-a-collection/"&gt;article&lt;/a&gt; (which we didn't read until it was too late), however the solution he provided still left us with some very undesireable behaviour.&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;code&gt;
    class Person ; attr_accessor_with_default :things, {{}} ; end # note the extra brackets!&lt;br/&gt;
    &lt;br/&gt;&lt;br/&gt;
    john = Person.new&lt;br/&gt;
    john.things[:table] = true&lt;br/&gt;
    &lt;br/&gt;
    ...&lt;br/&gt;
    &lt;br/&gt;
    jim = Person.new&lt;br/&gt;
    jim.things =&gt; {} # okay!&lt;br/&gt;
    john.things =&gt; {} # uhm... not okay!
    &lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The variable would only &lt;em&gt;stick&lt;/em&gt; if we actually assigned it.&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;code&gt;
    john.things = {:table =&gt; true}&lt;br/&gt;
    john.things =&gt; {:table =&gt; true} # yay!
    &lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But doing this every time is not only a pain but also introduces &lt;strong&gt;very&lt;/strong&gt; hard to debug errors, since the assignment does not fail...it just doesn't work!&lt;/p&gt;

&lt;p&gt;We solved it by going old-school. Back to the normal accessor for collections.&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;code&gt;
    class Person &lt;br/&gt;
       attr_accessor :things&lt;br/&gt;
     &lt;br/&gt;
       &amp;nbsp;def initialize attributes=nil&lt;br/&gt;
       &amp;nbsp;&amp;nbsp;super&lt;br/&gt;
       &amp;nbsp;&amp;nbsp;self.things = {}&lt;br/&gt;
       &amp;nbsp;end&lt;br/&gt;
    &lt;br/&gt;
    end
    &lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now the code works as expected and we can use all operators (like &gt;&gt;, []) from the get go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; It seems this had no effect on ActiveRecord objects that were created using finders so here is the fix for any those:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;code&gt;
    class Person &amp;lt; ActiveRecord::Base&lt;br/&gt;
       attr_accessor :things&lt;br/&gt;
     &lt;br/&gt;
       &amp;nbsp;def after_initialize&lt;br/&gt;
       &amp;nbsp;&amp;nbsp;self.things = {}&lt;br/&gt;
       &amp;nbsp;end&lt;br/&gt;
    &lt;br/&gt;
    end
    &lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <pubDate>Wed, 05 Mar 2008 09:37:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:830e2280-fc19-42e0-a443-5cd1b6eb4377</guid>
      <author>andre.foeken@movesonrails.com (Andre Foeken)</author>
      <link>http://www.movesonrails.com/articles/2008/03/05/attr_accessor_with_default</link>
      <category>Rails</category>
      <category>Ruby</category>
      <category>attr_accessor_with_default</category>
      <category>collection</category>
      <category>weird</category>
    </item>
  </channel>
</rss>
