Rubyを使い始めた (2) - Rails3のArelの例
はじめに
サンプルとして、下記のようなModelとデータベースを作成してある。
$ rails g model book name:string
$ rails g model user name:string lang:string age:integer book:references
- books
id | name |
---|---|
1 | レガシーコード改善ガイド |
2 | 情熱プログラマ |
3 | メタプログラミングRuby |
- users
id | name | lang | age | book_id |
---|---|---|---|---|
1 | sinsoku | python | 24 | 1 |
2 | _ryog | java | 24 | 2 |
3 | NowTom | ruby | 28 | 3 |
4 | tosikawa | python | 30 | 2 |
* サンプルのデータは実在の人物とは関係ありません
find とwhere の違い
日本語で説明するよりも、コードを見た方が早いので、例
Rails2 のfind
User.find(:first, :conditions => ["lang = ? and age = ?", 'python', 24])
Rails3 のwhere
User.where(:lang => 'python').where(:age => 24).first
上記の例のように、whereを使用するとname_scope のような書き方が出来ます。
使い方の例
- where句
User.where(:lang => 'python').all # => [#<User id:1, name: "sinsoku", lang: "python", age: 24, book_id: 1, create_at: ..., updated_at: ...>, # #<User id:4, name: "tosikawa", lang: "python", age: 30, book_id: 2, create_at: ..., updated_at: ...>] User.where(:name => 'sinsoku').first # => #<User id:1, name: "sinsoku", lang: "python", age: 24, book_id: 1, create_at: ..., updated_at: ...>
ちなみに、findのような引数も使えます。
User.where(['name = ? and lang = ?', 'NowTom', 'ruby']).first # => #<User id:3, name: "NowTom", lang: "ruby", age: 28, book_id: 3, create_at: ..., updated_at: ...>
- order句
users = User.arel_table User.where(:lang => 'python') .order(users[:age].asc).all # => [#<User id:1, name: "sinsoku", lang: "python", age: 24, book_id: 1, create_at: ..., updated_at: ...>, # #<User id:4, name: "tosikawa", lang: "python", age: 30, book_id: 2, create_at: ..., updated_at: ...>] User.where(:lang => 'python') .order(users[:age].desc).all # => [#<User id:4, name: "tosikawa", lang: "python", age: 30, book_id: 2, create_at: ..., updated_at: ...>, # #<User id:1, name: "sinsoku", lang: "python", age: 24, book_id: 1, create_at: ..., updated_at: ...>]
- include句
books = Book.arel_table User.where(:age => 24) .where(books[:name].eq('情熱プログラマー')) .includes(:book).first # => #<User id:2, name: "_ryog", lang: "java", age: 24, book_id: 2, create_at: ..., updated_at: ...>
- and条件
users = User.arel_table users.where(users[:age].lt(25).and(users[:lang].eq('java'))).first # => #<User id:2, name: "_ryog", lang: "java", age: 24, book_id: 2, create_at: ..., updated_at: ...> # 長いときはこっちの方が見易い users.where(['age < ? and lang = ?', 25, 'java']).first # => #<User id:2, name: "_ryog", lang: "java", age: 24, book_id: 2, create_at: ..., updated_at: ...>
- or条件
users = User.arel_table User.where(users[:name].eq('sinsoku').or(users[:lang].eq('ruby'))).all # => [#<User id:1, name: "sinsoku", lang: "python", age: 24, book_id: 1, create_at: ..., updated_at: ...>, # #<User id:3, name: "NowTom", lang: "ruby", age: 28, book_id: 3, create_at: ..., updated_at: ...>] # こういう書き方も出来ます User.where(users[:lang].eq_any(['java', 'ruby'])).all # => [#<User id:2, name: "_ryog", lang: "java", age: 24, book_id: 2, create_at: ..., updated_at: ...>, # #<User id:3, name: "NowTom", lang: "ruby", age: 28, book_id: 3, create_at: ..., updated_at: ...>]
- not 条件
users = User.arel_table User.where(users[:name].not_eq('sinsoku')).all # => [#<User id:2, name: "_ryog", lang: "java", age: 24, book_id: 2, create_at: ..., updated_at: ...>, # #<User id:3, name: "NowTom", lang: "ruby", age: 28, book_id: 3, create_at: ..., updated_at: ...>, # #<User id:4, name: "tosikawa", lang: "python", age: 30, book_id: 2, create_at: ..., updated_at: ...>]
- 遅延評価してる例
pythonista = User.where(:lang => 'python') pythonista.all # => [#<User id:1, name: "sinsoku", lang: "python", age: 24, book_id: 1, create_at: ..., updated_at: ...>, # #<User id:4, name: "tosikawa", lang: "python", age: 30, book_id: 2, create_at: ..., updated_at: ...>] books = Book.arel_table pythonista_with_legacy = pythonista.where(books[:name].eq('レガシーコード改善ガイド')).includes(:book) pythonista_with_leagacy.all # => [#<User id:1, name: "sinsoku", lang: "python", age: 24, book_id: 1, create_at: ..., updated_at: ...>]
おまけ
Arelのソースを読める方や英語のドキュメントを探し出せる方*1には関係のない話ですが、
上記の方法以外で、簡単にArelのメソッドを調べる方法を紹介しておきます。
$ rails c $ ruby-1.9.2-p136 :001 > Arel::Table.new.[Tab]
Tab補完で、Arelのメソッド一覧が出てきます。
SQLっぽい単語を入れて、Tab補完で出てきたら、たぶんSQLと同じ意味で使えると思います。
*1:探したけど、私は見つけられなかった・・・