2012-04-05 7 views
0

Étant donné que j'ai un objet qui répond donc à certaines méthodes. Je veux en collectionner quelques-uns dans un Hash, je suis toujours en train d'écrire un snipped comme ça.Une meilleure façon de remplir un hachage avec des valeurs

class Person 
    # ... 

    def some_selected_attributes 
    attrs = {} 
    [:first_name, :last_name, :zip].each do |attr| 
     attrs[attr] = self.__send__(attr) 
    end 
    attrs 
    end 
end 

Je crois qu'il existe une façon plus élégante de le faire.

: wq!

Répondre

1

Si vous voulez vraiment un hachage, LBg a vous a donné quelques beaux motifs. Mais vous pouvez envisager de créer de petits objets struct au lieu de hachages primitifs. Les structures se comportent comme des tables de hachage pour l'indexation et l'énumération, mais elles ont aussi des méthodes d'accesseurs, de sorte qu'elles peuvent être utilisées avec la notation d'envoi et de point.

class Person 
    # ... 
    SomeSelectedPersonAttrs = Struct.new :first_name, :last_name, :zip 

    def some_selected_attributes 
    SomeSelectedPersonAttrs[ * SomeSelectedPersonAttrs.members.map{|a| send a } ] 
    end 

end 

pa = person.some_selected_attributes 
pa.first_name # => "Joe" 
pa[:first_name] # => "Joe" 
pa['first_name'] # => "Joe" 
p.zip = 12345 # sets zip to 12345 
p[:zip] = 12345 
p['zip'] = 12345 

pa.values  # => ["Joe","Blow",12345] 
pa.each_pair {|k,v| ... } 
2

Comme il n'y a que trois attributs, je vois qu'il n'y a pas de raison de ne pas écrire directement:

def some_selected_attributes 
    { 
    first_name: first_name, 
    last_name: last_name, 
    zip: zip 
    } 
end 

Vous pouvez aussi le faire avec inject:

def some_selected_attributes 
    [:first_name, :last_name, :zip].inject({}) do |hash, attr| 
    hash[attr] = __send__ attr 
    hash 
    end 
end 

Une autre option, en utilisant Hash[] :

def some_selected_attributes 
    Hash[[:first_name, :last_name, :zip].map {|attr| [attr, __send__ attr] }] 
end 
+0

Je voulais aussi mentionner injecter. Mais même si je savais ce que ça faisait, je trouverais toujours difficile à lire. Donc, je viens souvent avec 'h = {}; ...; retour h; 'juste pour la lisibilité – Deradon

+0

Merci! Le premier pas [DRY] (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself) assez. «injecter» va dans la bonne direction, mais est difficile à lire. D'autres idées? – iblue

+0

Voir la dernière modification. –

-1

Je pense qu'il existe une meilleure façon d'accomplir ce que vous essayez de faire. Cela n'a pas beaucoup de sens d'écrire une méthode pour retourner un hachage d'arguments qui sont déjà dans la classe. Vous pouvez tout simplement faire les variables d'instance ou des méthodes accessibles à l'aide attr_accessor:

class Person 
    attr_accessor :first_name, :last_name, :zip 

end 

vous n'avez pas besoin la méthode some_selected_attributes(). Vous pouvez simplement accéder aux variables ou méthodes directement:

p = Person.new 
p.first_name # => value of first_name 

Si vous vouliez un hachage, vous pouvez simplement le créer:

p = Person.new 
hash = {:first_name => p.first_name, :last_name => p.last_name, :zip => p.zip } 

Je ne sais pas pourquoi vous voulez construire ce hachage non plus. Il semble que ce soit une façon plus "orientée objet" d'accomplir tout ce que vous essayez de faire (en passant l'objet entier comme argument). Au lieu de travailler avec un hachage de champs sélectionnés, je suggérerais de travailler avec des objets entiers.

Questions connexes