我正在尝试将大%的数字替换为更短的版本(10000% -> 10k%)。通常,代码可以工作,但如果number_to_percentage使用,则停止工作(使用完全相同的字符串)。
Loading development environment (Rails 5.1.2)
2.3.1 :001 > "10000.000%".bytes
=> [49, 48, 48, 48, 48, 46, 48, 48, 48, 37]
2.3.1 :002 > helper.number_to_percentage(10000).bytes
=> [49, 48, 48, 48, 48, 46, 48, 48, 48, 37] # totally same
2.3.1 :003 > helper.number_to_percentage(10000).sub(/(\d\d)\d\d\d(?:[.,]\d+)?\%$/){ "#{$1}k%" }
=> "k%" # doesn't work
2.3.1 :004 > "10000.000%".sub(/(\d\d)\d\d\d(?:[.,]\d+)?\%$/){ "#{$1}k%" }
=> "10k%" # works是什么导致了这一切?有什么想法吗?
发布于 2018-01-10 12:40:20
关键的区别是:
"10000.000%".class #=> String
number_to_percentage(10000).class # => ActiveSupport::SafeBufferActiveSupport::SafeBuffer是String的一个子类,包含UNSAFE_STRING_METHODS (包括sub和gsub)的概念。这个概念对于rails视图(这是通常使用number_to_percentage的地方)在安全性方面是有用的;防止XSS漏洞。
解决方法是显式地将变量转换为String。
number_to_percentage(10000).to_str.sub(/(\d\d)\d\d\d(?:[.,]\d+)?\%$/){ "#{$1}k%" }
=> "10k%"(请注意,它是to_str,而不是to_s!to_s只返回self,即ActiveSupport::SafeBuffer的实例;而to_str则返回常规String。)
This article和this rails issue将更详细地讨论这个问题。
或者,您可以像这样编写代码,它的工作方式与预期的一样:
number_to_percentage(10000).sub(/(\d\d)\d\d\d(?:[.,]\d+)?%$/, '\1k%')
#=> "10k%"实际上,我更喜欢这种方法,因为您不再依赖于对(非线程安全)全局变量的修改。
发布于 2018-01-10 12:47:30
因为number_to_percentage返回一个ActiveSupport::SafeBuffer,而不是一个字符串。
helper.number_to_percentage(10000).class # => ActiveSupport::SafeBufferActiveSupport::SafeBuffer (它是字符串的子类)在一些不安全的方法(如sub )中发挥了一些神奇的作用。所以你才会有惊喜。
https://stackoverflow.com/questions/48187312
复制相似问题