当我生成视图中提供的哈希时,如何覆盖 ActiveSupport::SafeBuffer
How do I override ActiveSupport::SafeBuffer when I yield a hash provided in a view
我的 profile.html.erb
提供了 layout.html.erb 上游的散列,以包含在元数据中
<% provide(:twitter, { %>
<% card: 'summary', %>
<% site: '@twitter', %>
<% title: 'Lorem ipsum', %>
<% description: 'Non sequitar', %>
<% image: gravatar_for(@user, { size: 150 } )%>
<% }) %>
然后 layout.html.erb
应该对此进行迭代并创建元标记:
<% yield(:twitter).each do |key, value|%>
<meta name="twitter:#{key}" content="#{value}" />
<% end %>
但是,它给了我错误 undefined method 'each' for #<ActiveSupport::SafeBuffer:0x007f8d616e5870>
,并且在用 byebug
检查了 yield(:twitter)
之后,我看到我产生了一个 ActiveSupport::SafeBuffer
:[=22= 的实例]
(byebug) hash = yield(:twitter)
"{:card=>"summary", :site=>"@twitter", :title=>"Lorem ipsum", :description=>"Non sequitar", :image=>"https://secure.gravatar.com/avatar/a937016807c66d89d0a62d7a1b235533?s=150"}"
(byebug) hash.class
ActiveSupport::SafeBuffer
我可以将字符串评估为散列,但 ActiveSupport::SafeBuffer
对其进行编码 html 是安全的,并且没有办法将原始字符串取回。有没有更聪明的方法来做到这一点,还是我必须用一个助手将字符串转换回哈希,然后 eval()
将它变成 has?
我用以下方法修复了它:
<% twitter_tags = String.new yield(:twitter)%>
<% twitter_tags = eval ( CGI.unescapeHTML( twitter_tags ) ) %>
<% twitter_tags.each do |key, value|%>
<%= tag(:meta, name: "twitter:#{key}", content: (value) )%>
<% end %>
恕我直言,这是一种极其丑陋的解决问题的方法。我会写一个帮助程序来从视图中删除大部分内容,但是,如果您有更优雅的解决方案,请分享它,我会接受您的回答而不是我的。
默认情况下,所有提供的值都是 ActiveSupport::SafeBuffer
的实例,这会将其转换为字符串,并再次将其计算为散列。
由于提供需要字符串或块,因此最好在帮助程序中创建元标记并将其作为字符串参数传递。
module TwitterHelper
def twitter_meta_tags(hash)
hash.each_with_object([]) do |(key, value), array|
a.push( tag(:meta, { name: "twitter:#{k}", content: v }, false, false ) )
end.join("\n").html_safe
# not sure if that last html_safe is really needed.
end
end
下游视图:
<%
provide(:twitter, twitter_meta_tags({
foo: "bar"
}));
%>
布局:
<%= yield(:twitter) %>
使用部分
另一种选择是使用部分并将块而不是字符串传递给 provide
:
<% # app/views/twitter/_meta_tags.html.erb %>
<% hash.each do |key, value|%>
<meta name="twitter:#{key}" content="#{value}" />
<% end %>
下游视图:
<% provide(:twitter) do %>
<%= render partial: "twitter/meta_tags", hash: {
card: 'summary',
site: '@twitter',
title: 'Lorem ipsum',
description: 'Non sequitar',
image: gravatar_for(@user, { size: 150 } )
} %>
<% end %>
布局:
<%= yield(:twitter) %>
我的 profile.html.erb
提供了 layout.html.erb 上游的散列,以包含在元数据中
<% provide(:twitter, { %>
<% card: 'summary', %>
<% site: '@twitter', %>
<% title: 'Lorem ipsum', %>
<% description: 'Non sequitar', %>
<% image: gravatar_for(@user, { size: 150 } )%>
<% }) %>
然后 layout.html.erb
应该对此进行迭代并创建元标记:
<% yield(:twitter).each do |key, value|%>
<meta name="twitter:#{key}" content="#{value}" />
<% end %>
但是,它给了我错误 undefined method 'each' for #<ActiveSupport::SafeBuffer:0x007f8d616e5870>
,并且在用 byebug
检查了 yield(:twitter)
之后,我看到我产生了一个 ActiveSupport::SafeBuffer
:[=22= 的实例]
(byebug) hash = yield(:twitter)
"{:card=>"summary", :site=>"@twitter", :title=>"Lorem ipsum", :description=>"Non sequitar", :image=>"https://secure.gravatar.com/avatar/a937016807c66d89d0a62d7a1b235533?s=150"}"
(byebug) hash.class
ActiveSupport::SafeBuffer
我可以将字符串评估为散列,但 ActiveSupport::SafeBuffer
对其进行编码 html 是安全的,并且没有办法将原始字符串取回。有没有更聪明的方法来做到这一点,还是我必须用一个助手将字符串转换回哈希,然后 eval()
将它变成 has?
我用以下方法修复了它:
<% twitter_tags = String.new yield(:twitter)%>
<% twitter_tags = eval ( CGI.unescapeHTML( twitter_tags ) ) %>
<% twitter_tags.each do |key, value|%>
<%= tag(:meta, name: "twitter:#{key}", content: (value) )%>
<% end %>
恕我直言,这是一种极其丑陋的解决问题的方法。我会写一个帮助程序来从视图中删除大部分内容,但是,如果您有更优雅的解决方案,请分享它,我会接受您的回答而不是我的。
默认情况下,所有提供的值都是 ActiveSupport::SafeBuffer
的实例,这会将其转换为字符串,并再次将其计算为散列。
由于提供需要字符串或块,因此最好在帮助程序中创建元标记并将其作为字符串参数传递。
module TwitterHelper
def twitter_meta_tags(hash)
hash.each_with_object([]) do |(key, value), array|
a.push( tag(:meta, { name: "twitter:#{k}", content: v }, false, false ) )
end.join("\n").html_safe
# not sure if that last html_safe is really needed.
end
end
下游视图:
<%
provide(:twitter, twitter_meta_tags({
foo: "bar"
}));
%>
布局:
<%= yield(:twitter) %>
使用部分
另一种选择是使用部分并将块而不是字符串传递给 provide
:
<% # app/views/twitter/_meta_tags.html.erb %>
<% hash.each do |key, value|%>
<meta name="twitter:#{key}" content="#{value}" />
<% end %>
下游视图:
<% provide(:twitter) do %>
<%= render partial: "twitter/meta_tags", hash: {
card: 'summary',
site: '@twitter',
title: 'Lorem ipsum',
description: 'Non sequitar',
image: gravatar_for(@user, { size: 150 } )
} %>
<% end %>
布局:
<%= yield(:twitter) %>