Frage

I'm studying Ruby and try to implement method_missing, but it's not working. For example, I want to print method name after find_ but ruby raises "undefined method 'find_hello'" when i call it on Book instance.

TEST_05.RB

module Searchable
    def self.method_missing(m, *args)
        method = m.to_s
        if method.start_with?("find_")
            attr = method[5..-1]
            puts attr
        else
            super
        end
    end
end

class Book

    include Searchable

    BOOKS = []
    attr_accessor :author, :title, :year

    def initialize(name = "Undefined", author = "Undefined", year = 1970)
        @name = name
        @author = author
        @year = year
    end
end


book = Book.new
book.find_hello
War es hilfreich?

Lösung

You are calling method on object which looks for instance_level method. So you need to define instance_level method_missing method:

module Searchable
    def method_missing(m, *args)
        method = m.to_s
        if method.start_with?("find_")
            attr = method[5..-1]
            puts attr
        else
            super
        end
    end
end

class Book

    include Searchable

    BOOKS = []
    attr_accessor :author, :title, :year

    def initialize(name = "Undefined", author = "Undefined", year = 1970)
        @name = name
        @author = author
        @year = year
    end
end


book = Book.new
book.find_hello   #=> hello

When you use self with method definition. It is defined as class level method. In your case Book.find_hello will output hello.

Andere Tipps

You've defined method_missing as a class method on Searchable, but you're trying to invoke it as an instance method. To invoke the method as it is, run it against the class:

Book.find_hello

If your intention is to find something from the entire collection of books, this is the canonical way it's done. ActiveRecord uses this approach.

You could similarly have a find_* instance method that would search the current book instance for something. If that's your intention, then change def self.method_missing to def method_missing.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top