ActiveRecordわかんない(プログラミング)
SQL文でのデータの取り出しは何となくわかってきた。
ActiveRecordで同じ処理できたらめっちゃ便利なのはわかってるけど、メソッドの使い方がわかんなすぎる。つよつよなりたい。
Railsガイドのよくわかんない日本語とか頑張って読んでいって、自分が頭に入れやすい関西弁に直していく。
全部読むとあまりにも長いから、必要になりそうなところだけや(● ˃̶͈̀ロ˂̶͈́)੭ꠥ⁾⁾
割といろんなサイトパクっていくけど見せるようじゃなくて自分で見返すようやから問題ナッシング。noteの運営的にまずいのならはやく私を○してくれ〜
参考なりそうなサイトたち
モデル名とテーブル名と謎部分
ActiveRecord使うにあたってのRailsでの大前提!
命名規則的にもモデル名は単数系(頭文字は大文字)で、テーブル名は複数形になってる。下みたいな感じ。
で、
いきなりなんのことやな感じやけど下記の簡単なコードの時点で分からないので、まずこれ解消する
Film.find_by(title: "BLANKET BEVERLY").inventories.size
コードでやってること簡単に言えば、"BLANKET BEVERLY"ってタイトルの映画に関するデータをfilmsテーブルから探して、そのあとさらに関連付いてるinventoriesテーブルの数を数えることで在庫いくつあるのか調べるみたいなやつ。そして疑問点
=>
A. ActiveRecordでの操作は基本的にはモデルに基づいてるので、デフォルトはモデル名を使用して操作するけど、inventoriesはそのFilmモデルの中でhas_manyとかで関連づけているテーブルなのでテーブル名で指定してる!っていう感じ。もうこれわかったのでつよつよなきがする。
まずActiverecordってなんなん?
rubyとSQLの翻訳機的なもの。
RailsのモデルでActiverecordが適用されいているおかげでデータベースの操作ができる感じやな。DBとrailsが本来全く関係ないもんやから、SQL文も使えない。
ActiveRecordのメソッド使用することでrubyでもデータベース使用できるね!って感じ。
どのデータベース使用しても、Ruby内で同じ書き方ができるのも強いね!
メソッドチェーンってなんなん?
例えば下記コードですべてのユーザー取得できる。
users = User.all
で、例えばこっからさらに取得条件追加したいときに、「.(ドット)」でメソッド繋いでいってかけるやつ。
users = User.where(active: true).order(created_at: :desc)
#where(active:true)でアクティブなユーザーのみ取得してる。
#order(created_at: :desc)で降順ソートしてる。
上から追加でさらに繋げれる
users = User.where(active: true).order(created_at: :desc).limit(10)
# limit(10)で結果を10件に制限できる。
つまり何行にも分けんでも一気に書けるということかな。SQL文やとこの辺りができないから、そういったところで便利なのかも。
Read(参照)系のメソッド
ほんまにここつよつよなりたくて書いてる。データから条件つけて取り出す系のメソッド。使えそうなもの片っ端から拾っていく!
findメソッド
主キーから探すときに使うメソッド。
User.find(1)
#SELECT * FROM users WHERE (users.id = 1) LIMIT 1と同義
---
user.find(1,10)
もしくはUser.find([1,10])
とかで主キーが1と10のユーザーを検索
find_byメソッド
主キーのid以外のカラムで探す時に使う。
条件マッチするレコードのあった場合に、最初のレコードを取得するらしい。存在せんくても例外は発生しなくてnilを返すらしい。
User.find_by(name: "hoge")
#SELECT * FROM users WHERE (users.name = "hoge") LIMIT 1
firstメソッド
デフォルトは主キーの順で取得。orderを使って順序変更も可能。
レコードが1つもなくてもnil返すよ
User.first
# これがデフォルト。users.idの昇順で最初の1つを取得してる
# SELECT * FROM users ORDER BY users.id ASC LIMIT 1
User.first(3)
# これは最初から3つ取得できる
# SELECT * FROM users ORDER BY users.id ASC LIMIT 3
User.order(:name).first
# 本来users.idで順序づけられているところを、nameの昇順で並び替えたうえで1つ目を取得してる感じ
# SELECT * FROM users ORDER BY users.name ASC LIMIT 1
lastメソッド
lastは降順にして1つ取得。つまり最後のレコード取得してる感じ。
User.last
# SELECT * FROM users ORDER BY users.id DESC LIMIT 1
whereメソッド
もうほんまにSQLのwhereと同じ。
取得する数が異なるだけで、搾り方はfind_byと同じ。whereは該当するレコード全部取得やで。
User.where(name: "hoge")
# SELECT * FROM users WHERE (users.name = "hoge")
該当しない方を搾りたい場合はwhere.notでオッケー
User.where.not(name: "hoge")
# SELECT * FROM users WHERE NOT users.name = "hoge"
複数条件の場合は配列使えば大丈夫
User.where(name: ['takeshi', 'satoshi'])
#SELECT * FROM users WHERE users.name = "hoge" OR users.name = "foo"
# もしくは下みたいな書き方もあるけどちょっと長め
User.where(name: "hoge").or(User.where(name: "foo"))
orderメソッド
デフォルトでは昇順並び替え。careated_at: :descなどで指定すれば降順で並び替え可能。
フィールドが1つの場合は「:フィールド名」になるけど、
複数指定の場合or並び順指定の場合は「フィールド名: :並べ方」になること注意!!
User.order(:created_at)
# SELECT * FROM users ORDER BY users.created_at ASCと同義。
User.order(name: :asc, created_at: :desc)
# SELECT * FROM users ORDER BY users.name ASC, users.created_at DESC
limitメソッド
取り出すレコードの上限を指定できる
User.limit(3)
# SELECT * FROM users LIMIT 5
joinsメソッド
テーブルの結合行えるよ!SQLでいうJOIN テーブル名 ONと同じ。
自動的にテーブルの主キーと関連テーブルの外部キーが一致するレコードだけを取得してくれる感じ。←内部結合になってる。
User.joins(:posts)
# Userテーブルのidとpostsテーブルのuser_idが一致するレコードだけ取得
# SELECT users.* FROM users INNER JOIN posts ON (posts.user_id = users.id)
もし関連するレコードがpostsにない場合でもそれ含めて全部取得したいって場合は、左外部結合をつかうで〜!
User.left_joins(:posts)
# SELECT users.* FROM users LEFT OUTER JOIN posts ON (posts.user_id = users.id)
認識的には
1. 左側のテーブル(今回やとusersテーブル)にあるレコードを全部取得して
2. 左側に関連するのが右側(今回やとpostsテーブル)にあればそれも取得する
って意味での左外部結合。やから一般的には右外部結合っていうのはほぼ使わん感じやな。
includesメソッド
N+1問題避ける目的。クエリの回数減らせるし負担かからないよーてやつ。
例えば、usersテーブルとpostsテーブルが1:多で関連づけられてて全部のユーザーとその投稿を取得したいとする。
users = User.all # ここでまずユーザーの情報取得して...
users.each do |user|
user_posts = user.posts # ユーザー毎にpostsにレコードないか探すやつ!!めちゃ面倒!
# 取得してから何かの処理
end
上のような感じで書いてしまうと、最初の一回のクエリでユーザー全部取得して、その後一人一人のユーザーごとに投稿を探すクエリをせなあかんから、クエリの数めっちゃ多くなる。100人ユーザーおったら合計で101回クエリ実行するみたいな。
ここでincludesメソッドの出番〜!
users = User.includes(:posts).all
上みたいな感じでuser取得するときにincludesでpostsテーブルも一括で読み込んで仕舞えば、一発で全部取得できるって言う感じ。
コードも短くなるし処理も短くなるからめちゃ便利!!
count, length, sizeメソッド
全部レコードの数を数える系のメソッドではある。ちょっと使い分けややこしい。また別記事に分けて理解深めようとは思う。
・sizeはメモリ読み込まれてる場合はSQL文実行しないし、されていない場合は、SQL実行した上で数を取得してくれる。割と柔軟。
user_count = User.size
・countはどんな状況であれ、SQLクエリ実行してしまうし取得するの数だけみたいな感じ?要素数の情報しかのちのちも使わない場合は効率よきなやつ。
実際アプリの処理で使うってなった場合は、あんまり使い道に幅広さ感じないかも。
user_count = User.count
・length、これのsizeとの棲み分けが1番わかんにゃい。
基本的にはsizeと同じ。レコードがメモリにある場合は、その数値返すし、なかったらSQL実行するみたいな。
上の解釈がわかりやすいかも。
◆その他CUDのメソッド
生成形(create)メソッドのメモ
@movie = Movie.new(title: "タイトル", content: "内容")
@movie = Movie.build(title: "タイトル", content: "内容")
# どっちも新しくインスタンス作成するためのメソッド、まだデータベース自体には保存されてない
@movie.save
# 作成した@movieをデータベースに保存
Blog.create(title: "タイトル", content: "内容")
# newとsaveを一発でできるメソッド!!DB保存まで持っていけるよ〜!
📚newとbuildの違いは何なん?
Updateメソッド
@blog.update
Deleteメソッド
@blog.destroy
destory!とかcreate!とかあるけどまた今度(*´꒳`*)