2010-03-12 4 views
3

J'utilise mon projet MOO pour m'enseigner Test Driven Design, et ça me prend des endroits intéressants. Par exemple, je l'ai écrit un test qui a un attribut sur un objet particulier doit toujours retourner un tableau, donc -La meilleure façon de faire un attribut toujours un tableau?

t = Thing.new("test") 
p t.names #-> ["test"] 

t.names = nil 
p t.names #-> [] 

Le code que j'ai pour cela est correct, mais il ne semble pas terriblement rubis me :

class Thing 

    def initialize(names) 
     self.names = names 
    end 

    def names=(n) 
     n = [] if n.nil? 
     n = [n] unless n.instance_of?(Array) 

     @names = n 
    end 

    attr_reader :names 
end 

Existe-t-il un moyen plus élégant, Ruby-ish de faire cela?
(NB: si quelqu'un veut me dire pourquoi ceci est un test stupide pour écrire, ce serait intéressant aussi ...)

+0

J'ai obtenu trois bonnes réponses. Merci tout le monde. – Shadowfirebird

+0

Que se passe-t-il si l'argument est convertible en tableau? Voir ma réponse pour plus de détails ... –

Répondre

5

Je voudrais souligner qu'il existe déjà une méthode intégrée à faire w Chapeau que tu veux! C'est ce qu'on appelle Array(). La question à se poser est: que deviennent les classes convertibles en tableaux (comme 0..42)? Je pense que la plupart des Rubisistes s'attendraient à ce qu'ils soient convertis. Alors:

class Thing 
    attr_accessor :names 

    def initialize(names) 
    self.names = names 
    end 

    def names=(values) 
    @names = Array(values) 
    end 
end 

Vous obtiendrez les mêmes résultats, par exemple:

t = Thing.new("car") 
t.names #-> ["car"] 

t.names = nil 
t.names #-> [] 

t.names = 42 
t.names #-> [42] 

t.names = [1, 2, 3] 
t.names #-> [1, 2, 3] 

t.names = 1..3 
t.names #-> [1, 2, 3] # Is this what you want, or not? 
+0

En fait, je ne suis pas sûr que cela compte - bien sûr, je ne sais pas à coup sûr jusqu'à ce que j'écrive tout le code! - mais c'est clairement la solution la plus élégante. Je vous ai transféré la tique. Désolé, tout le monde. – Shadowfirebird

+0

+1, Pour me faire lire la documentation 'Kernel.Array '. (http://www.ruby-doc.org/core/classes/Kernel.html#M005967) –

0

Utilisez le * pour aller chercher tous les params dans un tableau dans votre méthode initialize


class Thing 
    attr_accessor :names 

    def initialize(*names) 
     @names = names 
    end 
end 

t = Thing.new("test") 
p t.names #-> ["test"] 

t.names = nil 
p t.names #-> nil 

+0

La dernière exécution retourne 'nil', pas' [] ' –

+0

exact à droite je propose une autre solution – shingara

2

Vous pouvez utiliser la méthode getter pour mettre en forme la valeur.

class Thing 

    def initialize(names) 
    self.names = names 
    end 

    def names 
    [*@names].compact 
    end 

    def names=(values) 
    @names = values 
    end 

end 

t = Thing.new("test") 
p t.names #-> ["test"] 

t.names = nil 
p t.names #-> [] 
+0

' [* @ noms] .compact' est vraiment sympa. Il me semble que c'est plus lisible que '[* (n || [])]'. De plus, vous avez raison: je ne devrais être préoccupé par ce que la méthode publique renvoie, pas par la manière dont elle stocke les données. – Shadowfirebird

1

Dans d'autres odeurs comme mes réponses précédentes:


class Thing 
    def initialize(*names)                                                              
    @names = names 
    end 
    def names 
    @names || [] 
    end 
    def names=(*names) 
    @names = names 
    end 
end 

t = Thing.new("test") 
p t.names #-> ["test"] 

t.names = nil 
p t.names #-> [] 
+0

+1, Votre code après 't.names = nil' retournera' [nil] 'pour' t.names'. Vous devez ajouter un compact à la méthode 'names' et supprimer le' || 'car' @ noms' ne sera jamais 'nil'. –

3

Essayez ceci:

class Thing 

    def initialize(names) 
     self.names = names 
    end 

    def names=(n) 
    @names= [*(n||[])] 
    end 

    attr_reader :names 
end 

Testons la classe:

t = Thing.new("car") 
t.names #-> ["test"] 

t.names = nil 
t.names #-> [] 

t.names = [1, 2, 3] 
t.names #-> [1, 2, 3] 
+0

Je pense que la nouvelle version est efficace et elle a l'air bien :-) –