Ruby and public_method_defined? : strange behaviour
        Posted  
        
            by aXon
        on Stack Overflow
        
        See other posts from Stack Overflow
        
            or by aXon
        
        
        
        Published on 2010-04-25T14:12:43Z
        Indexed on 
            2010/04/25
            14:23 UTC
        
        
        Read the original article
        Hit count: 302
        
ruby
Hi there
Whilst reading through the book "The well grounded Rubyist", I came across some strange behaviour. The idea behind the code is using one's own method_missing method. The only thing I am not able to grasp is, why this code gets executed, as I do not have any Person.all_with_* class methods defined, which in turn means that the self.public_method_defined?(attr) returns true (attr is friends and then hobbies).
#!/usr/bin/env ruby1.9
class Person
        PEOPLE = []
        attr_reader :name, :hobbies, :friends
        def initialize(mame)
                @name = name
                @hobbies = []
                @friends = []
                PEOPLE << self
        end
        def has_hobby(hobby)
                @hobbies << hobby
        end
        def has_friend(friend)
                @friends << friend
        end
        def self.method_missing(m,*args)
                method = m.to_s
                if method.start_with?("all_with_")
                        attr = method[9..-1]
                        if self.public_method_defined?(attr)
                                PEOPLE.find_all do |person|
                                        person.send(attr).include?(args[0])
                                end
                        else
                                raise ArgumentError, "Can't find #{attr}"
                        end
                else
                        super
                end
        end
end
j = Person.new("John") 
p = Person.new("Paul") 
g = Person.new("George") 
r = Person.new("Ringo")
j.has_friend(p) 
j.has_friend(g) 
g.has_friend(p) 
r.has_hobby("rings")
Person.all_with_friends(p).each do |person| 
        puts "#{person.name} is friends with #{p.name}"
end 
Person.all_with_hobbies("rings").each do |person|
        puts "#{person.name} is into rings"
end
The output is
is friends with 
 is friends with 
 is into rings
which is really understandable, as there is nothing to be executed.
© Stack Overflow or respective owner