0

Im trying to execute inline ruby from a string. The string is stored in a database as a text and is not made using ruby.

string = 'The year now is #{Time.now.year}'
puts string

That returns

=> The year now is #{Time.now.year}

I want it to return

=> The year now is 2015

Is there any method in ruby that will execute inline ruby like that?

1
  • You can look at ERB to do this, but will need to change the #{ part appropriately. And you will gain the safety from ERB as well. Commented Jul 18, 2015 at 22:33

5 Answers 5

6

Yes, the only reason yours did not work is because single quotes cause a string literal (meaning there are no escapes or embedding').

string = "The year now is #{Time.now.year}"
puts string

will work (notice the double quotes).

Edit 1:

Another solution (other than eval), is to use string interpolation.

string = 'Time is: %s' 
puts string % [Time.now.year]

So, you can substitute with the %s:

string = 'The year now is %s' 
 => "The year now is %s" 
2.2.1 :012 > string % [Time.now.year]
 => "The year now is 2015" 

More here.

Sign up to request clarification or add additional context in comments.

4 Comments

As i said, the string is loaded from a database and is not made in ruby, the above was just an example. am not able to change the original string variable.
if the database also includes the single quotes you will have to regex and replace them. Look at String#gsub for example.
am not able to change the string in the database, the stringing the database is written like it is in the original question and am not able to change it to use string interpolation.
Wow. I was so dumb. I was looking for a Ruby equivalent of eval, not even thinking there would be.
1

You can use eval to accomplish this, but be warned that treating strings in a database as code is very risky:

eval('puts "the sum of 2 and 2 is #{2+2}"')

6 Comments

How can i use the string variable in a eval like that? eval('puts "#{string}"') will give me the same as the original result
And if the answer doesn't make the point clearly enough: make sure you can trust all the incoming strings as they can contain arbitrary code that will be executed. You don't want your users erasing/modifying parts of your application, don't you? :]
I tried using eval('puts "#{string}"'), with the string from the original question( with the single quotes). It will not run the inline ruby from the original string.
@lassvi why yes, because eval takes a string of Ruby source code. Try like eval %Q("#{string}") -- and check what string exactly you are getting before executing it.
Am aware, i was just trying to say that the answer was not a solution to my question(or at least i couldn't get it to work), since am not able to change the original string. This answer is not really different from puts "the sum of 2 and 2 is #{2+2}", but am not able to place the string inside double quotes.
|
1

For string interpolation to work you have to use double quotes.. A String literal created with single quotes does not support interpolation.

string = "The year now is #{Time.now.year}"

Comments

0

You can use ERB for this.

require 'erb'

from_database = 'The time is now #{Time.new.year}'

new_string = from_database.sub(/\#\{/, '<%= ')
new_string = new_string.sub(/\}/, '%>')
puts ERB.new(new_string).run

No checks for verifying that it is string interpolation, nor checks for using String#% method.

2 Comments

That will remove all "}" from the text tho, even if it hadn't been a part of the inline ruby :/ (But it would have worked fine for the example i had in my question. But the database will contain a lot more and different text)
Yes, but you didn't ask or bring that out. The removal of that code could be temporary, though, for evaluation, you can always present the original data. This is not a great regular expression use either. I can only answer the question and hopefully not make wrong assumptions while doing so with what is presented. :)
0

I ended up making a method that will find the inline ruby and use the eval() method on each of the ruby parts.

def text(text)
    text.scan(/\#{.*?}/).each do |a|
        text = text.gsub(a,eval(a[2..-2]).to_s)
    end
    text
end
string = 'The year now is #{Time.now.year}'
puts text(string)
=> The year now is 2015

Edit:

D-side came up with a much better solution:

puts eval %Q("#{string}") 
=> The year now is 2015

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.