2012-07-18 10 views
6

私は動的にcreateCriteriaを構築しています。これまでのところ、とても良い:GrailsでcreateCriteriaを動的かつDRY的に構築しますか?

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

上記のコードはうまく動作し、switch文で少し冗長です。しかし、ルールのいずれか、またはそのすべてに一致するように選択する機能を追加したい場合はどうすればよいですか?条件付きでルールをor{}に入れる必要があります。私はその後

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

をrulesListを通過し、その後

前に私が

if(groupOp == 'or'){ 
    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

まず第一に、あなたはメソッド名のGストリングを使用して、大きなスイッチを簡素化することができます。同じトリックはおよび/またはのために働く

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)のいずれかを呼び出すことができます。最後に、検索「プロパティのプロパティ」のために、あなたが介在driver {...}またはgarage {...}ノードを追加することなく、あなたがeq('drv.name', 'Fred')のようなもので問い合わせることができます基準閉鎖の先頭に

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

を追加した場合。

+1

グレート・ソリューションでは、私はまだGroovyのフルパワーを実現し活用していないようです。また、createAlias(これまで私が知っていたことは分かっていません)についてもっと知りたい人は、[ここ]を見てください(http://adhockery.blogspot.com/2009/06/querying-by-association-redux.html) – Weezle

+0

ありがとう! createAliasは私の問題を解決しました。なぜGrailsのドキュメントのcreateCriteriaページに記載されているのか分かりません。 – Ben

関連する問題