将方法传递给稍后要插入的字符串

时间:2014-04-29 17:30:36

标签: ruby-on-rails ruby

是否可以将字符串传递给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中不起作用

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)

您可以使用bindingERB延迟绑定外推:

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收到的字符串被信任和/或消毒时,这才是可以接受的。