简体   繁体   English

带子索的字符串插值

[英]String interpolation with subhashes

In my code I want to use string interpolation for an email subject I am generating. 在我的代码中,我想对我正在生成的电子邮件主题使用字符串插值。

output = "this is my %{title}" % {title: "Text here"}

This works as expected, but is there a way to use hashes inside of hashes and still be able to use string interpolation? 这可以按预期工作,但有没有办法在哈希中使用哈希并仍然能够使用字符串插值?

It would be awesome if I could do something like: 如果我可以这样做,那将是非常棒的:

output = "this is my %{title.text}" % {title: {text: "text here"}}

In Ruby 2.3, sprintf checks the hash's default value, so you could provide a default_proc to dig up the nested value: 在Ruby 2.3中, sprintf检查哈希的默认值,因此您可以提供default_procdig嵌套值:

hash = {title: {text: "text here"}}
hash.default_proc = proc { |h, k| h.dig(*k.to_s.split('.').map(&:to_sym)) }

"this is my %{title.text}" % hash
#=> "this is my text here"

Kind of hacky, but it seems to work. 有点hacky,但它似乎工作。

I don't think this is possible with % method. 我认为这不可能用%方法。 You'd have to use regular Ruby interpolation with "#{}" . 你必须使用常规的Ruby插值"#{}" I'd also point out that you can use OpenStruct . 我还要指出你可以使用OpenStruct

title = OpenStruct.new(text: 'text here')

output = "this is my #{title.text}" 

It's actually not hard to make this work if you write a simple utility method to "squash" a nested Hash's keys, eg: 如果你编写一个简单的实用工具方法来“挤压”嵌套的Hash密钥,实际上并不难做到这一点,例如:

def squash_hash(hsh, stack=[])
  hsh.reduce({}) do |res, (key, val)|
    next_stack = [ *stack, key ]
    if val.is_a?(Hash)
      next res.merge(squash_hash(val, next_stack))
    end
    res.merge(next_stack.join(".").to_sym => val)
  end
end

hsh = { foo: { bar: 1, baz: { qux: 2 } }, quux: 3 }

p squash_hash(hsh)
# => { :"foo.bar" => 1, :"foo.baz.qux" => 2, :quux => 3 }

puts <<END % squash_hash(hsh)
foo.bar: %{foo.bar}
foo.baz.qux: %{foo.baz.qux}
quux: %{quux}
END
# => foo.bar: 1
#    foo.baz.qux: 2
#    quux: 3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM