Ruby и public_method_defined? : странное поведение - PullRequest
1 голос
/ 25 апреля 2010

Читая книгу "Хорошо обоснованный рубист", я натолкнулся на странное поведение. Идея кода заключается в использовании собственного метода 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

что действительно понятно, так как нечего исполнять.


хм, это потому что у меня есть аксессуары для друзей и хобби? Но я думал, что они будут доступны только в экземплярах, а не на уровне объекта класса.

1 Ответ

4 голосов
/ 25 апреля 2010

Если предположить, что код, вставленный в ваш вопрос, является точным кодом, который вы запускаете, то проблема заключается в наборе ошибки в initialize:

def initialize( мама ) должно быть def initialize( имя )

Если имя параметра name введено с ошибкой, это приводит к строке @name = name, а не к значению

"установить @name на значение параметра"

значит

"установить @name на значение, возвращаемое методом name (ваш читатель attr)" (что, конечно, nil, поскольку оно не было установлено)

Следовательно, все ваши "Битлз" останутся без заданных имен, и результатом будут два друга для хобби Пола и Ринго, но со всеми пустыми именами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...