2016-08-19 3 views
1

J'ai une classe Team dans mon programme et j'essaie d'utiliser method_missing mais au lieu d'exécuter la fonction quand la méthode n'existe pas, cela me donne une erreur: "méthode non définie` éperviers pour l'équipe: classe (NoMethodError) »Method_missing ne fonctionne pas quand il le faut

Mon code est le suivant:

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 
+1

Vous ne voulez pas dire 'hawks = Team.new.hawks'? 'Team.hawks' tente d'invoquer la méthode de classe inexistante' hawks'. –

+1

Ou peut-être 'def self.method_missing'? – ScottJ

+0

non cela ne fonctionne pas et puisque Team.new est déjà une fonction, il ne fonctionnera pas method_missing –

Répondre

4

Il y a un certain nombre de problèmes avec votre code. Passons un par un.

De la documentation,

method_missing(*args) private Invoked by Ruby when obj is sent a message it cannot handle.

Ici message fait référence à la method. Dans ruby, chaque fois que vous appelez une méthode sur un objet, vous êtes en réalité send et object

Pour mieux comprendre cela, essayez ceci dans le shell irb.

1+2 
=> 3 
1.send(:+,2) 
=> 3 

Ici 1 et 2 sont des objets de la classe Fixnum. Vous pouvez le confirmer en utilisant 1.class. Ok, revenons à votre question. Ainsi, une méthode method_missing doit être appelée sur une instance.

team = Team.new 
team.hawks 

Si vous essayez la pièce au-dessus de code, vous obtiendrez une erreur en disant 'fetch': key not found: :roster (KeyError)

Vous pouvez contourner ce problème en passant un default value comme second paramètre à la méthode fetch. Remplacez votre méthode initialize avec

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 

fin

Si vous exécutez le script, vous obtiendrez un stack level too deep (SystemStackError) à cause d'une faute de frappe dans cette petite ligne.

str = methID.id2name 

Dans la définition de la méthode, vous recevez un argument avec le nom de methId mais à l'intérieur vous essayez d'appeler methID. Fixez avec

str = methId.id2name 

Si vous exécutez votre script, vous obtenez une erreur de nouveau en disant undefined method uppercase for "hawks":String (NoMethodError)

Ceci est parce qu'il n'y a pas de méthode uppercase sur les chaînes. Vous devriez plutôt utiliser la méthode upcase.

Team.new(roster:[], per: 0, name: str.upcase, best: 0) 

et vous devriez être prêt à partir.

Pour plus, voir http://apidock.com/ruby/BasicObject/method_missing

Hope this helps!

+0

wow merci beaucoup je ne peux pas croire que j'ai raté cela –

+0

@AvyayVaradarajan, j'ai mis à jour ma réponse pour refléter l'erreur sur ' majuscule''. Jetez un oeil –

+0

merci pour toute l'aide –

0
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. 

J'espère que c'est ce que vous cherchez.