1

Ruby 1.9.3: I am trying to implement a method which takes as argument a class, a symbol and a proc and defines (eventually overwriting) a new instance method for that class, but not a class method so that this test should pass:

require 'test/unit'

include Test::Unit::Assertions

class String
  def my_method
    'my_method'
  end
end

def define_instance_method(klass, method, &block)
  # klass.send :define_method, method, &block
  # ...
end

define_instance_method(Object, :my_method) { 'define_instance_method my_method' }
define_instance_method(String, :my_method) { 'define_instance_method my_method' }

assert Object.new.my_method == 'define_instance_method my_method'
assert_raise(NoMethodError) { Object.my_method }

assert String.new.my_method == 'define_instance_method my_method'
assert_raise(NoMethodError) { String.my_method }

I did many tryings (define_method, define_singleton_method, class_eval, instance_eval, instance_exec, module_eval...) but with no success; do you have any ideas?

2 Answers 2

3

@ProGNOMmers, recall that objects in Ruby are classes and classes are objects.

So everything in Ruby are objects, even classes :)

And when you define a method inside Object it will also be available to Class as well as to any class that inherits from Object.

That's mean to all classes.

Some proof:

define_instance_method(String, :my_method) { 'define_instance_method my_method' }

p String.new.my_method
p String.my_method

# =>  "define_instance_method my_method"
# =>  stackoverflow.rb:11:in `<main>': undefined method `my_method' for String:Class (NoMethodError)

See, your method not yet defined inside Object, thus not available inside String.

Now let's do it:

define_instance_method(Object, :my_method) { 'define_instance_method my_method' }

p String.my_method
# => "define_instance_method my_method"

p Array.my_method
# => "define_instance_method my_method"

p NilClass.my_method
# => "define_instance_method my_method"

So just comment define_instance_method(Object... in your tests
and String specs will pass just well.

Here are some crash tests

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

Comments

1

class_eval should work for you. Let me know why it isn't working for you

class A
end

A.class_eval do
  define_method(:foo) {puts 'hello'}
end

A.new.foo #hello
A.foo     #NoMethodError: undefined method `foo' for A:Class

1 Comment

It doesn't work: Object.my_method does not raise a NoMethodError

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.