夏が過ぎ風あざみ。
謎の首痛と腰痛、そして風邪に見舞われた8月でしたが、
人にうつせば治るというもので、すっかりよくなった山本です。
今日はRails3のコネタを。
Arel
Rails3では、O/RマッパーであるActiveRecordが進化を遂げ、「Arel」というライブラリを使用するようになりました。
「Arel」については様々なサイトで解説が載ってますが、
Rails2のfind系メソッドは、呼び出しの際にDBに対してSQLを発行していたのが、
Rails3では、インスタンスは一旦、 ActiveRecordのサブクラスである、 Relationのオブジェクトとして格納されます。
全部が全部ではないですが。
例えば、Userモデルがあるとして、
user = User.find(1) |
と、findを使ってデータを取得して、userの中身を見ると
user.class => User(id: integer, email: string, .....created_at: datetime, updated_at: datetime) |
と、Userモデルのインスタンスになっていますが、
user = User.where(:id => 1) |
と、whereを使うと、
user.class => ActiveRecord::Relation |
となります。
そしてこの時、SQLの処理は行われません。
あくまで関係の定義が詰まっているだけ。
この利点は、不要不急なSQL処理が走らないことですね。
また、これこそが、whereを数珠つなぎにして条件を加える、メソッドチェーンの書き方ができるわけです。
user = User.where(:id => 1) user = user.where("number > 1") user = user.where("type > 2") |
と書いて、3回もSQLが走ったら大変ですし。
じゃあいつクエリが発行されるのかというと、
実際に値を表示するときです。
例えば、
puts user
や
user.all
などと書いたときですね。
本当に値が必要になったときに処理をしてくれるので、リソースの節約につながるのかなと。
逆効果も
ただ、使い方を誤ると逆に無駄にクエリを発行することにもなります。
ある条件のデータの最大と最小を取り出したい、といった時、
僕はこう書いてました。
user = User.order("id ASC") user_min = user.first user_max = user.last |
rails2時代の感覚だと、1行目でレコードのデータが user に格納され、
2行目と3行目では、ただの配列の操作を行ってデータを格納する処理ですが、
実際には1行目では user にデータは格納されず、
2行目と3行目でクエリが発行されてデータが格納されます。
つまり、1回余分です。
これじゃあ無駄なので、1行目を
user = User.order("id ASC").all |
としました。
こうすれば、1行目で user にデータが格納され、クエリ発行は1回です。
時代はもうRails3.1
まだ、Arelに馴染んでなかったといってしまえばそれまでですが、
rails2の感覚でいると、いろいろ壁があるなーと実感しました。
今やもう3.1ですし、次はcoffeescriptをやらないといけないかなと思ってます。
上記は、あくまで自分の解ですが、他の解とか、そもそも論が何かあればツッコミのほどよろしくお願いします。