Ufront - using a model (which holds data) between several requests

186 views Asked by At

I am not so sure how to implement a model which can share its state between several requests. I mean a model which holds a set of data not only a model which describes how the data looks like.

An example would be a quizz or a survey where the user steps through a couple of questions and each question is requested via an next or prev route in a subcontroller where the response or selected value of the user would be stored in a model and only at the end saved (to a db or a file).

I can inject the model to the UfrontJSApplication, and have then access in every route in the controller but then my api doesn't know anything about it. I can't store it inside the api because it's recreated on every new request.

The idea is like this:

class SurveyController extends Controller {

    @inject public var surveyApi:app.api.AsyncSurveyApi;
    @inject public var surveyModel:SurveyModel; // injected into UfrontJsApplication

    @:route("/nextQuestion")
    public function doNextQuestions(args: { index:Int } ) {
        surveyModel.add(/*an item from the post vars*/);

        return surveytApi.getNextQuestion(args.index) >> function(questionVO):ViewResult {
              return new ViewResult(questionVO) );
        }; 
    }

    //called after the last question via a button finish for example
    @:route("/saveSurvey")
    public function doSaveSurvey() {

        //save the entire model filled up by every doNextQuestion route
        return surveytApi.save(/*can't pass my model here*/) >> function(message):RedirectResult {
              return new RedirectResult(message) );
        }; 
    }
}

Any thoughts about this? Maybe a solution should be implemented completely differently?

P.S. Perhaps someone with at least 1500 reputation can create an 'ufront' tag ?

3

There are 3 answers

0
Jason O'Neil On BEST ANSWER

A few options...

  1. Use a UFHttpSession. You might need to create one that works client side, but it could just be a very simple Map<String,Dynamic>. You could save the half-finished survey to the session in-between requests.

  2. Save the model to the server API on each request, in it's half finished state.

  3. If you're going to keep with the building of the survey client-side, before sending to the survey, you have to make the SurveyModel persist between requests. You could do this using dependency injection like you have, or just by keeping it in a static variable that you can access between requests. Either way you should be able to access the model in your doSaveSurvey() function, and send it to the API with surveyApi.save(mySurvey).

    If there's an issue with that, it would be good to see some code for what SurveyModel and SurveyApi look like, and what the error message is.

1
bubblebenj On

I don't have a technical answer but maybe a pointer to where to look at.

You should look into e-learning standards to see how they propose the implementation of suck models:

  • Current gen is SCORM 2004 (Used by all e-learning companies)
  • Next gen is xAPI (formerly TinCan)

The former use a "SCORM API wrapper" (js) to store data and send them to a "LMS" on the application request. It needs to be online to work.

The ladder is a lot more flexible, allows offline storing, doesn't require a LMS... I don't know it well yet but e-learning companies are moving toward it.

You can find infos about the standards here http://www.adlnet.gov/index.html#home-capabilities

NB: I think the data you want to store in the API is called "tracking" in the e-learning world.

Hope it can help you

1
TiagoLr On

i think the best way would be to save the answers on the client while he asks for more questions, then submit all via a POST route, for example using a pair question:response:

@route(POST, "/saveSurvey")
public function doSaveSurvey(qapairs: Array<{q:Int, a:String}>) {
   for(pair in qapairs) {
        var question = pair.q;
        var answer = pair.a;
   }
}