2010-06-26 21 views
1

Je voudrais comprendre comment le code suivant fonctionne:Ruby - ont besoin d'aide pour comprendre ce Injecter

def url 
    @url ||= { 
    "basename" => self.basename, 
    "output_ext" => self.output_ext, 
    }.inject("/:basename/") { |result, token| 
    result.gsub(/:#{token.first}/, token.last) 
    }.gsub(/\/\//, "/") 
end 

Je sais ce qu'il fait; en quelque sorte, il renvoie l'URL correspondant à un fichier situé o un dir sur un serveur. Donc, il retourne des chaînes semblables à ceci:

Je comprends que si @url a déjà une valeur, il sera retourné et le droit ||= sera rejeté. Je comprends aussi que cela commence à créer un hachage de deux éléments. Je pense aussi que je comprends le dernier gsub; il remplace les barres obliques inverses par des barres obliques (pour faire face aux serveurs Windows, je suppose).

Ce qui m'étonne est la partie inject. Je ne suis pas capable de le comprendre. J'ai utilisé inject avant, mais celui-ci est trop pour moi. Je ne vois pas comment cela se fait avec un each, puisque je ne comprends pas ce que ça fait. J'ai modifié légèrement la fonction d'origine pour cette question; l'original provient de this jekyll file.

À la votre!

+3

« la dernier gsub, il remplace les barres obliques inversées par des barres obliques "- non, il me semble qu'il remplace les doubles barres obliques par des barres obliques. – Ken

+0

Vous avez raison - merci de le signaler. – kikito

Répondre

2
foo.inject(bar) {|result, x| f(result,x) } 

peut toujours être écrit comme:

result = bar 
foo.each {|x| result = f(result, x)} 
result 

Donc, pour votre cas, la version avec chacun ressemblerait à ceci:

result = "/:basename/" 
{ 
    "basename" => self.basename, 
    "output_ext" => self.output_ext, 
}.each {|token| 
    result = result.gsub(/:#{token.first}/, token.last) 
} 
result 

Signification: pour tous-valeur paires de clés dans le hachage, chaque occurrence de la clé dans le "/:basename/" est remplacée par la valeur.

+0

Ohh. Donc, il remplace fondamentalement ': basename' par sa valeur réelle. Je comprends maintenant. Merci! – kikito

1

scindant Peut-être le code et tordant un peu aide

options = { "basename" => self.basename, "output_ext" => self.output_ext } 

options.inject("/:basename") do |result, key_and_kalue| 
    # Iterating over the hash yields an array of two elements, which I called key_and_value 

    result.gsub(":#{key_and_value[0]}", key_and_value[1]) 
end.gsub!(//\/\/, '/') 

Fondamentalement, le code inject est itérez tous vos options et le remplacement de la valeur réelle partout où elle voit un « : touche »