# Penalties of using an eval on every request

**URL:** <https://www.ruby-forum.com/t/penalties-of-using-an-eval-on-every-request/58562>\
**Category:** Rails\
**Created:** [April 23, 2006, 8:43am UTC](https://www.ruby-forum.com/t/penalties-of-using-an-eval-on-every-request/58562 "2006-04-23T08:43:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![bluetrust](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/8e7dd6/32.png) [@bluetrust](https://www.ruby-forum.com/u/bluetrust)\
**Post date:** [April 23, 2006, 8:43am UTC](https://www.ruby-forum.com/t/penalties-of-using-an-eval-on-every-request/58562/1 "2006-04-23T08:43:31Z")

</div>

Hello RoR!

I’m building a rails app for hosting multi-page surveys. I set up  
questionnaire, question, and question\_component models. Now I’m  
initializing them with some data.

survey.rb  
q1 = Question.new “q1”  
q1.quote “Welcome to a test of the new interviewing system.”

q2 = Question.new “q2”  
q2.quote “Do you like pie?”  
q2.single 1 =\> “Yes”, 2 =\> “No”  
q2.validation\_block = Proc.new { [1,2].include?  
@interview.answers[“2”] }

questionnaire.questions.concat [q1, q2]

– Real-life questionnaires can be thousands of questions long!

How horrible would it be if I initialized the questionnaire.questions  
object, on each request, by reading survey.rb from disk and evaling it?

Thanks for your time!

- Mike

---

<div class="post-metadata">

**Author:** ![bluetrust](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/8e7dd6/32.png) [@bluetrust](https://www.ruby-forum.com/u/bluetrust)\
**Post date:** [April 23, 2006, 9:52am UTC](https://www.ruby-forum.com/t/penalties-of-using-an-eval-on-every-request/58562/2 "2006-04-23T09:52:03Z")

</div>

> > > > > “Michael” == Michael J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> – Real-life questionnaires can be thousands of questions long!

> How horrible would it be if I initialized the questionnaire.questions  
> object, on each request, by reading survey.rb from disk and evaling it?

## Really horrible. Why don’t you store the populated questions in the database?

```
	     Calle D. <removed_email_address@domain.invalid>
	 http://www.livejournal.com/users/cdybedahl/
"Ah, optimism. I remember optimism." -- Anya, Buffy the Vampire 

```

Slayer

---

<div class="post-metadata">

**Author:** ![bluetrust](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/8e7dd6/32.png) [@bluetrust](https://www.ruby-forum.com/u/bluetrust)\
**Post date:** [April 24, 2006, 7:42pm UTC](https://www.ruby-forum.com/t/penalties-of-using-an-eval-on-every-request/58562/3 "2006-04-24T19:42:25Z")

</div>

Calle D. wrote:

> > > > > > “Michael” == Michael J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:
> 
> > – Real-life questionnaires can be thousands of questions long!
> 
> > How horrible would it be if I initialized the questionnaire.questions  
> > object, on each request, by reading survey.rb from disk and evaling it?
> 
> ## Really horrible. Why don’t you store the populated questions in the database?
> 
> ```
> Calle D. <removed_email_address@domain.invalid>
> http://www.livejournal.com/users/cdybedahl/
> "Ah, optimism. I remember optimism." -- Anya, Buffy the Vampire 
> 
> ```
> 
> Slayer

That’s a good question: why not initialize it once and then store the  
populated questions in the database?

That’s what I was doing, and it worked just fine, until I added  
procedures (proc/lambda) for validation and branching code. Procs seem  
really useful under the problem at hand, but they make the questions  
unserializable.

Here’s an example of some of the procs I use:

q2.validation\_block = Proc.new { [1,2].include?  
@interview.answers[“q2”] }

q2.after\_block = Proc.new do  
if @interview.answers[“q2”] == 1  
@interview.skip “q3”  
else  
@interview.skip “q4”  
end  
end

So in the controller it lets me do things like this:

if current\_question.validates?  
current\_question.after\_block.call  
render …next question…  
else  
render …same question…  
end

I feel like I’m being a moron and should stick the questionnaire data in  
a require, but that’s just for entire modules, right?

---

<div class="post-metadata">

**Author:** ![bluetrust](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/8e7dd6/32.png) [@bluetrust](https://www.ruby-forum.com/u/bluetrust)\
**Post date:** [April 25, 2006, 10:26am UTC](https://www.ruby-forum.com/t/penalties-of-using-an-eval-on-every-request/58562/4 "2006-04-25T10:26:17Z")

</div>

> > > > > “Michael” == Michael J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> That’s what I was doing, and it worked just fine, until I added  
> procedures (proc/lambda) for validation and branching code. Procs seem  
> really useful under the problem at hand, but they make the questions  
> unserializable.

They also make your questions sound more like full-on model classes  
than as instances of the same model class. Have you considered making  
a general Question class and then subclasses of that for each variant  
of code you need?

> I feel like I’m being a moron and should stick the questionnaire data in  
> a require, but that’s just for entire modules, right?

## It’s for including code, so I can’t see why you wouldn’t do it that way. If you can load all your questions once at startup, it should work fine.

```
	     Calle D. <removed_email_address@domain.invalid>
	 http://www.livejournal.com/users/cdybedahl/
 "Last week was a nightmare, never to be repeated - until this week"
			-- Tom, a.s.r

```

---

<div class="post-metadata">

**Author:** ![bluetrust](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/8e7dd6/32.png) [@bluetrust](https://www.ruby-forum.com/u/bluetrust)\
**Post date:** [April 25, 2006, 3:06am UTC](https://www.ruby-forum.com/t/penalties-of-using-an-eval-on-every-request/58562/5 "2006-04-25T03:06:05Z")

</div>

Michael J. wrote:

> Hello RoR!
> 
> I’m building a rails app for hosting multi-page surveys. I set up  
> questionnaire, question, and question\_component models. Now I’m  
> initializing them with some data.
> 
> survey.rb  
> q1 = Question.new “q1”  
> q1.quote “Welcome to a test of the new interviewing system.”
> 
> q2 = Question.new “q2”  
> q2.quote “Do you like pie?”  
> q2.single 1 =\> “Yes”, 2 =\> “No”  
> q2.validation\_block = Proc.new { [1,2].include?  
> @interview.answers[“2”] }
> 
> questionnaire.questions.concat [q1, q2]
> 
> – Real-life questionnaires can be thousands of questions long!
> 
> How horrible would it be if I initialized the questionnaire.questions  
> object, on each request, by reading survey.rb from disk and evaling it?

Hello Michael,

I’m also working on a “questionnaire” system. The solution I came up  
with is to store the definition of each question in a separate file (in  
the file system). In addition, you have a “map” file which defines the  
overall sequence of questions – each question being uniquely identified  
by its name for example. This way you only need to read in one question  
at a time – and in such a system each request usually relates to just  
one question. This avoids the overhead of reading the entire  
questionnaire definition for each request. After each request you can  
allow the question object to be discarded provided you have first saved  
the user’s answer data. All you need to preserve between requests is the  
“map” structure (which can be serialised) and the user response data  
(which can be serialised or put in a database record, etc).

One reference I have found useful is SCORM (google for it). SCORM is a  
standardised way of looking at the architecture of online learning  
activities – and questionnaires are very similar.

If you want to clean up your question definitions, this article about  
domain specific languages in Ruby is worth reading:

[http://jamis.jamisbuck.org/articles/2006/04/20/writing-domain-specific-languages](http://jamis.jamisbuck.org/articles/2006/04/20/writing-domain-specific-languages)

Paul Howson  
(Qld Australia)
