Techioz Blog

ハッシュを ERB テンプレートとして使用する場合、Ruby は「エンコーディング」について不平を言います

概要

ただそれだけに

require 'erb'
a = "això és una merda <%=rand(1..20)%>"
c = {"id" => "això és una merda <%=rand(1..10)%>"}

ERB.new(a).result を実行すると、すべて問題ありません。

ERB.new(a).result
=> "això és una merda 3"

しかし、ERB.new(c).result を使用すると、Ruby はエンコーディングの問題を訴えます。

ERB.new(c).result
/usr/lib/ruby/3.0.0/erb/compiler.rb:315:in `compile': undefined method `encoding' for {"id"=>"això és una merda <%=rand(1..10)%>"}:Hash (NoMethodError)
        from /usr/lib/ruby/3.0.0/erb.rb:351:in `initialize'
        from (irb):57:in `new'
        from (irb):57:in `<main>'
        from /usr/lib/ruby/gems/3.0.0/gems/irb-1.4.2/exe/irb:11:in `<top (required)>'
        from /usr/bin/irb:25:in `load'
        from /usr/bin/irb:25:in `<main>'

私が期待した結果は次のとおりです。

{"id" => "això és una merda 3"}

c を文字列としてキャストすることもできますが、ハッシュとしてキャストしたいと考えています。

解決策

ERB は文字列に対してのみ機能します。文字列の配列や文字列のキーや値を含むハッシュなどの文字列を含む構造がある場合は、文字列を個別に処理する必要があります。

ハッシュ値を処理するには、transform_values を使用できます。これは各値をブロックに渡し、ブロックの結果で値を更新します。

require 'erb'

c = {"id" => "això és una merda <%=rand(1..10)%>"}

c.transform_values! { |str| ERB.new(str).result }

c #=> {"id"=>"això és una merda 7"}

(レシーバーを変更せずに新しいハッシュを返す非!バリアントもあります)