LoginSignup
94
85

More than 5 years have passed since last update.

【続・find と where の違い 】ActiveRecord::Relation を学ぶ。

Last updated at Posted at 2017-03-07

こんにちは。7cocoです。
先日 Qiita に書いた ActiveRecord の find と where の違い。 でのコメントを受け、 ActiveRecord::Relation について調べてみました。

自分用のメモになります。

ActiveRecordとは

  • データベースにクエリを発行する。
  • 様々なデータベースとの互換性がある。
  • データベースの種類にかかわらず同じ表記を使用できる。

データベースからオブジェクトを取り出す検索メソッド

上のメソッドは全て ActiveRecord::Relation のインスタンスを返します。
つまり今回注目するのはこのメソッドたちが返すものです。

## 単一のオブジェクトを取り出す

上記メソッドは単一オブジェクトを返します。

複数のオブジェクトをバッチで取り出す

上記は一度にメモリに読み込めないような大量のレコードに対するバッチ処理のためのメソッドです。

ActiveRecord::Relation

上で紹介したメソッドたちが返すもの。下記のようなメソッドがあります。

  • ==
    • レシーバと引数を == で比べる。
  • any?
    • レコードがあるかどうかを boolean で返す。
  • blank?
    • レコードが空であるかどうかを返す。
  • build
    • new メソッドのエイリアス
  • cache_key
    • クエリによってフェッチされたことのあるキャッシュキーを返す。キャッシュキーはマッチしたレコードの数と最終更新時刻とともにビルドされる。クエリにマッチするレコードや存在するレコードが更新または削除された時、キャッシュキーも変わる。
  • create
    • 新しいレコードを作ろうとする。バリデーションに失敗するとイニシャライズオブジェクトを返す。 ActiveRecord::Base.create と同じ引数をとる。
  • create!
    • createに似ているが、バリデーションエラーが起こった場合例外を吐く。
  • delete
    • SQLの DElETE ステートメントを用いて引数とマッチするプライマリーキーの行を削除する。そして削除した行の数を返す。配列を用いることで複数行の削除が可能。
  • 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 は検索クエリを組み立てるもので、検索結果のオブジェクトとは異なるもの。
  • 上記メソッドをチェインすることでクエリを走らせる回数を減らしつつ柔軟なデータの取得や操作が可能。
  • 使いこなすにはまだまだ経験と勉強不足。

参考文献

94
85
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
94
85