3

I want to write a method which takes one parameter and creates another method, named with this parameter. Here is my code

class Class
  def createMethod(attr_name)
    attr_name = attr_name.to_s
    class_eval %Q{
        def #{attr_name}
            puts "bar"
        end
    }
  end
end

p Class.new.createMethod("foo").respond_to?(:foo)

Unfortunately, respond_to?(:foo) evaluates to false. What's wrong?

1 Answer 1

3

This is because class_eval is a class method and you're calling it in the context of an instance. You can do this instead:

class Class
  def createMethod(attr_name)
    attr_name = attr_name.to_s
    self.class.class_eval %Q{
        def #{attr_name}
            puts "bar"
        end
    }
    self # Return yourself if you want to allow chaining methods
  end
end

Here's the output from irb when doing this:

irb(main):001:0> class Class
irb(main):002:1>   def createMethod(attr_name)
irb(main):003:2>     attr_name = attr_name.to_s
irb(main):004:2>     self.class.class_eval %Q{
irb(main):005:2"         def #{attr_name}
irb(main):006:2"             puts "bar"
irb(main):007:2"         end
irb(main):008:2"     }
irb(main):009:2>   end
irb(main):010:1> end
=> nil
irb(main):011:0> clazz = Class.new
=> #<Class:0x007fd86495cd58>
irb(main):012:0> clazz.respond_to?(:foo)
=> false
irb(main):013:0> clazz.createMethod("foo")
=> nil
irb(main):014:0> clazz.respond_to?(:foo)
=> true
Sign up to request clarification or add additional context in comments.

3 Comments

The reason it's still false is that your createMethod call returns nil, not the instance, so you can't chain the respond_to? call. You could put self right before the end of createMethod and that would work.
Do not post images of text, instead copy-and-paste the actual text directly into your post. Images of text are not easily parseable, searchable, or accessible.
@AndrewMarshall Will do. Fixed.

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.