ruby - нужна помощь в понимании этого вопроса - PullRequest
1 голос
/ 26 июня 2010

Я хотел бы понять, как работает следующий код:

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

Я знаю, что он делает;каким-то образом он возвращает URL, соответствующий файлу, расположенному на сервере.Таким образом, он возвращает строки, подобные этой: /path/to/my/file.html

Я понимаю, что если @url уже имеет значение, оно будет возвращено, а правильное ||= будет отброшено.Я также понимаю, что это начинает создавать хэш из двух элементов.

Я также думаю, что понимаю последний gsub;он заменяет обратную косую черту на косую черту (я думаю, для работы с серверами Windows).

Что меня поражает, так это часть inject.Я не могу этого понять.Я использовал inject раньше, но этот слишком для меня.Я не понимаю, как это сделать с each, так как я не понимаю, что он делает.

Я немного изменил исходную функцию для этого вопроса;оригинал прибывает из этого файла джекила .

Приветствия!

Ответы [ 2 ]

2 голосов
/ 26 июня 2010
foo.inject(bar) {|result, x| f(result,x) }

Всегда можно записать как:

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

Так что для вашего случая версия с каждым будет выглядеть так:

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

Значение: для всех пар ключ-значение в хэше каждое вхождение ключа в "/:basename/" заменяется значением.

1 голос
/ 26 июня 2010

Возможно, разделение кода и небольшая подстройка помогут

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!(//\/\/, '/')

По сути, код внедрения выполняет итерацию по всем вашим options и заменяет действительное значение везде, где он видит ": ключ"

...