Active Record クエリインターフェイス | Rails ガイド
2.条件
# 条件を配列で Client.where('orders_count=? AND locked=?', 2, true) # プレースホルダで書くとわかりやすい Client.where('orders_count=:count AND locked=:locked', count: 2, locked: true) # 以下の様な書き方はSQLインジェクションの危険があるので非推奨 Client.where("orders_count='#{params[:count]}'") # 条件をHashで指定(普段はこれを使うことが多い) Client.where(locked: true) # 範囲指定 Client.where(created_at: (Time.now.midnight - 1.day)..Time.now.midnight) # IN Client.where(orders_count: [1,3,5]) # NOT Client.where.not(orders_count: 1)
3. 並び順
Client.where.not(orders_count: 1).order_by(:created_at) Client.where.not(orders_count: 1).order_by(created_at: :asc, orders_count: :asc)
4.特定のフィールドだけを取り出す
- #where は、
SELECT * FROM
が実行される - 特定のフィールドのみ取得したい場合は、#select を使う
User.select(:name)
SELECT "users"."name" FROM "users"
戻り値
[#<User:0x007fe664264948 id: nil, name: "kobayashi">, #<User:0x007fe6642645d8 id: nil, name: "yoshida">, #<User:0x007fe664264150 id: nil, name: "tanaka">]
SELECT DISTINCT
User.select(:name).distinct
5. limit と offset
Client.limit(5) # 上限を指定 Client.offset(5) # スキップするレコード数 Client.limit(10).offset(5) # 両方
6.グループ
Order.select("date(created_at) as ordered_date, sum(price) as total_price").group("date(created_at)")
SELECT date(created_at) as ordered_date, sum(price) as total_price FROM orders GROUP BY date(created_at)
7.Having
Order.select("date(created_at) as ordered_date, sum(price) as total_price"). group("date(created_at)").having("sum(price) > ?", 100)
SELECT date(created_at) as ordered_date, sum(price) as total_price FROM orders GROUP BY date(created_at) HAVING sum(price) > 100
8.条件を上書きする
現状使うところがあんまりないので、こんなのがあるんだ程度で
- #unscope : 特定の条件を取り除く
- #only : 条件を上書き
- #reorder : 並び順の指定を上書き
- #reverse_order : 並び順を逆に
- #rewhere : where を上書き
9. Nullリレーション
10. 読み取り専用オブジェクト
#readonly をつけると、読み取り専用になる
11. レコードを更新できないようロックする
楽観的ロック
- 基本的には競合しないという前提
- データの更新をした時に、更新カウンタを増やす
- 変更の直前に更新カウンタをチェックして、増えていたら更新しない(ActiveRecord::StaleObjectError)
- 更新カウンタは(lock_version:integer)を、テーブルに追加するだけでOK!
- 具体的には、#find したデータを #save する時に、lock_version をチェックする
ActiveRecord::Base.lock_optimistically = false
でOFFにできる
悲観的ロック
- 排他処理を行う
- #transaction を使う
Item.transaction do i = Item.lock.first i.name = 'Jones' i.save! end
もしくは
item = Item.first item.with_lock do item.increment!(:views) end
MySQLならば、BEGIN 〜 COMMIT が実行される