如何在Ruby中将一个字符串附加到一个变量上,并将整个字符串作为一个变量进行求值



我有以下Ruby代码:

module BigTime
FOO1_MONEY_PIT = 500
FOO2_MONEY_PIT = 501

class LoseMoney
@@SiteName = 'FOO1'
@site_num = @@SiteName_MONEY_PIT
def other_unimportant_stuff
whatever
end
end
end

因此,我在这里要做的是设置SiteName,然后使用SiteName并将其与字符串_MONEY_PIT组合,这样我就可以访问FOO1_MONEY_PIT并将其内容(在本例中为500(存储在@site_num中。当然,上面的代码不起作用,但我一定有办法做到这一点?

谢谢!!

如果您想动态获取常量的值,可以使用Module#const_get:

module BigTime
FOO1_MONEY_PIT = 500
FOO2_MONEY_PIT = 501

class LoseMoney
@@SiteName = 'FOO1'
@site_num = BigTime.const_get(:"#{@@SiteName}_MONEY_PIT")
end
end

不要,在任何情况下,都要使用Kernel#evalKernel#eval在任何情况下都是极其危险的,即使攻击者能够控制部分自变量的可能性很小。

例如,如果用户可以选择网站的名称,并将其网站命名为require 'fileutils'; FileUtils.rm_rf('/'),那么Ruby将很高兴地评估该代码,就像你告诉它的那样!

Kernel#eval是非常危险的,你不应该养成只在问题上抛出eval的习惯。这是一个非常专业的工具,只有在没有其他选择的情况下(剧透提醒:几乎总是有另一个选择(,并且只有在彻底的安全审查之后才能使用。

请注意,无论是否使用eval,动态构建变量名本身就已经是一种代码气味。它几乎总是指向某个地方的设计缺陷。一般来说,几乎可以保证用数据结构替换多个变量。例如,在这种情况下,类似于以下内容:

module BigTime
MONEY_PITS = {
'FOO1' => 500,
'FOO2' => 501,
}.freeze

class LoseMoney
@@SiteName = 'FOO1'
@site_num = MONEY_PITS[@@SiteName]
end
end

您可以将其重构为使用Hash进行名称查找,并使用getter方法进行检索,以便于测试/验证。例如:

module BigTime
MONEY_PITS       = { FOO1: 500, FOO2: 501 }
MONEY_PIT_SUFFIX = '_MONEY_PIT'

class LoseMoney
@@site = :FOO1
def initialize
site_name
end
def site_name
@site_name ||= '%d%s' % [MONEY_PITS[@@site], MONEY_PIT_SUFFIX]
end
end
end
BigTime::LoseMoney.new.site_name
#=> "500_MONEY_PIT"

相关内容

最新更新