burns
burns

Reputation: 1121

Is there a way to create a relationship to an arbitraray domain object in grails

Is there a way to create an association to an arbitrary domain object in grails?

Something like

class ThingHolder {
    DomainObject thing;
}

and then

Book b=new Book(title: "Grails 101").save()
Author a=new Author(name: "Abe").save()

ThingHolder t1=new ThingHolder(thing:b).save()
ThingHolder t2=new ThingHolder(thing: a).save()

So that

ThingHolder.get(t1.id).thing  // will be a Book

and

ThingHolder.get(t2.id).thing  // will be an Author.

Upvotes: 0

Views: 83

Answers (2)

burns
burns

Reputation: 1121

I'm still looking for a grailsier way to do this, but this seems to get the job done.

class ThingHolder {
    static constraints = {
        thing bindable:true // required so 'thing' is bindable in default map constructor.
    }

    def grailsApplication;

    Object thing;

    String thingType;
    String thingId;

    void setThing(Object thing) {    //TODO: change Object to an interface
        this.thing=thing;
        this.thingType=thing.getClass().name
        this.thingId=thing.id;       //TODO: Grailsy way to get the id
    }

    def afterLoad() {
        def clazz=grailsApplication.getDomainClass(thingType).clazz
        thing=clazz.get(thingId);
    }
}

Assuming you have a Book and Author (that do not override the ID attribute for the domain object).

def thing1=new Author(name : "author").save(failOnError:true);
def thing2=new Book(title: "Some book").save(failOnError:true);

new ThingHolder(thing:thing1).save(failOnError:true)
new ThingHolder(thing:thing2).save(failOnError:true)

ThingHolder.list()*.thing.each { println it.thing }

I found some extremely useful tips in these two answers.

How to make binding work in default constructor with transient values.

How to generate a domain object by string representation of class name

Upvotes: 1

Joshua Moore
Joshua Moore

Reputation: 24776

UPDATE (based on comment)

Since you don't want to (or can't) extend another class in your domain model, this won't be possible using GORM.

ORIGINAL Answer

Yes, you can do this. It's called inheritance. In your case you would have a Thing which is the super class of both Author and Book.

Your domain model might look like this:

class Thing {
  // anything that is common among things should be here
}

class Author extends Thing {
  // anything that is specific about an author should be here
}

class Book extends Thing {
  // anything that is specific about a book should be here
}

class ThingHolder {
  Thing thing
}

Since both Author and Book extend Thing they are considered to be a Thing as well.

However, doing this without understanding inheritance and how Grails/GORM models the data in your database is short sighted. You should research those topics fully to make sure this is really what you want.

Upvotes: 0

Related Questions