Question about instance_eval

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

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 Gray II

···

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

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

···

On 5/8/06, Pat Maddox <pergesu@gmail.com> wrote:

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

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

···

On 5/8/06, James Edward Gray II <james@grayproductions.net> wrote:

On May 8, 2006, at 3:30 PM, Pat Maddox 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 Gray II

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

···

On 5/8/06, Pat Maddox <pergesu@gmail.com> wrote:

On 5/8/06, James Edward Gray II <james@grayproductions.net> wrote:
> On May 8, 2006, at 3:30 PM, Pat Maddox 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 Gray 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