Question about instance_eval


#1

I’m trying to use instance_eval in a project I’m doing, and I
extracted a very simple example:

class IETest
attr_accessor :foo
end

t = IETest.new
t.instance_eval { self.foo = ‘foo’ }
puts t.foo

This works as expected. However if I do
t.instance_eval { foo = ‘foo’ }

then t.foo => nil

I also know that t.instance_eval { @foo => ‘foo’ } would work in this
case. However, I’m trying to set a Rails attribute, so I have to go
through the method accessor. Is there any way that I can make this
work with just { foo = ‘foo’ } instead of { self.foo = ‘foo’ } ?

Pat


#2

On May 8, 2006, at 3:30 PM, Pat M. wrote:

t.instance_eval { foo = ‘foo’ }

Ruby will always see the above as a local variable declaration.
There is no way around that.

I also know that t.instance_eval { @foo => ‘foo’ } would work in this
case. However, I’m trying to set a Rails attribute, so I have to go
through the method accessor.

You’ve showed one way to handle it. Another is the use
write_attribute(), if we are talking about ActiveRecord.

James Edward G. II


#3

No. Define method missing to dispatch calls to “foo” to the accessor,
and
change your block just a little bit. E.g.

class IETest
def method_misssing(sym, *args, &blk)
# dispatches any methods missing to “assignment” version of method.
self.send(sym + “=”, *args, &blk)
end
end

t = IETest.new
t.instance_eval { foo ‘foo’ } # notice lack of assignment operator
puts t.foo


#4

On 5/8/06, James Edward G. II removed_email_address@domain.invalid wrote:

You’ve showed one way to handle it. Another is the use
write_attribute(), if we are talking about ActiveRecord.

James Edward G. II

Can I call pass in an object to instance_eval? Let me show you the
full class…

class ScenarioGenerator
def initialize
@rules = []
end

def add_rule(&r)
@rules << r
end

def generate
s = Scenario.new
num_players = 0
@rules.each do |r|
r.call(s)
end

s.create_players(num_players) if num_players > 0
s

end
end

The reason I went to r.call(s) is so that I can do
g = ScenarioGenerator.new
g.add_rule { |s| s.sb = 200 }

s then becomes the Scenario that I created.

However I want to be able to modify num_players with a rule, so I need
instance_eval. I still need to be able to pass in the Scenario object
though. How could I do that?

Pat


#5

On 5/8/06, Pat M. removed_email_address@domain.invalid wrote:

through the method accessor.

def generate

Pat

Apparently I can’t do that, so I changed the design up a bit so that I
could do {|s| s.num_opponents = 3}.

Thanks for the help James and Justin, I really appreciate it.

Pat