-1

I have a class Foo with a method bar. How do I override foo's bar with

Foo.instance_eval do
  def bar
    #do something a little different
  end
end

whats to be overridden:

module Lorem
  class Foo
    def bar
      # do something
    end
  end
end

instance_eval needs to be used, class_eval works with overriding but doesnt keep the context

bjhaid
  • 9,592
  • 2
  • 37
  • 47
godzilla3000
  • 246
  • 3
  • 23
  • what's the problem.. then ? What is your question ? – Arup Rakshit Feb 17 '14 at 20:56
  • What you did above works.. What's the issue with it? (I just tried it and it did override Foo's bar) – Abdo Feb 17 '14 at 21:10
  • @Abdo I was confused 15 mins before than you :-) – Arup Rakshit Feb 17 '14 at 21:11
  • @ArupRakshit haha :-) I hope all is well dude :-) – Abdo Feb 17 '14 at 21:12
  • j, is it your desire to change `module Lorem` so that whenever it is `include`d, your new `bar()` will be used? – Cary Swoveland Feb 17 '14 at 21:14
  • `instance_eval` is used on an instance of an object not the Class, except you want to define class level methods – bjhaid Feb 17 '14 at 21:16
  • @abdo im trying to override a method, opening the class doesnt do it because the method im overriding with contains variables and requirements which were declared in the class instance – godzilla3000 Feb 17 '14 at 21:31
  • @bjhaid the class `Foo` itself is an object so his code can work. I'm just wondering if he's using it correctly – Abdo Feb 17 '14 at 21:34
  • It's still not clear. If `class A; include Lorem; end`, please show the result you want using `A` and/or `A.new`. – Cary Swoveland Feb 17 '14 at 21:35
  • @Abdo if you call `instance_eval` directly on `Foo` you would be creating class methods and not instance methods – bjhaid Feb 17 '14 at 21:35
  • OP should be a bit clear on how he accesses his class Foo cannot be accessed directly outside its namespace so calling `Foo.instance_eval ..` is not possible it should be `Lorem::Foo.instance_eval ..` – bjhaid Feb 17 '14 at 21:36
  • @bjhaid yup, you would. This is why I was saying I'm not sure whether the OP is using it correctly =) – Abdo Feb 17 '14 at 21:45

2 Answers2

0

Assuming you want to change module Lorem so that whenever it is included, your new bar() will be used, you were very close:

module Lorem
  class Foo
    def bar
      puts "old bar"
    end
  end
end

Lorem::Foo.class_eval do
  def bar
    puts "new bar"
  end
end

class A
  include Lorem
  Foo.new.bar #=> "new bar"
end
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
  • class_eval does not work because Lorem::Foo has instances and requirements which are evaluated in the class – godzilla3000 Feb 17 '14 at 21:26
  • I want every call on Lorem::Foo.new.bar to evaluate my overridden version of bar although the preexisting code / declared variables. I tried class_eval a while ago, switched to instance_eval – godzilla3000 Feb 17 '14 at 21:28
  • I do not understand your comments. I will await clarification of the question. – Cary Swoveland Feb 17 '14 at 21:50
  • @jquadrin how in the life cycle of your code do you determine which instance of `Lorem::Foo` should have what version of `bar` – bjhaid Feb 17 '14 at 21:52
0

I think the issue with what you're trying to achieve is that you're trying to override the method for objects that have been already created.

In order to do so, you need to iterate over those objects and override their method using ObjectSpace as in https://stackoverflow.com/a/14318741/226255

The following does not help:

class Foo
  def bar
    puts "hello"
  end
end

x = Foo.new

Foo.instance_eval do
  def bar
    puts "bar"
  end
end

x.bar

You get the following output:

hello
=> nil

In order to override the method for objects created BEFORE you do the instance_eval, do the following:

x = Foo.new

ObjectSpace.each_object(Foo) { |obj|
  def obj.bar
    puts "bar"
  end
}

You get the output:

x.bar
bar
=> nil
Community
  • 1
  • 1
Abdo
  • 13,549
  • 10
  • 79
  • 98
  • it should not be this complex what he wants is just `x.instance_eval { def bar; puts "bar"; end }` – bjhaid Feb 17 '14 at 21:47
  • Yes, but you're assuming he has a reference to `x`. This code would do it for all the instances of `Foo`. – Abdo Feb 17 '14 at 21:50
  • @bjhaid but still, you might be right if all he wants is to override `x` 's method =) – Abdo Feb 17 '14 at 21:51