Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails/GORM: creating one-to-one optional relationship

I'm designing a system in which posts/discussions between users can be upgraded to become tickets. At one particular place I'm trying to create a one-to-one optional relationship but am running into certain issues. A condensed version of the entities in the spotlight is given below.

Rules:

  1. A Post can become a Ticket if required. (optional)
  2. A Ticket must have a Post. (mandatory)

Post.groovy

class Post {

        String title
        String description
        String postedBy

        Ticket ticket

        static hasMany = [comments: Comment]

    static constraints = {
        title(blank:false)
        description(blank:false)
        postedBy(blank:false)
        ticket (nullable:true,unique:true)
    }
}

Ticket.groovy

class Ticket {

        String title
        String description
        String postedBy

        Post post

        static hasMany = [responses: Response]

        static constraints = {
                title(blank:false)
                description(blank:false)
                postedBy(blank:false)
                post (nullable:false,unique:true)
        }

}

This works to some extent. I can:

  1. Create a Post leaving the ticket attribute null If and when the post is upgraded to become a ticket
  2. I can explicitly set the Post's ticket attribute to point to the parent ticket.

However, this mapping isn't enforced at the domain level. It leaves room for a situation where Ticket1 points to Post1, but Post1 points to Ticket2 instead.

I tried using a static hasOne = [post: Post] in the Ticket class but later learned that it mandates the presence of a static belongsTo = [ticket: Ticket] in the Post class and this becomes a mandatory 1-to-1 relationship which is not what I'm looking for.

Is there a way to achieve this 1-to-1 optional mapping in this scenario? Any pointers would be most helpful.

like image 741
Sagar V Avatar asked Oct 07 '11 08:10

Sagar V


1 Answers

You could consider making a custom validator like

class Post {
  // Other fields

  Ticket ticket

  static constraints = {
    // Other constraints
    ticket (nullable:true,unique:true, validator: { val, obj ->
       if(val) {
         return val.post == obj
       }
    })
  }
}

Would this solve your problem?

like image 63
sbglasius Avatar answered Oct 31 '22 14:10

sbglasius