El código que cree que no funciona, sí:
var = "Value"
str = "a test Value"
p str.gsub( /#{var}/, 'foo' ) # => "a test foo"
Las cosas se ponen más interesantes si var puede contener metacaracteres de expresión regular. Si es así y desea que esos personajes mata hagan lo que suelen hacer en una expresión regular, entonces el mismo gsub funcionará:
var = "Value|a|test"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "foo foo foo"
Sin embargo, si su cadena de búsqueda contiene metacaracteres y no quiere que se interpreten como metacaracteres, utilice Regexp.escape así:
var = "*This*"
str = "*This* is a string"
p str.gsub( /#{Regexp.escape(var)}/, 'foo' )
# => "foo is a string"
O simplemente asigne a gsub una cadena en lugar de una expresión regular. En MRI> = 1.8.7, gsub tratará un argumento de reemplazo de cadena como una cadena simple, no como una expresión regular:
var = "*This*"
str = "*This* is a string"
p str.gsub(var, 'foo' ) # => "foo is a string"
(Solía ser que un argumento de reemplazo de cadena para gsub se convertía automáticamente en una expresión regular. Sé que era así en 1.6. No recuerdo qué versión introdujo el cambio).
Como se señaló en otras respuestas, puede usar Regexp.new como alternativa a la interpolación:
var = "*This*"
str = "*This* is a string"
p str.gsub(Regexp.new(Regexp.escape(var)), 'foo' )
# => "foo is a string"