Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Responding to Calls to Undefined Methods
3.
Frequently Asked Questions
3.1.
What is an undefined method in Ruby?
3.2.
What is a NilClass in Ruby?
3.3.
What is a colon in Ruby?
3.4.
What is the syntax for calling a method in Ruby?
4.
Conclusion
Last Updated: Mar 27, 2024

Responding to Calls to Undefined Methods In Ruby

Author soham Medewar
1 upvote

Introduction

According to The 2022 Airbrake Error Data Report, the most prevalent error within projects is the undefined method, often known as the NoMethodError exception. When a receiver (an object) receives a method that does not exist, an error occurs.

Instead of raising a NoMethodError when someone calls an undefined method on an instance of your class, you want to cut off the method call and do something else with it.

Alternatively, you may be required to explicitly specify a huge (potentially endless) number of methods for a class. You'd rather construct a single method that can respond to an endless number of different method names.

Responding to Calls to Undefined Methods

To overcome the above-discussed problem, we have a solution. Start with defining a missing_method for our class. For your class, define a method missing method. When somebody calls a method that would otherwise throw a NoMethodError, the missing_method method is invoked instead. It receives the symbol of the nonexistent method as well as any arguments passed in.

Here's a class that alters the default error handling when a method is missing.

Code

​​class MyClass
    def defined_method
        puts"This is a defined method."
    end
    def missing_method(method, *args)
        puts "Sorry, I don't know any #{method} method."
    end
end

obj = MyClass.new
obj.defined_method 
obj.undefined_method
You can also try this code with Online Ruby Compiler
Run Code


Output

This is a defined method.
Sorry, I don't know any undefined_method method.
You can also try this code with Online Ruby Compiler
Run Code

 

In the next example, we'll provide Fixnum, a missing_method implementation to define an infinite number of additional methods. Fixnum will now respond to any method that looks like "plus_#" and takes no arguments:

Code

class Fixnum
    def missing_method(m, *args)
        if args.size > 0
            raise ArgumentError.new("wrong number of arguments (#{args.size} for 0)")
        end
            match = /^plus_([0-9]+)$/.match(m.to_s)
        if match
            puts self + match.captures[0].to_i
        else
            raise NoMethodError.
            new("undefined method '#{m}' for #{inspect}:#{self.class}")
        end
    end
end
4.plus_5 # => 9
-30.plus_20 # => -10
10.plus_100 # => 110
20.send(:plus_50) # => 70
125.divide_25
# NoMethodError: undefined method 'divide_25' for 125:Fixnum
150.plus_7(10)
# ArgumentError: wrong number of arguments (1 for 0)
You can also try this code with Online Ruby Compiler
Run Code

 

The missing_method approach is widely used in delegation circumstances when one object must implement all of another object's methods. Rather than specifying each method, a class implements missing_method as a catch-all and sends "missing" method calls to other objects. The built-in delegate library makes this simple, but here's an example class that delegated practically all of its functions to a string. It should be noted that this class does not subclass String:

Code

class BackwardsString
    def initialize(s)
        @s = s
    end
    def missing_method(m, *args, &block)
        result = @s.send(m, *args, &block)
        result.respond_to?(:to_str) ? BackwardsString.new(result) : result
    end
    def to_s
        @s.reverse
        puts s
    end
    def inspect
        to_s
        puts s
    end
end
You can also try this code with Online Ruby Compiler
Run Code

 

The call to Object#send is the interesting part here. This method accepts the name of another method and calls it with the arguments provided. Without even glancing at the method name, we may delegate any missing method call to the underlying string:

s = BackwardsString.new("I'm ahead!") # => !daeha m'I
s.size # => 10
s.upcase # => !DAEHA M'I
s.reverse # => I'm ahead!
s.undefined_method # NoMethodError: undefined method 'no_such_method' for "I'm ahead!":String
You can also try this code with Online Ruby Compiler
Run Code

 

The missing_method method can also be used to add syntactic sugar to a class. If one of your class's methods is frequently invoked with a string argument, you can create an object.string a simple way object.method ("string").
 

A missing_method method can also be defined on a class. This can be used to add syntactic sugar to factory classes. Here's a basic factory class that makes it simple to construct strings (as if it wasn't already straightforward):

Code

class StringFactory
 def StringFactory.missing_method(m, *args)
 return String.new(m.to_s, *args)
 end
end

puts StringFactory.first_string # => "first_string"
puts StringFactory.second_string # => "second_string"
puts StringFactory.superclass # => Object
You can also try this code with Online Ruby Compiler
Run Code

 

If we try to call an explicitly defined method, then the missing_method will not be called, as we can see when we call the String.Factory.superclass method we get return value as "object".

The missing_method method intercepts all calls to undefined methods, including calls to "genuine" methods with incorrectly entered names. This is a frequent source of bugs. If you have problems while using your class, the first thing you should do is add debug statements to missing_method or comment it out entirely.

If you’re using missing_method to implicitly define methods, you should also be aware that Object.respond_to? returns false when called with the names of those methods. After all, they’re not defined:

Frequently Asked Questions

What is an undefined method in Ruby?

Undefined method call created a NoMethodError. This is a typical Ruby error that indicates that the method or attribute you are attempting to call on an object has not been declared.

What is a NilClass in Ruby?

Ruby includes a built-in class called NilClass. This class cannot be instantiated. When a message is delivered to nil, it is received by a hard-coded C-level "class" called rb_cNilClass, which corresponds to the NilClass in Ruby.

What is a colon in Ruby?

A colon (:) is used before a word to generate a Ruby symbol. Consider it to be an immutable string. A symbol is an instance of the Symbol class, and there is only one Symbol object for each given symbol name.

What is the syntax for calling a method in Ruby?

In the class, a method must be established with the name of the method followed by parentheses (). A method definition is made up of a method header and a method body. A method can be accessed by using the following syntax: method_name(); 

Conclusion

In this article, we have learned to respond to calls to undefined methods in ruby.

If you want to learn more, check out our articles on Object Marshalling in RubyTainting Objects in RubyCopying Objects In RubyHow To Invoke Global Functions In Ruby?, and Object References in Ruby.

Do upvote our blogs if you find them helpful and engaging!

Happy Learning, Ninjas!

Live masterclass