2013-04-11 6 views
5

In meiner Task-Management-Anwendung, sollten Benutzer in der Lage sein, Aufgaben zu filtern basierend auf: assignedTo, priority, status und/oder dueDateDynamisch eine Abfrage auf params basiert die Erstellung an eine Steuerung übergeben wird

Ich bin nicht sicher, wie man Um eine dynamische Abfrage zu erstellen, wird eine Abfrage basierend auf den verfügbaren Parametern erstellt.

Zum Beispiel:

Wenn ich eine URL haben wie: task/index?assignedTo=1&status=2

ich eine Abfrage nur auf diese beiden Parameter auf Basis aufbauen können. Die Methode, die ich bin es gewohnt, ist die

Task.findAllByAssignedToAndStatus(
    User.get(params.assignedTo), 
    TaskStatus.get(params.status) 
) 

Ich möchte natürlich nicht durch das Schreiben aus jeder findAllBy Abfrage für jede mögliche URL-Parameter-Kombination ein Trockenverfahren implementieren.

Gibt es eine gute Möglichkeit, dies in Grails zu tun?

+0

Es ist trivial, die finder Namen zu generieren, indem etwas zu tun wie '" findAllBy $ {params.collect {k, v -> k.capitalize()} .join ('And')} ", aber woher weiß man, dass 'assignedTo' eine 'User'-Instanz und' 'laden soll Status "sollte sich auf einen' TaskStatus' beziehen? –

+0

Einverstanden, ich würde es nicht so machen wollen. Es ist für eine Dissertation, also möchte ich, dass der Code so sauber wie möglich ist. –

+0

Könnte ich vorschlagen, eine benannte Abfrage - http://grails.org/doc/2.2.1/ref/Domain%20Classes/namedQueries.html - dann können Sie nach Benutzer und Status ausfiltern. Ich denke, sie rocken! – marko

Antwort

5

ich es geschafft, diese Arbeit wie folgt mit createCriteria zu erhalten:

Ich bin mit dem Wert 0 für eine der params, wenn der Benutzer für diesen speziellen Filter ‚Alle‘ auswählt, deshalb wird es von dem, wo entfallen Klausel, dh keine eq() Anweisung für diesen Parameter.

Ein Ausschnitt des Codes:

else 
    {  
     def assignedTo = Integer.parseInt(taskParams.assignedTo) 
     def priority = Integer.parseInt(taskParams.priority) 
     def status = Integer.parseInt(taskParams.status) 

     tasks = Task.createCriteria().list {    

      eq("project", Project.get(taskParams.PId)) 

      if(assignedTo > 0) 
       eq("assignedTo", User.get(assignedTo)) 

      if(priority > 0) 
       eq("priority", TaskPriority.get(priority)) 

      if(status > 0) 
       eq("status", TaskStatus.get(status))     
     }   
    } 
    return tasks 
} 
7

Wir haben umgesetzt Filterfunktionalität auf den Domänenklassen, dies zu tun. Kurz gesagt, fügen Sie Ihrer Domain-Klasse kleine Snippets namens namedQueries hinzu.

Beispiel:

class Employee { 

    String firstname 
    String lastname 
    Integer age 

    static constraints = { 
    } 

    static namedQueries = { 
     filteronFirstname { String inFirstname -> 
      if (inFirstname&& inFirstname?.size() > 0) { 
       ilike 'firstname', "%${inFirstname}%" 
      } 
     } 

     filteronLastname { String inLastname -> 
      if (inLastname && inLastname?.size() > 0) { 
       ilike 'lastname', "%${inLastname}%" 
      } 
     } 

     filteronAgeOlderThen { String ageOlderThen -> 
      if (age && age ?.size() > 0) { 
       gt 'age', ageOlderThen as Integer 
      } 
     } 

    } 
} 

Dies ermöglichen feinkörnige Filterfunktion, so dass Sie 1 list-Methode aufbauen können, die alle Filtermethoden verwendet und je nachdem, was der Benutzer als Eingabe gab die namedqueries miteinander verbunden ist.

Employee.filteronFirstname("John"). 
filterOnLastname("Doe"). 
filteronAgeOlderThen("10"). 
list(params) 
0

Meine Lösung für eine dynamische Wo Abfrage von URL:

if (params.query) { 
    def classLoader = getClass().getClassLoader(); 
    def query = new GroovyShell(classLoader).evaluate(
      "import myapp.Visit; Visit.where {$params.query}") 
    visits = query.list(params) 
} 

Diese seine Zwänge von einer URL wie dies geschieht:

visit/index?query=client.status=='suspect';atHome==false