views:

250

answers:

3

Here's the current flow of my quiz app:

  1. users/do_program
  2. quiz_contents/view
  3. quiz_questions/do_quiz

The checking if the user has to do another module after finishing the current ones are in the quiz_contents and quiz_questions controller which I think can be improved because of the duplicate code. So what would you guys suggest?

Some info:

  • A module belongs to a program and a program has many modules.
  • A module must have a quiz_content and it may or may not have a quiz_question
  • I got code that logs if a user finishes a quiz_content in quiz_contents and code that logs if a user finishes a quiz_question in quiz_questions

P.S. Also would you guys advise that I put the content/quiz to be rendered (the id in particular) in the session?

A: 

Based on what you have up here I assume you mean there is duplicate code in quiz contents and quiz_questions. If that is correct quiz contents is the only place for the has more modules logic to be. Especially since quiz question isn't guaranteed.

Woot4Moo
Yes that is correct but I got code that logs if a user completes a quiz in the quiz_questions
baker
why is that logic there? The quiz contents should be the only place that knows if a quiz has been completed. Quiz contents should have a list of quizzes/quiz questions.
Woot4Moo
I guess that's an error in my design. After a user finishes a quiz_question where should the flow go next?i mean in what controller?
baker
Once the quiz is completed the quizContent controller should know that it is completed. Looking back at the words you used the ProgramController (if there is one) would have logic flow go into it.
Woot4Moo
A: 

Using Cake any code that is to be reused goes in the following folders.

Controllers => Components

Models => Behaviors

Views => Elements

I suggest you take a longer look at http://book.cakephp.org to familiarize yourself with the framework.

A: 

If I understand you correctly then your models are set up like so:

Program hasMany Module hasMany QuizContent hasMany QuizQuestion

or more simply:

Program hasMany Module hasMany Quiz hasMany Question

There can be quite a lot to think about in these applications, so it is hard to tell you how we might structure this without knowing the answer to more questions:

  • Can users do a quiz more than once?
  • Can users return to questions they have already answered?
  • Are the answers saved individually?
  • Do the results get saved up and then stored at the end?
  • Do the results get stored in the database?
  • Are the results simply emailed off somewhere?

Assuming you want to strictly control the question seen, not allowing users to go back using their browser controls, holding the state (incomplete quizzes) in sessions instead of the database, you might approach it like this:

class QuizController extends AppController {
    # allow user to do a quiz
    function do($id) {
        # do something with each answer submitted
        if ($this->data) {
            // validate, save to database, or store in session until the end
            $questionNumber = $this->Session->read('Quiz.question');
            $this->Session->write('Quiz.question', $questionNumber + 1);
            $this->redirect(array('action' => 'do', $id));
        }
        # get the quiz (and questions)
        $quiz = $this->Quiz->find('first', array(
            'conditions' => array('Quiz.id' => $id),
            'contain' => array('Question'), // if using Containable
        ));
        # quiz doesn't exist
        if (!$quiz) {
            $this->cakeError('error404');
        }
        # get the question number
        $questionNumber = $this->Session->read('Quiz.question');
        # quiz hasn't been started
        if (!$questionNumber) {
            $questionNumber = 1;
            $this->Session->write('Quiz.question', $questionNumber);
        }
        # get the question
        $question = Set::extract("/Question[$questionNumber]", $quiz);
        # there are no more questions
        if (!$question) {
            // finalize quiz, save to database, redirect to obvious place
            $this->Session->setFlash('Quiz complete');
            $this->redirect(array('action' => 'index', $quiz['Quiz']['id']));
        }
        # set variables to the view
        $this->set(compact('quiz', 'question'));
    }
}

Note: In the example above I renamed the models to Quiz and Question to improve readabilty.

deizel