Open4

【Ruby on Rails】ActiveRecord::Relation

りかりか

ActiveRecord::Relation

Ruby on RailsのORM(Object-Relational Mapping)であるActive Recordにおける中心的なクラスの一つ
データベースのテーブルとアプリケーション内のオブジェクト間の「関係」を表現するためのもの

遅延評価 (Lazy Loading)

ActiveRecord::Relation オブジェクトは、それが実際に必要になるまでデータベースのクエリを実行しない。これを「遅延評価」と言う。
例えば、users = User.where(name: 'Alice') というコードがある場合、この行を実行した時点でデータベースへのクエリはまだ実行されない。
users を、例えば users.each のようにイテレート(繰り返し)するときに初めてデータベースのクエリが実行される。

チェーン可能

複数の ActiveRecord メソッドを連結して、複雑なクエリを組み立てることができる。
例えば、User.where(active: true).order(created_at: :desc).limit(10) のようにメソッドをチェーンできる。

不変性

ActiveRecord::Relation は不変オブジェクトであり、それに対する操作は新しい Relation オブジェクトを生成する。これは、元の Relation オブジェクトを変更することなく、さまざまなクエリ操作を行うことができるという意味。

スコープとの統合

scope メソッドで定義されたカスタムなクエリメソッドも、ActiveRecord::Relation オブジェクトとして返すことができ、それによって他の ActiveRecord メソッドと組み合わせることが可能。

配列ライクな動作

ActiveRecord::Relation オブジェクトは、配列のように振る舞うことができる。
例えば、each, first, last, map などのメソッドを利用できる。

SQLを直接書く必要が少ない

Active Recordと ActiveRecord::Relationは、データベースのクエリを直感的に書くことができるDSL(ドメイン固有言語)を提供する。これにより、ほとんどの場合でSQLを直接書く必要がなくなる。

総じて、ActiveRecord::Relationは、データベースのクエリを効率的かつ直感的に構築・実行するための非常に強力なツール。

りかりか

調べたけどあまりわかっていない…

りかりか

ActiveRecord::Relationとは何なのか、小学生にもわかるように説明していただけませんか?

もちろんです!

想像してみてください、あなたが図書館に行き、たくさんの本がありますね。もし、特定のジャンルやキーワードで本を探したいと思ったら、図書館員さんにリストをもらうことができます。

このリストは、あなたが探している本の情報だけを持っています。このリストは「どの本がほしいのか?」という情報を持っていて、本棚からそれらの本を実際に持ってくることができます。しかし、リスト自体は本ではありません。

ActiveRecord::Relation は、このリストのようなものです。データベースにある情報(本)をどのように取得するかの「リスト」や「指示」を持っているものです。そして、実際に必要な時に、その「リスト」に従ってデータベースから情報を取ってきます。

だから、ActiveRecord::Relationは「何を取ってくるか」の指示書のようなものと考えることができます!

りかりか

ActiveRecord::Relationの概念を理解するには、Railsでのクエリメソッドの動作を把握することが重要

ActiveRecord::Relationは、実際にはデータベースからのデータセットを表すオブジェクトだが、最初はただのクエリを表している

これは「遅延評価」や「チェーン可能」とも呼ばれる特性を持っている

  1. 遅延評価: ActiveRecord::Relationオブジェクトが作成されても、即座にデータベースへのクエリが実行されるわけではない
    実際にそのオブジェクトのデータが必要になるまでクエリの実行は遅延される
    たとえば、eachfirstto_aなどのメソッドが呼ばれたときに初めてクエリが実行される
  2. チェーン可能: ActiveRecord::Relationはメソッドチェーンでさらに詳細なクエリを組み立てることができる
    これにより、動的にクエリ条件を追加することができる

例:

# コントローラの話
users = User.where(active: true)  # ここではDBのクエリは実行されない
users = users.order(:created_at)  # まだクエリは実行されない
users = users.limit(10)           # ここまでクエリは実行されていない

# ビューの話
users.each do |user|
  puts user.name
end  # この時点で、上で組み立てたクエリが実際に実行される

この挙動のおかげで、必要に応じて条件を追加することができ、最終的に1つの効率的なクエリとしてデータベースに問い合わせることができる

しかし、一部のメソッド、例えばcountsumなどは、即座にデータベースクエリを実行する
これはそれらのメソッドが集計や特定の値を直接取得するためのものであるため
これらのメソッドを使用すると、ActiveRecord::Relationがもはや「待機中」ではなく、実際の値や結果を返す

結論として、ActiveRecord::Relationの戻り値や挙動は、それを呼び出すメソッドやその使用方法によって変わることがある