読者です 読者をやめる 読者になる 読者になる

エンジニアリングにはほど遠い

iPhoneアプリとかサイトとかをつくっていくブログです。

Ransackでグループ間OR検索が分からない件

Ransackは検索にとても便利なGemだけど、複雑な検索の仕方がイマイチ分からない。

( * || * ) && ( * && * ) みたいな、グループ間がANDな検索しかできないのかな・・・?

( * && * ) || ( * && * ) みたいな事がしたいのだけど。。。

ちなみに前者の検索についてはこういう風な感じ。

User.search({
               g: {
                    '0' => { m: 'or', power_gteq: 100, magic_gteq: 30 },
                    '1' => { m: 'and', level_gteq: 20, hp_lteq: 30 }
               }
            }
).result

たとえばこれだとパワーが100以上又は魔法が30以上で、かつレベルが20以上かつHPが30以下のユーザを取ってくる、みたいな感じです。

う〜ん。

2013/3/25 追記

上司にアドバイスをもらい分かりました!最初に入れ子にしなければいけなかったようです。

User.search({
  g: { 
       '0' => { m: 'or',
                g: {
                    '0' => { m: 'and', power_gteq: 100, magic_gteq: 30 },
                    '1' => { m: 'and', level_gteq: 20, hp_lteq: 30 }
                }
       }
  }
}
).result

2016/3/28 追記

上記は少し勘違いしていて、最初の記述は m: 'and' が省略されているだけでした。つまり

User.search(
  g: {
    '0' => { m: 'or', power_gteq: 100, magic_gteq: 30 },
    '1' => { m: 'and', level_gteq: 20, hp_lteq: 30 }
  }
).result
と
User.search(
  m: 'and',
  g: {
    '0' => { m: 'or', power_gteq: 100, magic_gteq: 30 },
    '1' => { m: 'and', level_gteq: 20, hp_lteq: 30 }
  }
).result
は同じ。

そして、orにしたければand部分を変えればおk
User.search(
  m: 'or',
  g: {
    '0' => { m: 'or', power_gteq: 100, magic_gteq: 30 },
    '1' => { m: 'and', level_gteq: 20, hp_lteq: 30 }
  }
).result

ちなみにさらなる入れ子は・・・
User.search(
  m: 'and',
  g: { 
    '0' => { 
      m: 'or',
      g: {
        '0' => { m: 'and', power_gteq: 100, magic_gteq: 30 },
        '1' => { m: 'and', level_gteq: 20, hp_lteq: 30 }
      }
    },
    '1' => { m: 'and', job_eq: 'brave', name_eq: 'Roto' }
  }
).result # => ((power >= 100 && magic >= 30) || (level >= 20 && hp <= 30)) && (job == "brave" && name == "Roto")