2016-08-30 1 views
0

je définissais cette méthode:Comment interdire un bloc (exige qu'aucun argument de bloc est donné) à Ruby

# @return [Array<String>] items 
def produce_items 
    ["foo", "bar", "baz"] 
end 

Une utilisation correcte serait, évidemment,

produce_items.each do |i| 
    puts i 
end 

Mais je l'ai écrit ce , qui ne fait rien en silence:

produce_items do |i| 
    puts i 
end 

Est-il possible de déclarer produce_items de telle sorte que mon utilisation incorrecte produit une erreur/exception? Si MRI ne peut pas le faire, un interprète alternatif peut-il le faire? Est-ce qu'un outil d'analyse statique comme RuboCop ou ruby-lint peut le faire?

Je soupçonne que ce peut être difficile parce qu'il ya des idiomes communs où les méthodes prennent un bloc en option:

def block_optional_implicitly 
    if block_given? 
    puts "Got a block" 
    yield 
    else 
    puts "Did not get a block" 
    end 
end 

def block_optional_explicitly(&block) 
    unless block.nil? 
    puts "Got a block" 
    block.call 
    else 
    puts "Did not get a block" 
    end 
end 

(Ceci est un revers de la question How to require a block in Ruby?)

+1

Vous pouvez toujours 'augmenter YikesBlock si block_given?' – Felixyz

+0

Vous pouvez déclencher une exception de façon sélective lorsque la méthode ne l'attend pas. Mais, vous devez être assez prudent pour ne pas le faire dans les méthodes qui pourraient réellement exiger un bloc (facultatif ou non). – kiddorails

Répondre

5

Oui, aucun moyen de le faire dans ruby, sauf le block_given? vérifie partout dans le code.

Passer un bloc à une méthode qui ne s'attend pas à ce que cela ne cause aucun dommage. En plus de quelque chose qui ne se passe pas (parce que vous avez oublié le .each). Cela devrait être couvert par des tests unitaires. Vous tuez deux oiseaux avec une pierre: faites votre code plus résistant à la régression et ne pas insérer fail "unexpected block" if block_given? dans chaque méthode de votre application.