method_missing | Metaprogramming in ruby -6

Prateek vyas
2 min readFeb 23, 2023

--

Missing methods in ruby

Another piece of metaprogramming is method_missing . When you call a method on an object, Ruby first goes into the class and browses its instance methods. If it doesn’t find the method there, it continues search up the ancestors chain. If Ruby still doesn’t find the method, it calls another method named method_missing which is an instance method of BasicObject that every object inherits.

BasicObject.private_methods.include? :method_missing
# => true

method_missing is mostly used in handling errors or you can use it to create methods on the fly if they doesn’t exist!

Let’s see it in action

class Book
attr_accessor :title

def method_missing(method_name, *_arguments, &_block)
if method_name.to_s.include?('test')
p 'I believe this is a test method'
else
p "Undefined method #{method_name} does not exist"
end
end
end
b = Book.new
b.test_method # => 'I believe this is a test method'
b.undefined_method # => "Undefined method #{method_name} does not exist"

In the above code i have created a Book class, and defined a method method_missing . which accepts the method name , arguments, and a block.

Then i have created a instance of a Book , on which i am calling a method test_method but i have not created it. SO the control will be going to the method_missing method and there i have used a check method_name.to_s.include?('test') which simply means that if a method name includes ‘test’ in it’s name then we will return “I believe this is a test method”. Now what if it doesn’t include the ‘test’ in it’s name? It will ofcourse call the original method_missing and give some error. But we have handled it in else condition. In which i am returning “Undefined method <method_name> does not exist”.

So if we do b.undefined_method it will give us “Undefined method undefined_method does not exist”.

Creating methods on the fly if they don’t exist

So we can combine our previous knowledge on creating the method if they doesn’t exist. let’s see one more example

class User

def initialize(name)
@name = name
end

def self.create(name)
user = User.new(name)
user
end

def method_missing(method, *args, &block)
return super unless method.to_s.eql? 'print_name'

self.class.send(:define_method, :print_name) do
@name
end
send(:print_name)
end
end

user = User.create('pratik')
p user.print_name # => 'pratik'

In the above code. we have a class User. and a class method create in which we created a new instance of the user with a name attribute.

Now after having an instance of User We want to access it’s name. But we dont have any such method . so method_missing will handle it. and inside the method_missing we have used send method and define_method to create a method print_name . it can be called later…

Thanks for giving it a read.

Happy coding!

--

--

Prateek vyas
Prateek vyas

Written by Prateek vyas

Hello i am prateek vyas working as a ruby developer

No responses yet