2015-03-14 16:06

Arelのto_sqlメソッドのソースコードを読んでみる(1)

Arelとは

SQL生成のライブラリ

Arelとは、Ruby on Rails3から使われるようになったSQL生成を行うライブラリで、主にActiveRecordから呼ばれます。

Arelのgithubページ

例えば、railsのコントローラで次のようなアクションメソッドを実装します。

users_controller.rb
1     def index
2       @user = User.find(params[:id])
3     end

2行目では、ActiveRecordのfindメソッドを使ってusersテーブルからuserレコードを抽出しています。

このとき、railsのlogでは、

rails console
   User Load (5.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1   [["id", 1]]
=> #<User id: 1, …

というような感じになっていると思います。

findメソッドを使うことでDBに対してSQLを発行しているのですが、ここで内部的にSQLを生成しているのがArelです。

Arelの使い方

Arelは上で記したようにActiveRecord経由で間接的に利用される他に、ActiveRecordのメソッドを経由してSQLを発行しようとするとコードが複雑になってしまう場合などに直接的に利用されます。

例えばサブクエリを使いたい場合。

users_controller.rb
1     def example
2       @users = User.where("group = ?", User.find(1).group)
3     end

このように、モデルに対する処理を入れ子にすると、

SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]

SELECT "users".* FROM "users" WHERE group = 'admin'

という2つのSQLが発行されてしまいます。

これをArelを使って生成すると、

users_controller.rb
1     user = Arel::Table.new :users
2
3     def example
4       sub_query = user.project('group').where(user[:id].eq(1))
5       sql = user.project('*').where(user[:group].eq(sub_query).to_sql
6
7       @users = User.find_by_sql(sql)
8     end

という風にできます。

1行目では、Arel::Tableのインスタンスを生成し、変数userに格納していて。

4行目ではサブクエリを、5行目ではサブクエリを使った最終的なSQLを生成しています。

そのSQLを7行目でDBに対して発行しているのです。

発行されるSQLは次の通り。

SELECT * FROM "users" WHERE "users"."group" = (SELECT group FROM "users" WHERE "songs"."id" = 1)

と、サブクエリを使って1つのSQLになっているのがわかります。

このように、Arelを使うことで極力SQLを書くこと無く複雑なSQLを生成することができそうです。

さて、この例では5行目の最後、to_sqlメソッドによってSQLを文字列として出力しているのですが。

次の記事でこのto_sqlメソッドがSQL文字列を生成する仕組みを見て行こうと思います。

次回はこちら ⇒ Arelのto_sqlメソッドのソースコードを読んでみる(2)

ソースコードリーディングの準備はこちらを参照してくださいね。
ソースコードリーディングの準備