Ruby
Rails
OriginalBitStarDay 21

Rails初心者が Active Reccordについてまとめてみた

はじめに

はじめまして!BitStarでエンジニアインターンをしている@kogriffey755です。
いまはRailsを学習しながらエンジニア業務をおこなっています。そんなぼくがRailsで???となった箇所をまとめてみました。初心者やこれからRailsをやろうかなと思ってるかたのためになれば嬉しいです
ではいってみましょー!!

1 Active Reccord について

まず、最初はActive Record についてです. Active Record とは、Active Record"とは、デザイン・パターンの一つらしい。SQLにプログラムから直接アクセスする方法もあるが...ちょっと不便
 データベースのテーブルをオブジェクトにマップすればいい
 というのが"Active Record"の考え方らしい へ〜〜〜
つまり、言い換えれば「ActiveRecordはRubyをSQLに翻訳していろいろ動作してくれているっぽいです
まあ、なんかやってんですね〜〜〜

1 Active Recordについて
Active Recordとは、MVCで言うところのM、つまりモデルに相当するものであり、ビジネスデータとビジネスロジックを表すシステムの階層です。Active Recordは、データベースに恒久的に保存される必要のあるビジネスオブジェクトの作成と利用を円滑に行なえるようにします。Active Recordは、ORM (オブジェクトリレーショナルマッピング) システムに記述されている「Active Recordパターン」を実装したものであり、同じ名前が付けられています

1.1 Active Recordパターン
Active RecordはMartin Fowlerによって Patterns of Enterprise Application Architecture という書籍で記述されました。Active Recordにおいて、オブジェクトとは永続的なデータであり、そのデータに対する振る舞いでもあります。Active Recordでは、データアクセスのロジックを確実なものにすることは、そのオブジェクトの利用者にデータベースへの読み書き方法を教育することの一部である、という意見を採用しています。

1.2 O/Rマッピング
オブジェクトリレーショナルマッピング (O/RマッピングやORMと略されることもあります)とは、アプリケーションが持つリッチなオブジェクトをリレーショナルデータベース(RDBMS)のテーブルに接続するものです。ORMを使用することで、SQL文を直接書く代りにわずかなアクセスコードを書くだけで、アプリケーションにおけるオブジェクトの属性やリレーションシップをデータベースに保存したりデータベースから読み出したりすることができるようになります。

1.3 ORMフレームワークとしてのActive Record
Active Recordにはさまざまな機能が搭載されており、その中でも以下のものが特に重要です。

モデルおよびモデル内のデータを表現する
モデル間の関連付け(アソシエーション)を表現する
関連するモデルを介した継承階層を表現する
データがデータベースに永続的に保存される前に検証(validation)を行なう
オブジェクト指向の表記方法でデータベースを操作する

2 自分がよくわかっていないものをまとめてみた

Active Reccord の使い方に関してはQiita 等によくまとめられているのでふだんはそれらを必死に漁りなんとか使えています,,,
そのなかでもここでは自分的によくわかってないものについてとりあげてみたいとおもいます

1 joins

joinsはテーブル同士を内部結合して検索するためのメソッドです。

内部結合とは、各テーブル同士で関連づけられたidが一致しているものだけを使って新しいテーブルを作ることです。

なので、idが一致しないものは切り捨てられます。

テーブルがいくつかに分けられている場合、1つ1つから必要なデータを見つけるよりも、テーブルを1つにまとめてから見つけるほうが楽

2 includes

includesはテーブルを結合してデータを扱うために用意されているメソッド。

includesでの結合は左外部結合で行われます。
結合には内部結合、左外部結合、右外部結合があります。
ようするに、左外部結合は左側のテーブルのカラムを優先して、結合するという意味です。

3joins と includes の違いってなんなの??

まず、2つのテーブルを結合する方法として、大きく内部結合と外部結合というものが存在しています。

  • 内部結合
    内部結合は、それぞれのテーブルの指定したカラムの値が一致するものだけを結合します。
    内部結合の場合、ベースとなるテーブルから、条件にマッチするレコードがないものは削除されるのです。

  • 外部結合
    外部結合は、内部結合のようにそれぞれのテーブルの指定したカラムの値が一致するものを結合するのに加え、どちらかのテーブルにしか存在しないものに関しても取得します。

① joins

デフォルトでINNER JOINを行う。LEFT OUTER JOINを行いたい時はleft_joinsを使う。
違いは、associationをキャッシュしないこと。
ActiveRecordのオブジェクトをキャッシュしない分メモリの消費を抑えられる。

なので、JOINして条件を絞り込みたいが、JOINするテーブルのデータを使わない場合はjoinsを使うのが良い。
User.joins().where(posts: {})とかUser.joins().merge(Post.)みたいに使う。

   User.joins(:avatar) 
   =>
   SELECT users.* 
    FROM users INNER JOIN avatars
      ON avatars.id = users.id AND avatars.bookname = 'User'

② includes

@posts = Post.includes(:user).all

includesは先読みしてキャッシュしておく
includesを使うことでN+1問題を解決することはできますが、includesを使用してusersテーブルを
取得する際のクエリが

select users.* from users where id in (1, 2, 3, ....)

となり不要なデータもselectしてしまっていて無駄があります。

そこで以下の様な解決策があります。
belongs_toでlamdaを渡す際にselectしてあげることでincludes等で関連テーブルをロードした際にもselectしたカラムのみ取得することができます。

3 最後に

 ほかにも eager_load とpreloadとかもあり、発行されるSQLが違うんだなーということが改めてSQL文をみて感じました。 Rails はけっこういろいろとやってくれているんだなーと Rails の公式ドキュメントをよんだりして理解を深めようかなーとおもいます!!!!
こんなところでおわりまーす