Method_missing не работает, когда это должно
У меня есть класс Team в моей программе, и я пытаюсь использовать method_missing, но вместо запуска функции, когда метод не существует, он выдает мне ошибку:"неопределенный метод`hawks'для Team:Class (NoMethodError)"
Мой код выглядит следующим образом:
class Team
attr_accessor :cust_roster, :cust_total_per, :cust_name, :cust_best_player
@@teams = []
def initialize(stats = {})
@cust_roster = stats.fetch(:roster) || []
@cust_total_per = stats.fetch(:per)
@cust_name = stats.fetch(:name)
@cust_best_player = stats.fetch(:best)
@@teams << self
end
def method_missing(methId)
str = methID.id2name
Team.new(roster:[], per: 0, name: str.uppercase, best: 0)
end
class <<self
def all_teams
@@teams
end
end
end
hawks = Team.hawks
2 ответа
Есть ряд проблем с вашим кодом. Давайте пройдемся по одному.
Из документации,
method_missing (* args) private Вызывается Ruby, когда obj отправляется сообщение, которое он не может обработать.
Вот message
относится к method
, В ruby, когда вы вызываете метод объекта, вы на самом деле send
в message
к object
Чтобы лучше это понять, попробуйте это в оболочке irb.
1+2
=> 3
1.send(:+,2)
=> 3
Здесь 1 и 2 являются объектами Fixnum
учебный класс. Вы можете подтвердить это, используя 1.class
, Хорошо, вернемся к вашему вопросу. Итак, method_missing
метод должен быть вызван на экземпляр.
team = Team.new
team.hawks
Если вы попробуете приведенный выше фрагмент кода, вы получите сообщение об ошибке 'fetch': key not found: :roster (KeyError)
Вы можете обойти это, передав default value
в качестве второго параметра fetch
метод. Замените свой initialize
метод с
def initialize(stats = {})
@cust_roster = stats.fetch(:roster, [])
@cust_total_per = stats.fetch(:per, 0)
@cust_name = stats.fetch(:name, "anon")
@cust_best_player = stats.fetch(:best, "anon")
@@teams << self
конец
Если вы выполните сценарий, вы получите stack level too deep (SystemStackError)
из-за небольшой опечатки в этой строке.
str = methID.id2name
В определении метода вы получаете аргумент с именем methId
но внутри ты пытаешься позвонить methID
, Исправить это с
str = methId.id2name
Если вы выполните свой скрипт, вы снова получите сообщение об ошибке undefined method uppercase for "hawks":String (NoMethodError)
Это потому что нет uppercase
метод на строки. Вы должны вместо этого использовать upcase
метод.
Team.new(roster:[], per: 0, name: str.upcase, best: 0)
и тебе должно быть хорошо идти.
Для получения дополнительной информации см. http://apidock.com/ruby/BasicObject/method_missing
Надеюсь это поможет!
class Team
attr_accessor :cust_roster, :cust_total_per, :cust_name, :cust_best_player
@@teams = []
def initialize(stats = {roster: [], per: 0, name: "", best: 0}) # I added the default values here.
@cust_roster = stats.fetch(:roster)
@cust_total_per = stats.fetch(:per)
@cust_name = stats.fetch(:name)
@cust_best_player = stats.fetch(:best)
@@teams << self
end
def method_missing(name, *args)
self.cust_name = name.to_s.upcase
end
class << self
def all_teams
@@teams
end
end
end
team_hawks = Team.new #=> create an instance of Team class, I renamed the object to avoid confusions.
team_hawks.hawks #=> called method_missing which assigned the cust_name variable to "HAWKS"
team_hawks.cust_name #=> HAWKS, so cust_name is assigned to be hawks. This is to check if the assignment worked.
Надеюсь, это то, что вы ищете.