18

I want to allow users to traverse the domain classes and print out dumps of stuff. My frist problem: assuming the following works just fine:

//this works
class EasyStuffController{
  def quickStuff = {
    def findAThing = MyDomainClass.findByStuff(params.stuff)
    [foundThing:findAThing]
  }
}

What is the proper way to write what I am trying to say below:

//this doesn't
class EasyStuffController{ servletContext ->
  def quickStuff = {
    def classNameString = "MyDomainClass" //or params.whichOne something like that
    def domainHandle = grailsApplication.domainClasses.findByFullName(classNameString)
    //no such property findByFullName
    def findAThing = domainHandle.findByStuff(params.stuff)
    [foundThing:findAThing]
  }
}



//this also doesn't
class EasyStuffController{ servletContext ->
  def quickStuff = {
    def classNameString = "MyDomainClass" //or params.whichOne something like that
    def domainHandle 
    grailsApplication.domainClasses.each{
      if(it.fullName==classNameString)domainHandle=it
    }
    def findAThing = domainHandle.findByStuff(params.stuff)
    //No signature of method: org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass.list() is applicable
    [foundThing:findAThing]
  }
}

Those lines above don't work at all. I am trying to give users the ability to choose any domain class and get back the thing with "stuff." Assumption: all domain classes have a Stuff field of the same type.

Mikey
  • 4,692
  • 10
  • 45
  • 73

1 Answers1

45

If you know the full package, you can use this:

String className = "com.foo.bar.MyDomainClass"
Class clazz = grailsApplication.getDomainClass(className).clazz
def findAThing = clazz.findByStuff(params.stuff)

That will also work if you don't use packages.

If you use packages but users will only be providing the class name without the package, and names are unique across all packages, then you can use this:

String className = "MyDomainClass"
Class clazz = grailsApplication.domainClasses.find { it.clazz.simpleName == className }.clazz
def findAThing = clazz.findByStuff(params.stuff)
Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
  • I get the error(using the second method and className="Account"): Cannot cast object 'Artefact > Account' with class 'org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass' to class 'java.lang.Class' due to: java.lang.ClassNotFoundException: Artefact > Account – Mikey Jun 14 '11 at 22:22
  • Sorry about that, I edited the answer to get the Java class from the DomainClass. – Burt Beckwith Jun 15 '11 at 04:49
  • @burt: I believe, you missed a .clazz in the second line of your first example (just like you added to the second block). Unfortunately the [funny naming](http://grails.org/doc/latest/api/org/codehaus/groovy/grails/commons/AbstractGrailsClass.html#getClazz%28%29) prevented my edit to be approved :-) – martin Aug 24 '12 at 11:16
  • 1
    Is this approach still applicable in versions later than 2.3.x? – John Giotta Sep 20 '14 at 00:43
  • 1
    Looks like with grails 3, the getArtefact method doesnt work if you dont specify the class name with package – Sudhir N Mar 11 '17 at 15:27