Ruby and public_method_defined? : strange behaviour
- by aXon
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.