Forum: Ruby Question about instance_eval

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Pat M. (Guest)
on 2006-05-09 00:31
(Received via mailing list)
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
James G. (Guest)
on 2006-05-09 00:40
(Received via mailing list)
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
Justin B. (Guest)
on 2006-05-09 00:40
(Received via mailing list)
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
Pat M. (Guest)
on 2006-05-09 01:08
(Received via mailing list)
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
Pat M. (Guest)
on 2006-05-09 01:27
(Received via mailing list)
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
This topic is locked and can not be replied to.