# Accessor\_writer methods and instance\_eval

**URL:** <https://www.ruby-forum.com/t/accessor-writer-methods-and-instance-eval/112875>\
**Category:** Ruby\
**Created:** [August 24, 2007, 1:41am UTC](https://www.ruby-forum.com/t/accessor-writer-methods-and-instance-eval/112875 "2007-08-24T01:41:20Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Thomas\_Gantner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/53a042/32.png) [@Thomas\_Gantner](https://www.ruby-forum.com/u/Thomas_Gantner)\
**Post date:** [August 24, 2007, 1:41am UTC](https://www.ruby-forum.com/t/accessor-writer-methods-and-instance-eval/112875/1 "2007-08-24T01:41:20Z")

</div>

Hi

I stumbled upon a problem with ‘instance\_eval’ (using ruby 1.8.5 on  
linux-x86\_64). Simplified code example:

irb:01\> S = Struct.new(:a)  
=\> S  
irb:02\> s = S.new(1)  
=\> #  
irb:03\> s.a  
=\> 1  
irb:04\> s.a = 2  
=\> 2  
irb:05\> s  
=\> #  
irb:06\> s.instance\_eval { puts a }  
2  
=\> nil  
irb:07\> s.instance\_eval { a = 3 }  
=\> 3  
irb:08\> s  
=\> #  
irb:09\> s.instance\_eval { self.a = 3 }  
=\> 3  
irb:10\> s  
=\> #

My problem is in line 07: it seems that the ‘a’ in the block is treated  
as a  
local variable, therefore all the writer-accessor methods (‘a=’) are  
hidden  
within the block. I get the same result when instance\_eval-ing the  
string “a = 3” instead of the block variant.

Is there a way to avoid this behaviour without using ‘self.a’ or passing  
the  
struct as a parameter into the block (which quite obsoletes the meaning  
of  
instance\_eval)?

My real world use of this pattern is using a block with ‘initialize()’:

class C  
def initialize(&blk)  
@format = Struct.new( … many, many elements with default values  
…)  
@format.instance\_eval(&blk)  
end  
end

To explicitly override some default format-values I want to use

c = C.new { elem8 = 8; elem17 = ‘test’; … }

This won’t work as explained above. I know I can use

c = C.new {|format| format.elem8 = 8; format.elem17 = ‘test’; … }

or

c = C.new { self.elem8 = 8; self.elem17 = ‘test’; … }

but both seem somewhat redundant and need too much typing (yeah I know  
I’m  
lazy ;-).

Thanks for any suggestions.

-Thomas

---

<div class="post-metadata">

**Author:** ![Thomas\_Gantner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/53a042/32.png) [@Thomas\_Gantner](https://www.ruby-forum.com/u/Thomas_Gantner)\
**Post date:** [August 24, 2007, 2:47am UTC](https://www.ruby-forum.com/t/accessor-writer-methods-and-instance-eval/112875/2 "2007-08-24T02:47:25Z")

</div>

Hi~

On Aug 23, 2007, at 4:40 PM, Thomas Gantner wrote:

> =\> 1  
> =\> #  
> string “a = 3” instead of the block variant.  
> class C
> 
> lazy ;-).
> 
> Thanks for any suggestions.
> 
> -Thomas
> 
> –  
> \<sig. under construction\>

No unfortunately you are stuck with the behavior you observed.  
Whenever ruby sees ‘a = b’ it assumes it is a local variable  
assignment. This happens at parse time so there is no way to affect  
it at runtime. It’s a tradeoff in order to allow local variables to  
look like method calls and visca versca. So you have to prefix an  
assignment with self. or another object, otherwise it is a local  
variable assignment and you cannot work around it since it happens at  
parse time.

Cheers-  
– Ezra Z.-- Founder & Ruby Hacker  
– removed\_email\_address@domain.invalid  
– Engine Y., Serious Rails Hosting  
– (866) 518-YARD (9273)

---

<div class="post-metadata">

**Author:** ![Thomas\_Gantner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/53a042/32.png) [@Thomas\_Gantner](https://www.ruby-forum.com/u/Thomas_Gantner)\
**Post date:** [August 24, 2007, 3:31am UTC](https://www.ruby-forum.com/t/accessor-writer-methods-and-instance-eval/112875/3 "2007-08-24T03:31:27Z")

</div>

Hi,

At Fri, 24 Aug 2007 08:40:08 +0900,  
Thomas Gantner wrote in [ruby-talk:266021]:

> Is there a way to avoid this behaviour without using ‘self.a’ or passing the  
> struct as a parameter into the block (which quite obsoletes the meaning of  
> instance\_eval)?

Nothing. It’s one of reasons why using instance\_eval for such  
purpose is not a good idea.

---

<div class="post-metadata">

**Author:** ![Thomas\_Gantner](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/53a042/32.png) [@Thomas\_Gantner](https://www.ruby-forum.com/u/Thomas_Gantner)\
**Post date:** [August 25, 2007, 10:42pm UTC](https://www.ruby-forum.com/t/accessor-writer-methods-and-instance-eval/112875/4 "2007-08-25T22:42:18Z")

</div>

on Fri 24. August 2007 03.30, Nobuyoshi N. wrote:

> 

Thanks for your quick answer (also to Ezra).

I found a solution by defining setter-methods for every struct member:

class C  
def initialize(&blk)  
@format = Struct.new( … many, many elements …) do  
members.each do |key|  
self.send(:define\_method, “set\_#{key}”.to\_sym) do |new\_value|  
self[key] = new\_value  
end  
end  
end  
@format.instance\_eval(&blk) if block\_given?  
end  
end

Then I can use:

c = C.new { set\_elem8(8); set\_elem17(‘test’); … }

Quite readable, but not many keystrokes saved. Is there a better  
alternative? I understand you suggest something without instance\_eval()?

-Thomas
