是否可以将字符串传递给ruby中的方法并使该方法插入该字符串?
我有这样的想法:
do_a_search("location = #{location}")
...
def do_a_search(search_string)
location = .... #get this from another source
Model.where(search_string)
end
上下文是RoR,但我认为这是一个普遍的红宝石问题。我意识到上面的例子看起来有点复杂,但我正在尝试重构一堆非常重复的方法。
问题在于,如果我将字符串插入双引号中,则在调用方法时位置不存在,如果我将其放在单引号中,它将永远不会被插值...
我真正想做的是将它放在单引号中并稍后进行插值。我不认为这是可能的,或者我错过了什么?
编辑要明确(因为我认为我已经过度简化了我上面要做的事情),其中一个问题是我可能想要在多个上下文中调用此方法;我可能真的想打电话给
do_a_search("country = #{country}")
甚至
do_a_search("country = #{country} AND location = #{location})
(国家/地区也作为我方法中的本地变量存在)。因此,我想在我的方法调用
中传递替换所需的所有内容我认为facets gem中的String.interpolate方法可以解决我的问题但是它在rails 4中不起作用
答案 0 :(得分:9)
为此目的,使用%
。首先,创建一个字符串:
s = "location = %{location}"
稍后,您可以将%
应用于它:
s % {location: "foo"} # => "location = foo"
如果您不必命名参数,则更简单:
s = "location = %s"
s % "foo" # => "location = foo"
答案 1 :(得分:2)
正如我上面提到的,Facets Gem会对此有所帮助,但似乎无法在rails 4中使用
然而,扩展String的代码非常简单:
class String
def self.interpolate(&str)
eval "%{#{str.call}}", str.binding
end
end
我认为实施&然后在方法中使用它是做我正在寻找的最明智的方式,但我会接受Sawa的回答,因为正如Paul Richter& Chuck指出,我认为这会有所作为,但如果我没有完全接听电话那就冒“爆炸”的风险。
答案 2 :(得分:1)
你想要的基本上是一个格式字符串,所以我认为你可以通过sprintf或%
更好地服务。
do_a_search("location = %s")
...
def do_a_search(search_string)
location = .... #get this from another source
Model.where(search_string % location)
end
如果您想要插入多个内容并且不想强制执行订单,则可以使用哈希和命名说明符。
do_a_search("location = %{location}")
...
def do_a_search(search_string)
location = .... #get this from another source
Model.where(search_string % {location: location})
end
答案 3 :(得分:0)
您可以使用binding
和ERB
延迟绑定外推:
require 'erb'
def do_a_search(search_string)
location = 'this'
ERB.new(search_string).result(binding)
end
do_a_search('location = <%= location %>')
# => "location = this"
或者,您可以直接使用eval
:
def do_a_search(search_string)
location = 'this'
eval search_string, binding
end
do_a_search('"location = #{location}"')
# => "location = this"
当然,只有当您在do_a_search
收到的字符串被信任和/或消毒时,这才是可以接受的。