2

I am trying to call a proc on a class but access instance methods from it with an inherited class. I think some mock code will make more sense :)

class Bar
  def self.foo &block
    @foo ||= block
  end
  def foo; self.class.foo.call(); end
  def bar; 'bar'; end
end

class Foo < Bar
  foo do
    bar
  end
end

Foo.new.foo
# NameError: undefined local variable or method `bar' for Foo:Class

I want to be able to access the bar instance method on the Bar class. The reason for calling the foo class method with a block from the inherited class is part of the DSL requirement, but any suggestions for a better design would be appreciated.

3
  • 2
    The two foos are confusing. Commented Nov 23, 2013 at 9:34
  • Why are new.bar or making bar a class method not good? Commented Nov 23, 2013 at 9:36
  • @SergioTulentsev HA! sorry... im not very creative with my contrived code :) Commented Nov 23, 2013 at 19:04

1 Answer 1

1

Blocks are lexically scoped, including the value of self. At the point where the block is defined, self is Bar and Bar doesn't respond to bar. You need to evaluate the block in the context of the object (in this case an instance of Bar and not Bar itself) whose methods you want to call. That's what instance_eval does:

class Bar
  def self.foo(&block) @foo ||= block end
  def foo; instance_eval(&self.class.foo) end
  def bar; 'bar' end
end

class Foo < Bar; foo do bar end end

Foo.new.foo
# => 'bar'

Note that all the usual disclaimers about instance_eval apply: since you change the value of self methods and instance variables that the block author may expect to be available won't be.

Sign up to request clarification or add additional context in comments.

1 Comment

perfect! i was actually playing with instance_eval earlier, but it was not working since I was not using the ampersand to convert it to a proc. But now it makes sense. Thanks you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.