Ruby on rails 轨道编号\u到\u百分比和子轨道行为

Ruby on rails 轨道编号\u到\u百分比和子轨道行为,ruby-on-rails,ruby,regex,Ruby On Rails,Ruby,Regex,我正在尝试将较大的%数字替换为较短的版本(10000%->10k%)。通常代码可以工作,但如果使用了number\u to\u percentage,它将停止工作(使用完全相同的字符串) 这是什么原因造成的?有什么想法吗?关键区别在于: "10000.000%".class #=> String number_to_percentage(10000).class # => ActiveSupport::SafeBuffer ActiveSupport::SafeBuffer是Str

我正在尝试将较大的%数字替换为较短的版本(10000%->10k%)。通常代码可以工作,但如果使用了
number\u to\u percentage
,它将停止工作(使用完全相同的字符串)

这是什么原因造成的?有什么想法吗?

关键区别在于:

"10000.000%".class #=> String
number_to_percentage(10000).class # => ActiveSupport::SafeBuffer
ActiveSupport::SafeBuffer
String
的子类,包含
不安全字符串方法的概念(包括
sub
gsub
)。这个概念对于rails视图(通常使用
number\u to\u percentage
)在安全性方面非常有用;防止XSS漏洞

解决方法是将变量显式转换为
字符串

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
返回常规
字符串

,并对该问题进行更详细的说明

或者,您也可以这样编写代码,它可以按预期工作:

number_to_percentage(10000).sub(/(\d\d)\d\d\d(?:[.,]\d+)?%$/, '\1k%')
#=> "10k%"

实际上我更喜欢这种方法,因为您不再依赖于对(非线程安全)全局变量的修改。

因为number\u to\u percentage返回的是ActiveSupport::SafeBuffer,而不是字符串

helper.number_to_percentage(10000).class # => ActiveSupport::SafeBuffer

ActiveSupport::SafeBuffer(String的一个子类)对sub这样的不安全方法有一些神奇的作用。这就是为什么你会有一些惊喜。

你的Ruby和Rails版本是什么?它在Ruby 2.4.1p111和Rails 5.1.3中工作。@GregNavis你确定吗??我发现的一件事是,如果您先运行
“10000.000%”。sub(…)
,然后设置
$1
。所以,
number\u to\u percentage(10000).sub(…)
如果您先运行第一个方法,它就会工作!ruby 2.3.1和rails 5.1.2良好的性能,@TomLord。这正是我所做的。谢谢,我也找到了使用\1的方法,但仍然很好奇为什么原始代码不起作用(但使用文字!)@valodzka。
helper.number_to_percentage(10000).class # => ActiveSupport::SafeBuffer