将方法传递给稍后要插入的字符串
是否可以将字符串传递给ruby中的方法并使该方法插入该字符串?
我有这样的想法:
do_a_search("location = #{location}") ... def do_a_search(search_string) location = .... #get this from another source Model.where(search_string) end
上下文是RoR,但我认为这是一个普遍的ruby问题。 我意识到上面的例子看起来有点复杂,但我正在尝试重构一堆非常重复的方法。
问题是,如果我将字符串插入双引号中,则在调用方法时位置不存在,如果我将其放在单引号中,它将永远不会被插值…
我真正想要做的是将它放在单引号中并稍后进行插值。 我不认为这是可能的,或者我错过了什么?
编辑:要清楚(因为我认为我已经过度简化了我上面要做的事情),其中一个问题是我可能想在多个上下文中调用此方法; 我可能真的想打电话
do_a_search("country = #{country}")
甚至
do_a_search("country = #{country} AND location = #{location})
(国家也作为我方法中的局部变量存在)。 因此,我希望在方法调用中传递替换所需的所有内容
我认为facet gem中的String.interpolate方法可以解决我的问题,但它在rails 4中不起作用
为此目的,使用%
。 首先,创建一个字符串:
s = "location = %{location}"
之后,您可以将%
应用于它:
s % {location: "foo"} # => "location = foo"
如果您不必为参数命名,那么它更简单:
s = "location = %s" s % "foo" # => "location = foo"
正如我上面提到的, Facets Gem会对此有所帮助,但似乎不适用于rails 4
但是它扩展String的代码非常简单:
class String def self.interpolate(&str) eval "%{#{str.call}}", str.binding end end
我认为实施然后在方法中使用它是做我正在寻找的最明智的方式,但我会接受Sawa的回答,因为正如Paul Richter和Chuck所指出的那样,我认为它会起作用,但是如果我没有完全接听电话那么“爆炸”的风险。
你想要的基本上是一个格式字符串,所以我认为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
您可以使用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
中收到的字符串被信任和/或清理时, do_a_search
是可接受的。