2017-07-26 1 views
2

J'essaie de faire référence à l'un des paramètres d'un objet à l'intérieur du bloc transmis avec lui.Comment puis-je référencer les paramètres d'un objet dans un bloc passé?

def command(attributes = {}, &block) 
    yield 
end 

command(attr_1: 'Open Mike Night', 
    attr_2: 2033392, 
    attr_3: [9.29, 10.08, 12.32]) do |event| 

    event.message.delete 

    puts "#{self.attributes[:attr_1]}" # <-- That didn't work. 

end 

Est-ce que quelque chose comme ça est possible et si oui, comment pourrais-je le faire? Que dois-je regarder?

+0

La dernière clé devrait-elle être 'attr_3'? –

+0

@ sagarpandya82 Vous avez raison, désolé! – Calculon

+0

Avez-vous un «rendement» dans votre définition de «commande»? –

Répondre

0

En haut de ma tête, vous pourriez faire quelque chose comme ça. Attention, je n'ai aucune idée si cela convient au code de production.

Ce code crée des variables d'instance pour chaque clé en itérant sur les clés de l'argument hash. Puis, quand nous appelons command, nous pouvons faire référence à la valeur de chaque clé dans le bloc à l'aide de la instance_variable correspondante:

def command(attributes = {}, &block) 
    attributes.each_key { |key| 
    instance_variable_set("@#{key}",attributes[key]) 
    } 
    yield 
end 

command(attr_1: 'Open Mike Night', 
     attr_2: 2033392, 
     attr_3: [9.29, 10.08, 12.32]) do |event| 

    puts "#{@attr_1}" 
end 

impressions:

Open Mike Night 
+0

Cela ne fonctionne pas si la méthode est définie dans une portée différente de celle où elle est appelée. Le bloc est délimité par son environnement, donc si 'command 'est défini dans' class A' mais que la méthode est appelée dans 'la classe B',' @ attr_1' sera évalué dans le contexte de 'B', pas' A' –

0

les cédons au bloc:)

def command(attributes = {}) 
    yield self, attributes 
end 

attributes = { attr_1: 'Open Mike Night', attr_2: 2033392, attr_3: [9.29, 10.08, 12.32] } 

command(attributes) do |obj, attrs| 
    p "#{obj.object_id}, #{attrs[:attr_1]}" 
end 
# => "70309890142840, Open Mike Night" 

Toute méthode, constante ou variable disponible dans une étendue de méthode peut être donnée en tant qu'argument à yield pour être envoyée dans un bloc en tant que variable de bloc. Alors vous pouvez en faire ce que vous voulez. Dans ce cas, attrs serait également une variable complètement optionnelle, et le bloc serait valide sans cela.

command(attributes) { |obj| p obj.object_id } # => 70309890142840 

P.S. Vous n'avez pas besoin de &block dans la signature de la méthode si vous utilisez yield. Vous ne donniez pas non plus yield un argument dans votre question, mais transmettiez une variable |event| dans le bloc, ce qui aurait été nil. Donc je l'ai juste laissé dans l'exemple ci-dessus.