Home > Back-end >  Calling methods from a different class on method_missing
Calling methods from a different class on method_missing

Time:10-03

I am new to Ruby; thus, please forgive if ask this question incorrectly

I have a class that loads a collection and loads items into a collection based on a certain criteria

require_relative 'thing'
class Someclass
    def self.tings
       things=load_things()
    end
    def self.select_things(something)
       return things.select { |thing| thing.some_property == something }
    end
end

I would like to use method_missing instead of the direct defintions

require_relative 'thing'
class Someclass
    def self.method_missing(method, *args)
        things=load_things()
        if method == 'select_things'
            self.send("things.select { |thing| thing.some_property == args }")
        end
    end
end

However, this approach doesn't work and method_missing just outputs the code string. Is there a proper way to call a code from method_missing?

Thank you very much everyone in advance

CodePudding user response:

There are two issues with your method_missing implementation:

  1. The method name is given as a symbol, not as a string:

    def self.method_missing(method, *args)
      if method == :select_things
        # ...
      end
    end
    
  2. You have to call super if you don't process the message yourself:

    def self.method_missing(method, *args)
      if method == :select_things
        # ...
      else
        super
      end
    end
    

If you don't call super your object is going to swallow any message without ever raising a NoMethodError and you'll have a very hard time understanding why your code isn't working.

In addition, you should also implement respond_to_missing? to return true for the messages you are responding to, e.g.:

def self.respond_to_missing?(method, include_all = false)
  [:select_things].include?(method) || super
end

The above gives you:

Someclass.respond_to?(:select_things) #=> true
  •  Tags:  
  • ruby
  • Related