Reputation: 48676
i have a module that needs to save a solution(for a quiz) value. This is trivial, of course, when the solution is simply a value like '342'. However, there are cases where there are some dynamic calculations taking place. For instance, if a user enters the value 100, it could be that in order to get the correct solution, i would first have to calculate (x*2) == 300. Therefore, if x=100, the solution would be wrong.
Unluckily, i cannot store such calculations in a database(at least based on what i know). One thing that i could do is add specific solution methods for particular quizzes in my Quiz model. However, i don't like this at all. It's making the class very difficult to maintain, so i quickly abandoned that idea.
Another idea would be to save a new class object in every quiz that needs that. This class will include all the methods needed, that just verify the calculations(either with STI or a module, most probably the latter is easier). I like this idea better and i think that it's most probably what i am going to implement, but before doing so, i would like to hear your ideas about it.
How would you go about it ?
NOTICE that a big problem that arises from creating a module or a class to handle all the solutions, is the case where i would like to have multiple quiz authors in the future. If they could create their own challenges, it would be virtually impossible to create dynamic solutions for them this way. Or it would be a hell for me to supervise every such entry and manually create the needed code.
Upvotes: 1
Views: 122
Reputation: 30455
Store Ruby code in your DB as text, and run a parser over it before eval
uating it (to confirm that it only holds an arithmetic expression, and not something nasty like Dir['/**/*'].each { |f| File.delete(f) }
). You can use a tool like Treetop to build the parser. As a bonus, once you know how to use Treetop, the next time you need to build a parser, it will be easy.
Upvotes: 1
Reputation: 20408
i cannot store such calculations in a database(at least based on what i know)
Sure you can. Code is just text and ruby is a dynamic language. You could store your correct solution evaluation expression as text, then turn it into code with eval.
So, if that text field was the evaluation_expr field of a question object containing something like "(x.to_i*2) == 300" (expecting x to be the supplied answer):
evaluator = eval "lambda { |x| #{question.evaluation_expr} }"
got_it_right = evaluator.call( params[:x] )
This gives you the ability to have arbitrarily complex ruby expressions for calculating correct answers to your quiz question and store them in a database.
Unfortunately, this is also a security risk if you're accepting the entry of these expressions from untrusted users, because you are going to execute what they enter as ruby in your service. Of course that's a problem endemic to multiple quiz authors if they have to write code to express their questions.
Upvotes: 1