开发者

ruby - need help understanding this inject

开发者 https://www.devze.com 2023-01-04 16:39 出处:网络
I\'d like to understand how the following code works: def url @url ||= { "basename" => self.basename,

I'd like to understand how the following code works:

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

I know what it does; somehow it returns the url corresponding to a file located o a dir on a server. So it returns strings similar to this: /path/to/my/file.html

I understand that if @url already has a value, it will be returned and the right ||= will be discarded. I also understand that this begins creating a hash of two elements.

I also think I understand the last gsub; it replaces backslashes by slashes (to cope with windows servers, I guess).

What amazes me is the inject part. I'm not able to understand it. I have used inject before, but this one is too much for me. I don't see how this be done with an each, sinc开发者_StackOverflow社区e I don't understand what it does.

I modified the original function slightly for this question; the original comes from this jekyll file.

Cheers!


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

Can always be written as:

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

So for your case, the version with each would look like this:

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

Meaning: for all key-value-pairs in the hash, each occurrence of the key in the "/:basename/" is replaced with the value.


Perhaps splitting the code and tweaking a little helps

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

Basically, the inject code is iterating over all your options and replacing for the actual value wherever it sees a ":key"

0

精彩评论

暂无评论...
验证码 换一张
取 消