
Ruby on Rails ActiveRecordメソッド 基礎編📝
目 的
・読んだ内容を構造的に整理しアウトプット
・自身が見返せるようにする為
・最近ActiveRecordの理解が足りていないことが判明した為
こんなに人に読んでほしい👀
・Ruby on Railsを学習する人|している人
・駆け出しエンジニア
・ActiveRecordの理解が低いと感じている人
では早速整理していきたいと思います😄
この記事で扱ってない内容〜😨
・MVCモデルについて
・ORM(オブジェクトリレーショナルマッピング)
・SQL振る舞いや書き方の説明
・オブジェクト指向
ActiveRecordてなんぞや??🍒
Active Recordとは、MVCで言うところのM、つまりモデルに相当するものであり、ビジネスデータとビジネスロジックを表すシステムの階層です。Active Recordは、データベースに恒久的に保存される必要のあるビジネスオブジェクトの作成と利用を円滑に行なえるようにします。
Railsガイドv6.0 ActiveRecord引用
https://railsguides.jp/active_record_basics.html
なるほど、つまりモデルは永続的にdbへデータオブジェクトを保存する為にActiveRecordを使用するということか。
ActiveRecordモデルを作成する〜⌨️
class Movie < ApplicationRecord
関連付け
has_many :reviews, dependent: :destroy
検証
validates :name, presence: true
validates :director, presence: true
validates :summary, presence: true, length:{ maximum: 140 }
getter/setter
attr_accessor :name, :director, :summary
private
フォーム入力許可チェック(StrongParameters)
def movie_params
params.require(:movie).permit(:name, :director, :summary)
end
end
ApplicationRecord > ActiveRecord::Baseを継承している
CRUDの書き方や振る舞い〜🍇
作成(create)
new:新規オブジェクトインスタンスの作成のみ
create:新規オブジェクトインスタンス&dbへレコードが1件作成(保存)される
<パターン1>
movie = Movie.new
movie.name = "君の名は"
movie.director = "深海誠"
movie.save
<パターン2>
Movie.create(name: "君の名は", director: "深海誠")
検索(read)
all:全モデルのオブジェクトを返す
first:最初(一番古い)のオブジェクトを返す 1件
second:2番目のオブジェクトを返す 1件
last:最後(一番新しい)のオブジェクトを返す 1件
find:引数にidのみ指定可能※引数は複数指定可(IN句なる)or条件
L該当データなし > ActiveRecord::RecordNotFound(例外発生⚠️)
find_by:id以外の属性を指定可能 与えられた条件の最初にマッチしたオブジェクを返す ※引数は複数指定可
L該当データなし nilが返ってくる(例外発生しない)
count:件数
order:並び替え(ASC、DESC)
where:データの集合(配列)※notパターンは割愛
番外
paginate(ページネーション)
実際にコードを書いてみます💡
movie.all > 戻り値:Active_Relation
SELECT "movies".* FROM "movies"
movies = movie.all.order("created_at: DESC")
SELECT "movies".* FROM "movies" ORDER BY create_at: DESC LIMIT ? [["LIMIT", 11]]
=> #<Movie::ActiveRecord_Relation:0xdac>
movies.map { |movie| puts (:&name)}
Movie.first
SELECT "movies".* FROM "movies" ORDER BY "movies"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<Movie:0x00007fdc37adcbc0 id: 1, name: "君の名は。", director: "深海 誠", summary: "ココロコネクト">
Movie.last
SELECT "movies".* FROM "movies" ORDER BY "movies"."id" DESC LIMIT ? [["LIMIT", 1]]
=> #<Movie:0x00007fdc38b67490 id: 10, name: "魔法科高校の劣等生 星の絆", director: "テスト太郎", summary: "主人公最強系">
引数1
Movie.find(params[:id])
SELECT "movies".* FROM "movies" WHERE "movies"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<Movie:0x00007fdc3991f740 id: 1, name: "君の名は。", director: "深海 誠", summary: "ココロコネクト">
引数複数(IN) > 戻り値:配列
SELECT "movies".* FROM "movies" WHERE "movies"."id" IN (?, ?, ?) [["id", 1], ["id", 2], ["id", 3]]
=> [#<Movie:0x00007fdc38bf4ca0 id: 1, name: "君の名は。", director: "深海 誠", summary: "ココロコネクト">,
#<Movie:0x00007fdc38bf4b88 id: 2, name: "冴えない彼女の育てかた Fine", director: "柴田 彰久", summary: "史上最強のギャルゲーを作る!!">,
#<Movie:0x00007fdc38bf4a70 id: 3, name: "SHIROBAKO", director: "水島 努", summary: "アニメ業界の事情をコミカルに描いている。">]
Movie.find_by(name: params[:name])
SELECT "movies".* FROM "movies" WHERE "movies"."name" = ? LIMIT ? [["name", "君の名は"], ["LIMIT", 1]]
Movie.where(name: "君の名は", director: "深海 誠").order("created_at")
SELECT "movies".* FROM "movies" WHERE "movies"."name" = ? AND "movies"."director" = ? ORDER BY created_at [["name", "君の名は"], ["director", "深海 誠"]]
Movie.count > レコード件数
Movie.where(id: params[:id]).paginate(page: params[:page])
SELECT "movies".* FROM "movies" LIMIT 30 OFFSET 0
SELECT COUNT(*) FROM "movies"
更新(update)
編集/更新するためのレコード(PK)を取得し値を上書き保存する
結論:パターン2は多くの属性を更新したい時に便利!
共通:find_by(対象カラム: "値" )
<パターン1>
属性を上書き:Movie.name = "値"
更新:Movie.save
<パターン2>
1行で
更新:Movie.update(対象カラム: "値")
<パターン3>
複数のレコードを更新
更新:Movie.update_all (更新したい列: "値")
実際にコードを書いてみます💡
<パターン1>
@movie = Movie.find_by(name: "君の名は") or Movie.find(params[:id])
データを上書き
@movie.name = "冴えないの彼女の育てかた"
@movie.save
<パターン2>
複数のデータを上書きする時に便利
@movie.update(name: "冴えない彼女の育てか")
<パターン3>
@movie.update_all(name: "魔法科高校の劣等生") > moviesテーブルの全レコードnameが更新
削除(delete)
更新と同様に削除するためのレコード(PK)を取得
最初に削除対象のレコードをfindしてくる。
<パターン1>
取得:find_by(対象カラム: "値")
1件の削除
destroy
<パターン2>
指定したデータの削除
destroy_by(対象のカラム: "値")
<パターン3>
全レコードの削除
destroy_all
実際にコードを書いてみます💡
<パターン1>
@movie = Movie.find(params[:id])
@movie.destroy
<パターン2>
nameが君の名はのレコードを全削除
Movie.destroy_by(name: "君の名は")
<パターン3>
moviesテーブルの全レコード削除
Movie.destroy_all
検証(バリーデーションチェック)👀 valid?
movies(db)テーブルへ保存する前に値が妥当か?を検証します
別記事にて投稿予定。。。🙇♂️
マイグレーション(db)へ変更を反映させる migration
こちらも量が多いため、別記事にまとめます🙇♂️
※検証、マイグレーションは後日 こちらへURl埋め込みます。
まとめ
ActiveRecordを振り返ってみて、正直まだまだ全然足りませんがあとは共同開発の中で使って都度理解していこうと思います。
ActiveRecord::Baseの中で用意されている便利なメソッドは今後も使うことになりそうです。
そしてActiveRecordの基礎の部分を紐解いた際に関連する検証やマイグレーションなど、多岐に渡ることからもRuby on Railsの中で大事な部分であることが分かりました。
今後も継続し、何か学習の過程にインプットした際には試しながら&記事にまとめアウトプットしていきます。
最後まで読んでくださり ありがとうございました✨