2010-06-26 35 views
1

我想明白下面的代码是如何工作的:红宝石 - 需要帮助理解这个注入

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是如何实现的,因为我不明白它的作用。

我对这个问题稍微修改了原始函数;原来来自this jekyll file

干杯!

+3

“的最后一个gsub;它用斜线替换反斜杠“ - 不,它在我看来像是用斜杠替换双斜线。 – Ken 2010-06-26 16:35:10

+0

你说得对 - 感谢你指出了这一点。 – kikito 2010-06-26 18:01:58

回答

2
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/"中每个键的出现都被替换为该值。

+0

哦。所以它基本上取代了'basename'的真实价值。我现在知道了。谢谢! – kikito 2010-06-26 16:27:33

1

也许分裂代码和调整一点点帮助

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和更换实际值只要它看到一个“:关键”