2012-07-18 5 views
6

मैं गतिशील रूप से createCriteria बनाने पर काम कर रहा हूं। अब तक, तो अच्छा:ग्रेल्स में गतिशील रूप से और एक ड्रवाई तरीके में बनाने का निर्माण करें?

obj डोमेन वस्तु (रों) मैं वापस

rulesList चाहते है नक्शे जो पकड़ क्षेत्र, ऑपरेटर का उपयोग करने पर खोजे जाने के लिए की एक सूची है, और के खिलाफ खोज करने के लिए मूल्य है

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 
      } 
     } 
    } 
} 

उपर्युक्त कोड ठीक काम करता है और स्विच स्टेटमेंट के साथ केवल थोड़ा वर्बोज़ दिख रहा है। लेकिन क्या होगा यदि मैं किसी भी नियम या उन सभी से मेल खाने के लिए चुनने के लिए कार्यक्षमता जोड़ना चाहता हूं? मुझे सशर्त रूप से नियमों को or{} में रखना होगा। मैं की तरह

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

कुछ नहीं कर सकते इससे पहले कि मैं rulesList के माध्यम से

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

बाद में जाने के लिए और उसके बाद। सभी मुझे क्या करना सोच सकते हैं प्रत्येक शर्त के लिए कोड को दोहराने के लिए है:

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

अब कोड काफी लापरवाह और दोहराव लग रही है। मान लीजिए कि मैं डोमेन ऑब्जेक्ट की किसी संपत्ति की संपत्ति पर खोज करना चाहता हूं? (पूर्व: मैं उन वाहनों को वापस करना चाहता हूं जिनके टायर एक निश्चित ब्रांड हैं; vehicle.tires.brand, या जिन वाहनों का ड्राइवर नाम से मेल खाता है; vehicle.driver.name)। मैं की तरह कुछ करने के लिए होता है:

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': 
     ... 
} 

उत्तर

9

सबसे पहले, आप विधि नाम के लिए एक gstring का उपयोग करके अपने बड़े स्विच को आसान बनाने में कर सकते हैं:

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

एक ही चाल और/या के लिए काम करता है:

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

या आप एक चर पहले करने के लिए बंद आवंटित कर सकते हैं और फिर या तो or(theClosure) या and(theClosure) के रूप में उपयुक्त कहते हैं। अंत में, खोज "एक संपत्ति की संपत्ति" के लिए, आप

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

मापदंड बंद के शीर्ष करने के बीच driver {...} या garage {...} नोड जोड़ते किए बिना तो आप eq('drv.name', 'Fred') जैसी चीजों पर क्वेरी कर सकते हैं।

+1

ग्रेट सॉल्यूशन, ऐसा लगता है कि मैं अभी भी ग्रोवी की पूरी शक्ति को महसूस नहीं कर रहा हूं और लीवरेज कर रहा हूं। साथ ही, createAlias ​​(जिसे मैं पहले के बारे में कुछ भी नहीं जानता था) के बारे में अधिक जानने में दिलचस्पी रखने के लिए (http://adhockery.blogspot.com/2009/06/querying-by-association-redux.html) – Weezle

+0

धन्यवाद ! createAlias ​​मेरी समस्या हल हो गई। मुझे नहीं पता कि Grails दस्तावेज़ीकरण के createCriteria पृष्ठ पर इसका उल्लेख क्यों नहीं किया गया है। – Ben

संबंधित मुद्दे