Hi all,
I have a domain three domain class like this : Tasks.groovy class Tasks { static belongsTo = [ user : User ] //other fields Date startDate Date endDate } User.groovy class User { //relationships. . . . static belongsTo = [ company : Company, role : Role, resource : Resource] static hasMany = [ holidays : Holiday, tasks : Tasks] //other fields } Holiday.groovy class Holiday { static belongsTo = User Date startDate Date endDate //other fields } Now when I create a Tasks instance, I want to put a constraint such that the Tasks startDate and endDate doesn't fall within the User's Holidays startDate and endDate. And throw and error if it has. I want a way to put this constraint on my domain class itself(i.e on Tasks). Is it possible to do so? Thanks in advance.
Ant's
|
With a customer validator, see the docs for details
-- Graeme Rocher On Friday, February 24, 2012 at 6:58 AM, antoaravinth wrote:
|
Well the custom validator is working for putting a constraint on the same Domain class instance. Not on the case of relationships.
Ant's
|
You can look at the relationships of a domain class from the domain class. Just be careful because of the association is not initialized and lazy you can run into trouble. For this kind of thing you really need to load a separate instance to avoid interfering with the flushing process.
-- Graeme Rocher On Friday, February 24, 2012 at 10:27 AM, antoaravinth wrote:
|
Is this what you're looking for.
static constraints = { startDate(validator: {val, obj -> return obj.user?.holidays?.every { !(it.startDate.after(val) && it.endDate.before(val))}})
endDate(validator: {val, obj -> return obj.user?.holidays?.every { !(it.startDate.after(val) && it.endDate.before(val))}}) } Kind regards,
Matti van Aert 2012/2/24 Graeme Rocher <[hidden email]>
Met vriendelijke groet, Matti van Aert Achter de Molen 45 4873 GW Etten-Leur M: +31 (0)6 5499 4867 |
In reply to this post by Graeme Rocher-2
Thanks Graeme Rocher will look into it.
On Fri, Feb 24, 2012 at 3:55 PM, Graeme Rocher-2 [via Grails] <[hidden email]> wrote:
Ant's
|
In reply to this post by Matti van Aert
The solution given by Matti van Aert, is not working. I did the same as what you have said, but that doesn't work.
Ant's
|
ants - think i have a solution for you, although i'd be curious to hear more from graeme about how this might change if any of the associations were lazy. perhaps i need to revisit the GORM gotcha series, if it's covered there. if not, maybe time for part 4? :) i didn't try matti's solution, but as a general style note i'm not personally a fan of navigation on an object's relationships outside of that object, if possible. i think that leads to making code more difficult to refactor, so i try and provide convenience methods that state the intent of the relationship navigation. so in the code below i put a "isUserAvailable()" method on the User domain, and had the Tasks custom validator call that method. hope this makes sense, and let me know if it works for you - or doesn't. from just a little testing in the grails console i think it does what it should. fun little exercise. :) dave btw, i set holidays to a SortedSet on the User class, and in a real-world scenario i'd probably think about using that with a for loop instead of the ".any" in the isUserAvailable() method. i'd trace the sql queries and see how many it executes. but basically with a SortedSet according to holiday start dates, if your task date is in January there's no reason to keep checking the holiday dates for the rest of the year. does that make sense? and the reason for a for loop instead of a closure in that scenario, is that as far as i know you can't break out of a closure. class Tasks { static belongsTo = [user:User] Date startDate Date endDate static constraints = { startDate( nullable:false, validator: { val, obj -> obj?.user?.isUserAvailable( val, obj?.endDate ) }) endDate( nullable:false ) } // wants constraint so that Task cannot be created if task start/end date falls within any of the User's Holiday's start/end date } class User { SortedSet holidays static hasMany = [ holidays: Holiday, tasks: Tasks ] static constraints = { } static transients = ['isUserAvailable'] def isUserAvailable( startDate, endDate ) { def datesConflictWithHolidays = this.holidays?.any { startDate.after( it.startDate ) && startDate.before( it.endDate ) \ || endDate.after( it.startDate ) && endDate.before( it.endDate ) } return ! datesConflictWithHolidays } } class Holiday implements Comparable { static belongsTo = User Date startDate Date endDate static constraints = { startDate( nullable:false ) endDate( nullable:false, validator: { val, obj -> val?.after(obj?.startDate) }) } def compareTo(that) { this?.startDate <=> that?.startDate } } |
Thanks for the reply and some good tips. Now consider the scenario where I'm selecting the users from a drop down box and I want to check that particular users holiday stats. This is very much easy if I put the code in my controller and check them. But is there a way to the same in domain class via a validator constraint?
Ant's
|
i'm not sure i'm following the question. are you trying to see the user's holidays before saving the Tasks domain? if so, doing something like the isUserAvailable() method could be reused beyond just the validator, and called via ajax to provide immediate feedback to the UI as to whether the dates entered are valid or not, prior to trying to actually persist the data to the DB. remember that the validator constraints will be checked only if domain.validate() or domain.save() is called. (or something similar, maybe .merge() or whatever else.)
again, generally speaking, i try to keep my controllers as simple as possible and have them focusing on handling navigation primarily. i shoot for putting any/most real logic in the domain or service layers. |
Thanks mate, I got into working, Thanks for your advice too... :)
On Mon, Feb 27, 2012 at 9:06 AM, talldave [via Grails] <[hidden email]> wrote: i'm not sure i'm following the question. are you trying to see the user's holidays before saving the Tasks domain? if so, doing something like the isUserAvailable() method could be reused beyond just the validator, and called via ajax to provide immediate feedback to the UI as to whether the dates entered are valid or not, prior to trying to actually persist the data to the DB. remember that the validator constraints will be checked only if domain.validate() or domain.save() is called. (or something similar, maybe .merge() or whatever else.)
Ant's
|
Free forum by Nabble | Edit this page |