The eval method will evaluate your string as Ruby code. BUT...
eval is fragile
Your string contains the return keyword, which always returns from a method call. If you eval that string inside a method, any code that comes after it will never run because the method will return. If you eval that outside of a method, you'll get a LocalJumpError exception because return is only valid inside a method. I can imagine this causing all sorts of mysterious bugs in your code.
eval is dangerous
You say the metadata comes from your side, but you're still opening up a huge failure point in your code when you eval because it could do literally anything. That one call to eval could wipe the entire disk, it could download and run an exploit, it could even rewrite your script into a malicious AI with a hatred for humanity. There is really no point in using such a powerful method when you just want to do some numerical comparison.
eval is confusing
Realistically, you're probably fine using eval. Your code will work and the world won't end. But even then it's terrible because it creates completely unreadable code. Any programmer reading your script (including yourself, six months later when you come back to fix something) will reach that eval and think "Uh... what exactly does this do?" In cases like this, you should always store as little logic in the DB as possible, and do the rest of the calculation in the code. How would you do that in this case? I can think of a few options.
Store only the intervals
With a DB schema like
table BMIIntervals (
MinValue Double,
Description String
)
You could store the rows
18.5, 'healthy'
25, 'overweight'
30, 'obese'
Then you can easily do the calculation in Ruby:
intervals = db.query("SELECT * FROM BMIIntervals ORDER BY MinValue DESC")
intervals.each { |row| return row[1] if $bmi >= row[0] }
return nil
Store only the calculation name
Or if the BMI intervals are fixed, and the metadata says what kind of calculation to do, you could simply define the calculation in Ruby:
module MetadataFuncs
def self.bmi
return 'obese' if $bmi > 30
return 'overweight' if $bmi >= 25
return 'healthy' if $bmi >= 18.5
end
end
Then your metadata string would be just "bmi" and instead of eval(metadata) you could do MetadataFuncs.send(metadata). This way you know exactly what code the metadata might call, even without seeing what data are in the database.
eval, but I would strongly caution against that right now).