Читая книгу "Хорошо обоснованный рубист", я натолкнулся на странное поведение. Идея кода заключается в использовании собственного метода method_missing. Единственная вещь, которую я не могу понять, это то, почему этот код выполняется, так как у меня не определены методы класса Person.all_with_ *, что, в свою очередь, означает, что self.public_method_defined? (Attr) возвращает true (attr - друзья а потом увлечения).
#!/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
Выход
is friends with
is friends with
is into rings
что действительно понятно, так как нечего исполнять.
хм, это потому что у меня есть аксессуары для друзей и хобби? Но я думал, что они будут доступны только в экземплярах, а не на уровне объекта класса.