2012-06-25 14 views
6

Tengo un método estático en una clase de dominio que devuelve una url. Necesito construir esa url dinámicamente pero g.link no está funcionando.No se puede usar grails g.link en la clase de dominio

static Map options() { 
    // ... 
    def url = g.link(controller: "Foo", action: "bar") 
    // ... 
} 

consigo los siguientes errores:

Apparent variable 'g' was found in a static scope but doesn't refer to a local variable, static field or class. Possible causes: 
You attempted to reference a variable in the binding or an instance variable from a static context. 
You misspelled a classname or statically imported field. Please check the spelling. 
You attempted to use a method 'g' but left out brackets in a place not allowed by the grammar. 
@ line 17, column 19. 
      def url = g.link(controller: "Foo", action: "bar") 
        ^

1 error 

Obviamente, mi problema es que yo estoy tratando de acceder g del contexto estático, por lo que ¿cómo consigo alrededor de esto?

+2

No haga esto en un ámbito estático. Use un método de instancia, o mejor aún, ponga este código en un servicio para que pueda ser inyectado. – OverZealous

+0

No tengo una instancia en el momento en que estoy haciendo esto. – ubiquibacon

+1

Sí, estoy de acuerdo con OverZealous. Realmente mala idea hacerlo de esta manera. – Gregg

Respuesta

9

El objeto g es un taglib, que no está disponible dentro de una clase de dominio como lo sería en un controlador. Se puede llegar a ella a través de la grailsApplication como se muestra aquí: How To Call A Taglib As A Function In A Domain Class

Una mejor manera de hacer esto en Grails 2+ es a través del servicio grailsLinkGenerator, así:

def grailsLinkGenerator 

def someMethod() { 
    def url = grailsLinkGenerator.link(controller: 'foo', action: 'bar') 
} 

En ambos casos, se le necesita hacer un trabajo extra para obtener grailsApplication/grailsLinkGenerator desde un contexto estático. La mejor manera es, probablemente, para agarrarlo fuera de la propiedad domainClass de la clase de dominio:

def grailsApplication = new MyDomain().domainClass.grailsApplication 
def grailsLinkGenerator = new MyDomain().domainClass.grailsApplication.mainContext.grailsLinkGenerator 
+0

Estaba tan cerca. Intenté linkGenerator, pero recibía advertencias de contexto estáticas. Quitarlo de la clase de dominio como sugirió funcionó bien. ¡Gracias! – ubiquibacon

5

Si está utilizando Grails 2.x puede usar la API de LinkGenerator. Aquí hay un ejemplo, estoy reutilizando una clase de dominio con la que estaba probando antes, así que ignore la funcionalidad no relacionada con la URL.

class Parent { 
    String pName 

    static hasMany = [children:Child] 

    static constraints = { 
    } 
    static transients = ['grailsLinkGenerator'] 

    static Map options() { 
     def linkGen = ContextUtil.getLinkGenerator(); 
     return ['url':linkGen.link(controller: 'test', action: 'index')] 
    } 
} 

clase de servicio con el método estático

@Singleton 
class ContextUtil implements ApplicationContextAware { 
    private ApplicationContext context 

    void setApplicationContext(ApplicationContext context) { 
     this.context = context 
    } 

    static LinkGenerator getLinkGenerator() { 
     getInstance().context.getBean("grailsLinkGenerator") 
    } 

} 

grano de Def para nueva utilidad frijol

beans = { 
    contextUtil(ContextUtil) { bean -> 
     bean.factoryMethod = 'getInstance' 
    } 
} 

Si necesita la URL base, añadir absolute:true a la llamada de enlace.

Cuestiones relacionadas