2014-07-10 3 views
5

je besoin d'une méthode par une chaîne d'entrée pour faire un calcul, comme celui-cichaîne Convertir en fonction en ruby-on-rails

function = "(a/b)*100" 
a = 25 
b = 50 
function.something 
>> 50 

ont une méthode pour cela?

+1

Si vous êtes trop confiant, utilisez 'Kernel # eval' ... Comme' eval (fonction) '. –

+3

Je ne sais pas ce que vous voulez en faire, mais s'il vous plaît ** ne faites pas confiance à l'entrée de l'utilisateur **, c'est-à-dire n'utilisez pas quelque chose provenant des utilisateurs finaux dans votre "chaîne à évaluer". – MrYoshiji

+0

Ma suggestion honnête est .. S'il vous plaît changer votre interface, de sorte que vous n'avez pas besoin d'utiliser un tel # # eval. Pensez-y d'une autre façon. Aucun point d'utiliser une famille * eval * en faisant un tel * math *. –

Répondre

7

Vous pouvez utiliser instance_eval:

function = "(a/b)*100" 
a = 25.0 
b = 50 

instance_eval function 
# => 50.0 

Sachez cependant que l'utilisation eval est intrinsèquement précaire, surtout si vous utilisez l'entrée externe, car il peut contenir du code malveillant injecté.

Notez également que a est réglé sur 25.0 au lieu de 25, car si elle est un entier a/b entraînerait 0 (entier).

+0

+1 pour une solution simple et claire –

+5

Attention, cela peut faire quoi que ce soit dans votre application, ex: User.destroy_all. –

+0

@BrunoMuceliniMergen, oui, j'ai mentionné que dans ma réponse –

2

Vous pouvez jeter un coup d'œil à la gemme dentaku, qui est un analyseur et un évaluateur de formules mathématiques et logiques.

require 'dentaku' 

a = 25.0 
b = 50 
function = "(#{a}/#{b})*100" 

calculator = Dentaku::Calculator.new 
calculator.evaluate(function) # => 50.0 

N'utilisez pas eval.

+1

"Ne pas utiliser d'évaluation." Il y a un temps et un lieu pour 'eval'. 'eval' va bien quand vous * savez * ce qui est eval'd. Si la chaîne est créée par le script et est basée sur des données aseptisées, elle est sûre. C'est dangereux quand les données sont inconnues/non-aseptisées. –

+0

@theTinMan Vous avez raison. Mais je vais toujours pratiquer la bonne habitude de ne pas utiliser 'eval', et je chercherai un * math parser *, comme celui que j'ai montré ici. Je ne supporte pas, 'eval' en utilisant, où il y a un moyen. '# instance_eval' ou' # instance_exec' a d'autres buts, mais ce n'est pas le cas pour les calculs mathématiques. De toute façon c'est une question de goût, d'éviter le risque. –