Подтвердить что ты не робот

Как сделать "позднюю" интерполяцию строк в Ruby

>> string = '#{var}'
=> "\#{var}"

>> proc = Proc.new { |var| string }
=> #<Proc:[email protected](pry):6>

>> proc.call(123)
=> "\#{var}"

Не то, что я хочу. Двойные кавычки вокруг string приводят к очевидному undefined local variable.

4b9b3361

Ответ 1

Хотя это возможно, он не будет работать так, как вы намереваетесь здесь, не используя eval, и, как правило, это плохая идея, если есть альтернатива. Хорошая новость заключается в том, что у вас есть несколько вариантов.

Наиболее простым является использование форматирования sprintf, которое упрощается с помощью метода String#%:

string = '%s'

proc = Proc.new { |var| string % var }

proc.call(123)
# => "123"

Это действительно надежный метод, так как все, что поддерживает метод .to_s, будет работать и не приведет к тому, что юнивер не сможет взорваться, если он содержит исполняемый код.

Ответ 2

В моем случае мне нужна конфигурация, хранящаяся внутри yml, с интерполяцией, но которая только интерполируется, когда мне это нужно. Принятый ответ с Proc казался мне слишком сложным.

В рубине 1.8.7 вы можете использовать синтаксис % следующим образом:

"This is a %s verb, %s" % ["nice", "woaaaah"]

При использовании по крайней мере рубина 1.9.x(или рубина 1.8.7 с i18n) существует более чистая альтернатива:

my_template = "This is a %{adjective} verb, %{super}!"

my_template % { adjective: "nice", super: "woah" }
=> "This is a nice verb, woah!"

Ответ 3

Он работает с eval:

proc = Proc.new { |var| eval(%Q{"#{string}"}) }

(Если вы доверяете значению строки.)

Ответ 4

Вы можете достичь СУХОЙ, которую вы ищете, создавая функцию "curried" (то есть: Proc, которая возвращает Proc), где внутренняя функция содержит базовую строку с переменными для каждой части, которая отличается.

Исправьте меня, если я ошибаюсь, но в вашем коде за вашей прокомментированной ссылкой единственное различие между двумя строками - это единственный char в конце. (Даже если это не так, вы можете использовать эту технику для достижения той же цели). Вы можете создать Proc, который возвращает Proc, который содержит вашу строку, затем дважды вызовите внешний Proc для двух ваших завершающих символов:

rails_root = "whatever" # Not variant for the string
rails_env_prompt = "whatever" #not variant for the string

spec = Proc.new { |tail_char| 
  Proc.new {|obj, nest_level, *| 
    "#{rails_root} #{rails_env_prompt} #{obj}:#{nest_level}#{tail_char} "
  }
}

Pry.config.prompt = [ spec.call(">"), spec.call("*") ]  

Pry.config.prompt[0].call("My obj", "My Nest Level")
# result: "whatever whatever My obj:My Nest Level> "

Ответ 5

Вам нужно определить строку, несущую интерполяцию вне вашего Proc?

proc = Proc.new { |var| "#{var}" }
proc.call(123) # "123"

Это было бы самым чистым способом, я думаю.