Results 1 to 10 of 10

Thread: Domain Modeling Question

  1. #1

    Default Domain Modeling Question

    Hi all,

    I'm evaluating to use grails for a project. I'm completely knew to grails and trying to model my domain.

    I've the following simple domain just to try how domain modeling works in grails:

    Code:
    class Survey {
        static hasMany = [answers : SurveyAnswer,responses: SurveyResponse]
        ...
    }
    
    class SurveyAnswer {
        static belongsTo = [survey:Survey]
        static hasMany = [responses:SurveyResponse]
        String answer;
        
        static constraints = {
            survey(blank:false)
            answer(blank:false)
        }
        ...
    }
    
    class SurveyResponse {
        static belongsTo = [answer:SurveyAnswer, survey:Survey]
        
        static constraints = {
            answer(blank:false)
            dateCreated(editable:false)
            lastUpdated(editable:false)
        }
        ...
    }
    With scaffolding controllers I have all the CRUD views I need for the moment (very cool). However when I add a SurveyResponse I'm able to save all combinations of survey + answer. But apparently I should be able to store Responses for a specific survey only with answers which belong to that survey.
    Is there any standard grails way to apply such constraints and I just don't find it in the documentation or do I have to add custom code in the controller layer?

    Thanks a lot,
    Thomas
    Last edited by ThomasBecker; Feb 4th, 2011 at 10:18 AM. Reason: code tags fixed

  2. #2

    Default

    I thought about skipping the relation between Survey and SurveyResponse. There's still the connection Survey - SurveyAnswer - SurveyResponse.
    But the question still stays how to tell grails that it should only allow SurveyResponses which have a direct or indirect relation to a specific survey.

  3. #3
    Join Date
    Jul 2010
    Posts
    23

    Default Careful Design

    Thomas
    I just wanted to offer a quick response that may or may not be helpful but I still recommend it based on what you seem to be modeling.

    Burt Beckwith - an excellent contributor to the Grails ecosystem - has a presentation at infoq : http://www.infoq.com/presentations/GORM-Performance where he talks a little about these one to many and many to many relations especially in the context of what may be large numbers of child objects.

    Kindly watch it and in the process you may actually get some answers to the questions about best practices you mentioned.

    Just a thought.

  4. #4

    Default

    Hi,

    watched and enjoyed the presentation. Thanks for the link. Remodelt my domain a bit accordingly.

    However my question is not 100% answered, but I'am trying to establish the constraints now on the view.

    Cheers,
    Thomas

  5. #5
    Join Date
    Jul 2010
    Posts
    23

    Default Using Constraints

    Hi Thomas
    I believe Grails Constraints blocks work hand in hand with validation. They are used mainly to ensure that before you save data, you can validate your object state by calling the validate() method on your domain instance to have it checked against the rules in the constraints block. see: Link to Validation documentation

    For what you want to do, I noticed you have answer as a String and not a SurveyResponse. You should change that. Perhaps that is all that is wrong in your definitions.!

  6. #6

    Default

    HI deuseks,

    thanks for your reply. I will look more into how form validation is done in grails. I can definetly work out something with custom code and or grails validation. I just thought there must be something builtin in grails.

    Regarding the Answer as String. My domain model is a simplified part of the domain the real application will have and is not final at all. It's just enough to evaluate if grails is up to do the job:

    I've a Survey object.
    A Survey will have multiple SurveyAnswer Objects (each representing a single answer for this Survey).
    A Survey will have multiple SurveyResponse Objects. These are the answers given by the user to a survey.

    The constraint I'd like to have enforced are:

    - A SurveyResponse for Survey 1 can only have a SurveyAnswer which belongs to Survey 1. Answers belonging to Survey 2 should not be allowed.

    I will see if I can work around that and am having some ideas already. But atm. I'm stuck with another issue which should be a really simple thing to do in grails. See my other post.

    Cheers,
    Thomas

  7. #7
    Join Date
    Jun 2010
    Location
    London
    Posts
    304

    Default

    A custom 'validator' constraint should work for you.

  8. #8

    Default

    HI deuseks, Hi Peter,

    thanks for the hints. I'm trying to do the following now:

    Code:
    class Response {
    	Survey survey
    	Answer answer
    	Store store
        static belongsTo = [answer:Answer, survey:Survey, store:Store]
        
        static constraints = {
    		survey(blank:false)
    		store(blank:false)
            answer(blank:false),inList:survey.answers)
        }
    
        String toString(){
            return answer.toString()
        }
    }
    However it doesn't work and throws a MissingPropertyException:

    Caused by: groovy.lang.MissingPropertyException: No such property: survey for class: com.bat.pop.server.Response
    Possible solutions: survey

    Intuitively I'd expected that this should do the job. However will now try the custom validator instead.

    Had a couple of more issues with grails. Some have been caused by myself trying the wrong thing. But it always took me a while to find out what the root cause is. Maybe it's just me being not clever enough for grails. But I usually don't have that many issues with other technologies. Lets see how far I'll get. Maybe the risk to go for grails is too high considering that what I'm trying to do now is in no way complicated when writing a nice plain Java Domain model, putting some ORM on top of it and writing the CRUD views yourself.

    Thanks for the help again.

    Cheers,
    Thomas

  9. #9
    Join Date
    Jun 2010
    Location
    London
    Posts
    304

    Default

    Thomas,

    The particular problem in this case is that you are referring to an instance property from the static constraints block. That won't work (for the same reasons it doesn't work in Java). However, the Groovy error message is a little mystic. We should definitely point out common pitfalls like this.

    What you really want is a custom validator:
    Code:
    class Response {
        Survey survey
        Answer answer
        Store store
    
        static belongsTo = [answer:Answer, survey:Survey, store:Store]
        
        static constraints = {
            survey(blank:false)
            store(blank:false)
            answer(blank:false), validator: { val, obj -> val in obj.survey.answers} )
        }
    
        String toString(){
            return answer.toString()
        }
    }
    The second argument to the validator closure is the Response instance, which allows you to access its instance 'survey' property. 'val' is the value that is being saved for that property.

    We definitely value such feedback because it helps us improve the feedback mechanisms in Grails. In fact, we should be able to improve the error message in the above example, so I'll raise an issue.

  10. #10

    Default

    Hi Peter,

    great. Works. Thumbs up for the good support.

    Thinking about the fact that the constraint block is static it should have been clear to me that I can't access instance variables in there. *facepalm* Won't do the same mistake again.

    The custom validator looks quite nice and I even like the syntax. Will not try to add custom error message and then this one is sorted out as well.

    Cheers,
    Thomas

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •