おぴよの気まぐれ日記

おぴよの気まぐれ日記

岡山やプログラミング、ファッションのこと、子育てや人生、生き方についての備忘録。

【Rails保存版】Active Recordで作ったオブジェクトを保存しよう!(save/update)

Ruby on Railsでデータベースを操作するのに使うActive Record。

今回は、saveupdateを使って実現するオブジェクトの保存方法紹介します。

今回利用するテーブル情報はこちらです。 f:id:opiyotan:20191003222737p:plain

基本的な使い方

保存する役割を果たすメソッドは以下の通りいっぱいあります。

  • save
  • save!
  • update
  • update!
  • update_attribute
  • update_attributes
  • update_attributes!
  • update_column
  • update_columns
  • update_all

それぞれの違いは、「戻り値の違い」と「コールバックの有無」です。

使い所や実行結果などをそれぞれ見ていきたいと思います。

save

  • よく使う処理: コントローラーのcreate
  • 戻り値: true/false

基本的に利用するのは、createアクションです。戻り値がtrue/falseになるので保存が成功したか失敗したかで処理を分けるように記述します。

# new_users_controller.rb
def create
  @user = NewUser.new(new_user_params)

  if @user.save
    redirect_to :new_users_path, notice: 'ユーザーを登録しました。'
  else
    render :new
  end
end
# 成功する場合
> user.name = 'opiyo'
=> "opiyo"
> user.save
   (0.3ms)  BEGIN
  NewUser Create (0.9ms)  INSERT INTO "new_users" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "opiyo"], ["created_at", "2019-10-07 12:09:45.517006"], ["updated_at", "2019-10-07 12:09:45.517006"]]
   (0.6ms)  COMMIT
=> true

# 失敗する場合
> user.save
   (0.3ms)  BEGIN
   (4.8ms)  ROLLBACK
=> false

save!

  • よく使う処理: モデル、rakeタスク
  • 戻り値: 例外(ActiveRecord::RecordInvalid)

基本的に利用するのは、モデルやrakeタスクなどで利用します。合わせて例外処理を書く場面が多いと思います。

self.transaction do
  self.name = 'opiyo'
  self.save!
end

begin
  user.name = 'opiyo'
  user.save!
rescue => e
  puts e
end

update

  • よく使う処理: コントローラーのupdate
  • 戻り値: true/false

基本的に利用するのは、updateアクションです。

def update
  if @user.update new_user_params
    redirect_to new_users_path(@magazine), notice: 'ユーザーを保存しました'
  else
    render 'edit'
  end
end
> user.update(name: 'opiyo')
   (0.3ms)  BEGIN
  NewUser Create (5.8ms)  INSERT INTO "new_users" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "opiyo"], ["created_at", "2019-10-07 13:03:40.364928"], ["updated_at", "2019-10-07 13:03:40.364928"]]
   (1.3ms)  COMMIT
=> true

update!

  • よく使う処理: モデル
  • 戻り値: 例外(ActiveRecord::RecordInvalid)

基本的に利用するのは、モデルやrakeタスクなどで利用します。合わせて例外処理を書く場面が多いと思います。

self.transaction do
  self.save!(name: 'opiyo')
end

begin
  self.save!(name: 'opiyo')
rescue => e
  puts e
end

update_attribute

  • よく使う処理: モデルやrakeタスク
  • 戻り値: true/false

基本的に利用するのは、モデルやrakeタスクです。

updateとの違いは、保存できるのは1つのカラムでvalidationを無視します。

# validationの設定
class NewUser < ApplicationRecord
  validates :name, presence: true
end

# 実行結果
> user.update(age: 1)
   (0.3ms)  BEGIN
   (0.3ms)  ROLLBACK
=> false

> user.update_attribute(:age, 1)
   (0.3ms)  BEGIN
  NewUser Create (0.4ms)  INSERT INTO "new_users" ("age", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["age", 1], ["created_at", "2019-10-07 13:29:20.417777"], ["updated_at", "2019-10-07 13:29:20.417777"]]
   (2.0ms)  COMMIT
=> true

update_attributes

  • よく使う処理: モデルやrakeタスク
  • 戻り値: true/false

基本的に利用するのは、モデルやrakeタスクです。

update_attributeとの違いは、複数保存ができ、validationは実行されます。なので処理の内容としてはupdateと全く同じです。

> user.update_attributes(age: 2)
   (0.3ms)  BEGIN
   (0.2ms)  ROLLBACK
=> false
> user.update_attributes(name: 'opiyo', age: 2)
   (0.3ms)  BEGIN
  NewUser Update (0.6ms)  UPDATE "new_users" SET "name" = $1, "age" = $2, "updated_at" = $3 WHERE "new_users"."id" = $4  [["name", "opiyo"], ["age", 2], ["updated_at", "2019-10-07 13:32:12.006308"], ["id", 7]]
   (2.9ms)  COMMIT
=> true

update_attributes!

  • よく使う処理: モデルやrakeタスク
  • 戻り値: 例外(ActiveRecord::RecordInvalid)

基本的に利用するのは、モデルやrakeタスクです。

update_attributesとの違いは、例外が発生します。なので処理の内容としてはupdate!と全く同じです。

update_column

  • よく使う処理: ajax使ってデータ更新するときやモデルやrakeタスク
  • 戻り値: 例外(ActiveRecord::RecordInvalid)

基本的に利用するのは、モデルやrakeタスクです。

updateupdate_attributeとの違いは、「validationを無視」「コールバック無視」「update_at無視」です。つまり保存するだけ。

update_columns

  • よく使う処理: ajax使ってデータ更新するときやモデルやrakeタスク
  • 戻り値: 例外(ActiveRecord::RecordInvalid)

基本的に利用するのは、モデルやrakeタスクです。

update_attributesと同じで複数カラムを同時に更新するときに使います。内容はupdate_columnと同じで「validationを無視」「コールバック無視」「update_at無視」です。

まとめ

  • create: save!
  • update: update
  • モデルやrakeタスク: save/update_attributes
  • ただ保存したい: update_columns
  • 例外: !

各メソッドの実行結果や、どうゆう時に何を使うかまとめてきました。

改めて見直すと、各メソッドの微妙な違いを意識して処理できてたか曖昧な部分もあるので見直したいなーと思いました。