Passing a method for subsequent interpolation

Is it possible to pass a string to a method in ruby ​​and use this method to interpolate this string?

I have something like this:

do_a_search("location = #{location}")
...
def do_a_search(search_string)
  location = .... #get this from another source
  Model.where(search_string)
end

Context is RoR, but it is a common ruby ​​question that I think. I understand that the above example seems a bit confusing, but I'm trying to reorganize a bunch of very repetitive methods.

The problem is that if I put the string in interpolation in double quotes, the location does not exist when the method is called, if I put it in single quotes, it will never be interpolated ...

What I really want to do is put it in single quotes and interpolate it later. I don’t think it is possible, or am I missing something?

edit: to be clear (as I think I have simplified what I'm trying to do above), one of the problems is that I can name this method in several contexts; Maybe I really want to call

do_a_search("country = #{country}")

or even

do_a_search("country = #{country} AND location = #{location})

(the country also exists as a local var in my method). Therefore, I want to pass everything necessary for replacement in the method call

I think the facets gem String.interpolate method will solve my problem, but it does not work in rails 4

+4
source share
4 answers

Used for this purpose %. First create a line:

s = "location = %{location}"

Later you can apply to it %:

s % {location: "foo"} # => "location = foo"

If you do not need to specify parameter (s), then this is simpler:

s = "location = %s"
s % "foo" # => "location = foo"
+9
source

, Facets Gem , , , rails 4

String :

class String
  def self.interpolate(&str)
    eval "%{#{str.call}}", str.binding
  end
end

, , - , , , , , , , "", .

+2

, , , , sprintf %.

do_a_search("location = %s")
...
def do_a_search(search_string)
  location = .... #get this from another source
  Model.where(search_string % location)
end

, , Hash named.

do_a_search("location = %{location}")
...
def do_a_search(search_string)
  location = .... #get this from another source
  Model.where(search_string % {location: location})
end
+1

You can later link the extrapolation with bindingand 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"

Or you can directly use eval:

def do_a_search(search_string)
  location = 'this'
  eval search_string, binding
end

do_a_search('"location = #{location}"')
# => "location = this"

This, of course, will be acceptable only if the lines you get in do_a_searchare reliable and / or sanitized.

0
source

Source: https://habr.com/ru/post/1538621/


All Articles