ActiveRecordの #or を使うときは、こう考えると良さそう

Rails5で追加された #or について。 (どうでもいいけど、このメソッド、ググラビリティ低すぎぃ)

社内で話してたら、Twitterで会話されてた。

つまりこう考えれば良いということか。

「whereを AND だと思ったうえで、メソッドのチェーン順に従う。」 と思えば良いのか。

Model
  .where(A)
  .where(B).or(C)

は改行のせいでgroupingが存在している気になるけど、字句解析結果は結局のところこう↓

Model.where(A).where(B).or(C)

これを、チェーン順に解釈すれば確かに

A and B or C

になる。一方、

Model.where(B).or(C).where(A)

なら、チェーン順とはすなわち「or Cが先」を意味することになる。これはSQL演算子結合順と異なるため、ARが勝手に

(B or C) and A

にしてくれる、と。

「順序で結果が変わるのは後でバグを誘発し易いから避けたい」と思う場合は、「明示的に括弧を書く」と同じことをARのDSL上でやればよい。つまり、こう。

Model
  .where(A)
  .where(Model.where(B).or(C))

余談

これ、「直感とのズレ」が起こる本質的なポイントは、そもそもSQLにあるんじゃねーか?

ANDの連結を「項」と考えると↑の議論は意味がわかるけど、SQLにおいては「項」にあまり意味がないことが多い。むしろ、ORの連結の方に「filter単位」という意味があり、filter単位をANDするという考え方をすることが多いはず。「項」と「filter単位」のどちらを基準と考えるかで、どちらが直感的かの捉え方も変わるなぁ。