1

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 ?

Franco Ponticelli
  • 4,430
  • 1
  • 21
  • 24
michaPau
  • 1,598
  • 18
  • 24
  • Why can't you save your model in `surveyApi.save()`? Assuming it is based on `ufront.db.Object` it should be able to be sent over remoting. – Jason O'Neil May 20 '15 at 07:35
  • In the moment my model is not based on `ufront.db.Object`. I wanted to keep the api as generic as possible to be able to switch between database storage or file storage or some mock service. Can be that I am simply still to much in my Flex/Robotlegs framework thinking. Which is great but completely different I guess. Thank you for your suggestions below - I going to try them out and come back after I made some experiences. – michaPau May 20 '15 at 09:46
  • For the api call *save*: I always get a compiler error: *Failed to parse function argument `args`. The args object must contain only the types String, Int, Float and Bool. * when try pass something different than String, Int etc. to my save method in my UFApi impl. – michaPau May 20 '15 at 10:31
  • Hmmm that error comes from when you are setting Controller routes, and should not affect what you do in your UFApi. I'd be interested to see more code so I can try understand what is happening. – Jason O'Neil May 20 '15 at 13:16
  • p.s. Nothing wrong with keeping your APIs very generic. It's probably a smart move :) You should be able to pass those objects to the API though. Once that problem is solved, your approach above seems perfectly reasonable. – Jason O'Neil May 20 '15 at 13:17
  • I tracked down the problem with the *argument args* compiler error. It was because I injected the api inside the controller like this: `@inject public var testApi:app.api.AsyncTestApi;`, when I change to `@inject public var testApi:AsyncTestApi;` with the import on the top it works. Never thought that this would change something :) Strange that it only happens when I declare a method inside the api with args different than simple types – michaPau May 21 '15 at 10:17
  • @micahPooh ... That sounds like it might be a bug in the new minject, which uses macros to get the type names. I might try to investigate. – Jason O'Neil May 21 '15 at 11:20
  • I am actually using the git v2 branch of minject (last update I made 18/05 I think), but I remember having the same issue when using the release 1.6.1 before. – michaPau May 21 '15 at 14:00

3 Answers3

2

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.

Community
  • 1
  • 1
Jason O'Neil
  • 5,908
  • 2
  • 27
  • 26
0

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;
   }
}
TiagoLr
  • 2,782
  • 22
  • 16
  • Yes, thanks for the suggestion. I actually do it in a similar way. I use `var postMap:MultiValueMap = this.context.request.post;` to get all my POST vars. I don't know if that has an advantage though – michaPau May 21 '15 at 10:25
0

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

bubblebenj
  • 116
  • 2
  • Might be worth a reading and interesting, so thank you, but the question is about the ufront framework and Haxe. The 'survey' is just an example and not the problem 'per se' – michaPau May 21 '15 at 10:01