こんにちは。7cocoです。
先日 Qiita に書いた ActiveRecord の find と where の違い。 でのコメントを受け、 ActiveRecord::Relation について調べてみました。
自分用のメモになります。
ActiveRecordとは
- データベースにクエリを発行する。
- 様々なデータベースとの互換性がある。
- データベースの種類にかかわらず同じ表記を使用できる。
データベースからオブジェクトを取り出す検索メソッド
- create_with
- distinct ( 英語のページ )
- eager_load
- extending
- from
- group
- having
- includes
- joins
- limit
- lock
- none
- offset
- order
- preload
- readonly
- references
- reorder
- reverse_order
- select
- uniq
- where
- bind いいページが見つからない……。
上のメソッドは全て ActiveRecord::Relation のインスタンスを返します。
つまり今回注目するのはこのメソッドたちが返すものです。
## 単一のオブジェクトを取り出す
上記メソッドは単一オブジェクトを返します。
複数のオブジェクトをバッチで取り出す
上記は一度にメモリに読み込めないような大量のレコードに対するバッチ処理のためのメソッドです。
ActiveRecord::Relation
上で紹介したメソッドたちが返すもの。下記のようなメソッドがあります。
-
==
- レシーバと引数を == で比べる。
-
any?
- レコードがあるかどうかを boolean で返す。
-
blank?
- レコードが空であるかどうかを返す。
-
build
-
new
メソッドのエイリアス
-
-
cache_key
- クエリによってフェッチされたことのあるキャッシュキーを返す。キャッシュキーはマッチしたレコードの数と最終更新時刻とともにビルドされる。クエリにマッチするレコードや存在するレコードが更新または削除された時、キャッシュキーも変わる。
-
create
- 新しいレコードを作ろうとする。バリデーションに失敗するとイニシャライズオブジェクトを返す。 ActiveRecord::Base.create と同じ引数をとる。
-
create!
-
create
に似ているが、バリデーションエラーが起こった場合例外を吐く。
-
-
delete
- SQLの
DElETE
ステートメントを用いて引数とマッチするプライマリーキーの行を削除する。そして削除した行の数を返す。配列を用いることで複数行の削除が可能。
- SQLの
-
delete_all
- 最初にレコードをインスタンス化することなくレコードの削除を行う。そのため、
destroy
メソッドの呼び出しやコールバックの呼び出しは行われない。
- 最初にレコードをインスタンス化することなくレコードの削除を行う。そのため、
-
destroy
-
id
を渡されたオブジェクトを削除する。オブジェクトは初めにインスタント化される。
-
-
destroy_all
- それぞれのレコードのインスタンス化とその
destroy
メソッドの呼び出しを行ってレコードを削除する。
- それぞれのレコードのインスタンス化とその
-
eager_loading
- リレーションに eager loading が必要かどうかを返す。
-
empty?
- レコードがないかどうかを返す。
-
encode_with
- リレーションオブジェクトArrayをシリアル化する。
-
explain
- リレーションによって呼び出されるクエリーに
EXPLAIN
を走らせ、結果を文字列で返す。
- リレーションによって呼び出されるクエリーに
-
find_or_create_by
- 与えられた属性からレコードを見つける。見つからなかった場合はその属性のレコードを作成する。
-
find_or_create_by!
-
find_or_create_by
と大体同じだが、作られたレコードが invalid だった場合に例外を吐く。
-
-
find_or_initialize_by
-
find_or_create_by
と似ているが、create
の代わりにnew
を呼ぶ。
-
-
joined_includes_values
- プリロードのためのマークされているジョインを行う。eager load を行う必要がある。
-
load
- まだロードされていない場合、データベースからレコードをロードする。
-
many?
- レコードの数が1よりも大きいかどうかを返す。
-
new
- 現在のスコープを維持しながら relation から 新しいレコードを作る。
-
none?
- レコードがないかどうかを返す。
-
one?
- レコードがちょうど一つかどうかを返す。
-
reload
- リレーションのリロードを強制的に行う。
-
scoping
- 現在のスコープのすべてのクエリをスコープする。
-
size
- レコードのサイズを返す。
-
to_a
- relation object を Array にする。
-
to_sql
- relation の SQL statement を返す。
-
uniq_value
-
uniq
メソッドとuniq!
メソッドは非推奨。uniq_value
は後方互換性を維持するためにdistinct_value
に委譲する。代わりにdistinct_value
を使用すること。
-
-
update
- オブジェクトを更新してバリデーションを通過したらデータベースに保存する。
-
update_all
- 与えられた情報に現在の relation をのすべてのレコードを更新する。
-
where_value_hash
- where条件のハッシュを返す。
正直な感想としては「わー、なんかいっぱいあるんだなあ。」みたいな感じですが、 find_or_create_by
あたりは使いどころも多い便利メソッドなので積極的に使っていきたいです。
まとめ
- ActiveRecord::Relation は検索クエリを組み立てるもので、検索結果のオブジェクトとは異なるもの。
- 上記メソッドをチェインすることでクエリを走らせる回数を減らしつつ柔軟なデータの取得や操作が可能。
- 使いこなすにはまだまだ経験と勉強不足。