2012-07-18 22 views
6

Tôi đang làm việc để xây dựng một động cơ createCriteria. Cho đến nay, như vậy tốt:Xây dựng createCriteria trong Grails động và theo cách DRY?

obj là đối tượng miền (s) Tôi muốn trở lại

rulesList là danh sách các bản đồ mà giữ lĩnh vực này để được tìm kiếm trên, các nhà điều hành để sử dụng, và giá trị để tìm kiếm đối

def c = obj.createCriteria() 
l = c.list (max: irows, offset: offset) { 
    switch(obj){   //constrain results to those relevant to the user 
     case Vehicle: 
      eq("garage", usersGarage) 
      break 
     case Garage: 
      users { 
       idEq(user.id) 
      } 
      break 
    } 
    rulesList.each { rule -> 
     switch(rule['op']){ 
      case 'eq': 
       eq("${rule['field']}", rule['value']) 
       break 
      case 'ne': 
       ne("${rule['field']}", rule['value']) 
       break 
      case 'gt': 
       gt("${rule['field']}", rule['value']) 
       break; 
      case 'ge': 
       ge("${rule['field']}", rule['value']) 
       break 
      case 'lt': 
       lt("${rule['field']}", rule['value']) 
       break 
      case 'le': 
       le("${rule['field']}", rule['value']) 
       break 
      case 'bw': 
       ilike("${rule['field']}", "${rule['value']}%") 
       break 
      case 'bn': 
       not{ilike("${rule['field']}", "${rule['value']}%")} 
       break 
      case 'ew': 
       ilike("${rule['field']}", "%${rule['value']}") 
       break 
      case 'en': 
       not{ilike("${rule['field']}", "%${rule['value']}")} 
       break 
      case 'cn': 
       ilike("${rule['field']}", "%${rule['value']}%") 
       break 
      case 'nc': 
       not{ilike("${rule['field']}", "%${rule['value']}%")} 
       break 
      } 
     } 
    } 
} 

Mã trên hoạt động tốt và chỉ có một chút chi tiết với các câu lệnh chuyển đổi. Nhưng điều gì sẽ xảy ra nếu tôi muốn thêm chức năng để chọn BẤT K of quy tắc hoặc TẤT CẢ chúng? Tôi sẽ cần phải có điều kiện đặt các quy tắc trong một or{}. Tôi không thể làm điều gì đó như

if(groupOp == 'or'){ 
    or{ 
} 

trước khi tôi đi qua các rulesList và sau đó

if(groupOp == 'or'){ 
    } 
} 

sau đó. Tất cả những gì tôi có thể nghĩ là lặp lại mã cho từng điều kiện:

if(groupOp == 'or'){ 
    or{ 
     rulesList.each { rule -> 
      switch(rule['op']){ 
       ... 
      } 
     } 
    } 
} 
else{ 
    rulesList.each { rule -> 
     switch(rule['op']){ 
      ... 
     } 
    } 

Bây giờ mã trông khá cẩu thả và lặp đi lặp lại. Giả sử tôi muốn tìm kiếm trên thuộc tính của thuộc tính của đối tượng miền? (Ví dụ: Tôi muốn trả lại các phương tiện có lốp xe là một thương hiệu nhất định; xe.tires.brand hoặc các phương tiện có trình điều khiển phù hợp với tên; vehicle.driver.name). Tôi sẽ phải làm một cái gì đó như:

switch(rule['op']){ 
    case 'eq': 
     switch(thePropertiesProperty){ 
      case Garage: 
       garage{ 
        eq("${rule['field']}", rule['value']) 
       } 
       break 
      case Driver: 
       driver{ 
        eq("${rule['field']}", rule['value']) 
       } 
       break 
     } 
     break 
    case 'ne': 
     ... 
} 

Trả lời

9

Trước hết, bạn có thể đơn giản hóa chuyển đổi lớn của bạn bằng cách sử dụng một G-string cho tên phương pháp:

case ~/^(?:eq|ne|gt|ge|lt|le)$/: 
    "${rule['op']}"("${rule['field']}", rule['value']) 
    break 

Bí quyết cùng làm việc cho và/hoặc:

"${(groupOp == 'or') ? 'or' : 'and'}"() { 
    rulesList.each { rule -> 
    switch(rule['op']){ 
     ... 
    } 
    } 
} 

hoặc bạn có thể gán việc đóng cửa cho một biến đầu tiên và sau đó gọi một trong hai or(theClosure) hoặc and(theClosure) cho phù hợp. Cuối cùng, đối với các "tài sản của một tài sản" tìm kiếm, nếu bạn thêm

createAlias('driver', 'drv') 
createAlias('garage', 'grg') 

để phía trên cùng của việc đóng cửa các tiêu chí sau đó bạn có thể truy vấn về những thứ như eq('drv.name', 'Fred') mà không cần phải can thiệp thêm driver {...} hoặc garage {...} nút.

+1

Giải pháp tuyệt vời, có vẻ như tôi vẫn chưa nhận ra và tận dụng toàn bộ sức mạnh của Groovy. Ngoài ra, đối với bất cứ ai quan tâm đến việc tìm hiểu thêm về createAlias ​​(mà tôi không biết gì về trước đây) xem qua [ở đây] (http://adhockery.blogspot.com/2009/06/querying-by-association-redux.html) – Weezle

+0

Cảm ơn ! createAlias ​​đã giải quyết được vấn đề của tôi. Tôi không biết tại sao nó không được đề cập trên trang createCriteria của tài liệu Grails. – Ben

Các vấn đề liên quan