railsがんばる子

Ruby on Railsがんばる子です。胡蝶蘭のECサイトを運営しています。

arel_tableを利用してexistsの外部副問い合わせを実現する

ActiveRecordで複雑なことをやろうとするとarel_tableだと伺いまして。

準備

rails -v
Rails 4.1.0
ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-darwin13.0]
rails new test_app
cd test_app
rails g model yamada name:string
rails g model nanika status:string name:string yamada:references
bundle exec rake db:migrate
bundle exec rails console

まず、Arel::Tableオブジェクトを取得するところから。

nanika = Nanika.arel_table
=> #<Arel::Table...

今回はexistsの相関副問い合わせを作ってみました。

t1 = nanika.project(nanika[:yamada_id]).where(nanika[:status].eq('good')).group(nanika[:yamada_id]).as('t1')
=> #<Arel::Nodes...
t1.to_sql
=> "(SELECT \"nanikas\".\"yamada_id\" FROM \"nanikas\"  WHERE \"nanikas\".\"status\" = 'good' GROUP BY \"nanikas\".\"yamada_id\") t1"
yamada = Yamada.arel_table
condition = yamada.from(t1).where(t1[:yamada_id].eq(yamada[:id])).project("'X'").exists
Yamada.where(condition)
Yamada Load (0.2ms)  SELECT "yamadas".* FROM "yamadas"  WHERE (EXISTS (SELECT 'X' FROM (SELECT "nanikas"."yamada_id" FROM "nanikas"  WHERE "nanikas"."status" = 'good' GROUP BY "nanikas"."yamada_id") t1  WHERE t1."yamada_id" = "yamadas"."id"))
=> #<ActiveRecord::Relation []>

レコード入れてないのでやまだは見つかりませんでしたが、EXISTSで外側のテーブルを参照できています!!


関係無いのもあるけどarel_table調査のときの参考にしたページの断片

ActiveRecord4でこんなSQLクエリどう書くの? Arel編 - TIM Labs

sql - ActiveRecord Arel OR condition - Stack Overflow