Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I just stumbled onto this question while running into the same problem.</p> <p>For reference, the <a href="http://apidock.com/rails/Module/attr_accessor_with_default" rel="nofollow">docs</a> specify the block form is dynamically evaluated in the instance scope. To continue the example, its usefulness is really quite limited, but at least works the way you might expect:</p> <pre><code>class Container attr_accessor_with_default(:block_collection) { name.underscore } end &gt; c = Container.new(:name =&gt; "TestName") &gt; c.block_collection # =&gt; "test_name" &gt; c.block_collection = "something else" # =&gt; "something else" &gt; c.name =&gt; "TestName" </code></pre> <p>Here's the really quirky part though...</p> <pre><code>class Container attr_accessor_with_default :naive_collection, [0, 0] end # This works as expected &gt; c = Container.new &gt; c.naive_collection = ["foo", "bar"] # =&gt; ["foo", "bar"] &gt; Container.new.naive_collection # =&gt; [0, 0] &gt; c.naive_collection[0] = 0 # =&gt; [0, "bar"] &gt; Container.new.naive_collection # =&gt; [0, 0] # But this doesn't &gt; c2 = Container.new &gt; c2.naive_collection # =&gt; [0, 0] &gt; c2.naive_collection[0] = "problem!" # =&gt; ["problem!", 0] &gt; Container.new.naive_collection # =&gt; ["problem!", 0] </code></pre> <p>Digging into the source a bit, I see that attr_accessor_with_default defines an instance method that returns the default value or executes the block. Which is fine.</p> <p>It then goes on to execute this within a module_eval:</p> <pre><code>def #{sym}=(value) class &lt;&lt; self; attr_reader :#{sym} end @#{sym} = value end </code></pre> <p>Which is just ridiculously convoluted. I may end up ticketing this as a bug if I can't figure out the motivation for this behavior.</p> <p><strong>Update:</strong></p> <p>I managed to figure out what was going wrong here.</p> <pre><code>def attr_accessor_with_default(sym, default = Proc.new) define_method(sym, block_given? ? default : Proc.new { default }) module_eval(&lt;&lt;-EVAL, __FILE__, __LINE__ + 1) def #{sym}=(value) class &lt;&lt; self; attr_accessor :#{sym} end @#{sym} = value end EVAL end </code></pre> <p>Initially, the default value exists as a proc. Once you invoke the setter, the getter and setter methods are overwritten by attr_accessor methods and the instance variable is initialized. The problem is that the default proc in the getter returns the class-level default value. So when you do something like:</p> <pre><code>&gt; c2.naive_collection[0] = "problem!" # =&gt; ["problem!", 0] </code></pre> <p>you're actually changing the default value for the class.</p> <p>I think this method should probably be implemented as:</p> <pre><code>class Module def attr_accessor_with_default(sym, default = Proc.new) module_eval(&lt;&lt;-EVAL, __FILE__, __LINE__ + 1) def #{sym} class &lt;&lt; self; attr_reader :#{sym} end @#{sym} = #{ default.dup } end def #{sym}=(value) class &lt;&lt; self; attr_accessor :#{sym} end @#{sym} = value end EVAL end end </code></pre> <p>I'll ticket it and offer up a patch.</p> <p><strong>Update again:</strong> <a href="https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/6496" rel="nofollow">https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/6496</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload