すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】 updateメソッドの使い方を徹底解説!

ぴっかちゃん
ぴっかちゃん

updateメソッドとは、すでにテーブルに保存されているデータを、新しい情報に更新するメソッドです。

updateメソッドの構文
1
モデルのインスタンス.update(更新データ)
updateメソッドの使用例
1
2
@item = Item.find(1)
@item.update(name: "Tシャツ", price: 1800)

updateメソッドは、以下の流れで使用します。

1.変数に、更新したいレコードの情報を代入する。
例では、Itemsテーブルのidが1番のデータを代入しています。

2.その変数に対してupdateメソッドを使用する。
updateメソッドの引数には、変更後のデータをハッシュ形式で与えます。

updateの引数について

ハッシュは通常、以下のように「キー」と「バリュー」を波括弧で囲みます。
 { name: "Tシャツ", price: 1800 }
そのため、これを引数にするなら本来は以下のように書きそうです。
 @item.update( { name: "Tシャツ", price: 1800 } )
しかし、Rubyではハッシュを引数で使う場合波括弧は省略できるため、省略して簡潔に書くのが一般的です。

updateメソッドの使い方

この章では、updateメソッドの使い方について解説します。

実際の書き方をみてみよう

updateメソッドは、通常ストロングパラメータとセットで使用します。

1
2
3
4
5
6
7
8
9
10
11
12
class ItemsController < ApplicationController

  def update
      @item = Item.find(params[:id])  # 1.インスタンス変数にセット
      @item.update(item_params)   # 2.updateメソッドの実行
  end

  private
    def item_params
      params.require(:item).permit(:name, :num)
    end
end

1. インスタンス変数にセット

@item = Item.find(params[:id])では、更新したいレコードの情報を@itemという変数に代入しています。

ここで、ユーザーが何番のidのレコードを更新しようとしているのか把握する必要があります。そのため、paramsを使用して取得しています。

2. updateメソッドの実行

@item.update(item_params)では、実際に更新するためのメソッドを実行しています。

updateメソッドの引数には「item_params」と記述しています。これはストロングパラメーターを使用して安全にデータを更新したいためです。

ここでは流れだけ確認しておきましょう。
ここで引数に指定している「item_params」はメソッドの名前です。まずこのメソッドが実行され、その結果がupdateメソッドの引数になります。

1
params.require(:item).permit(:name, :num)

item_paramsメソッドの、上記の部分が実行されると、ユーザーが入力した内容に従ってこのようなハッシュ(のようなもの)ができます。

1
{ name: "Tシャツ", num: 3 }

この返り値を、updateメソッドの引数に使用しています。 

updateメソッドはコントローラーのどこに書くか

updateメソッドは、コントローラーの7つのアクションのうち、updateの中に記述します。

通常editとセットで使用し、editで編集のためのビューの表示を、updateのなかで実際のデータ更新を行います。

アクション名 機能
index リソースの一覧を表示させる
show リソースの詳細を表示させる
new 投稿フォームを表示させる
create リソースを追加させる
edit 更新フォームを表示させる
update リソースを更新させる
destroy リソースを削除する

Railsではこの7つのアクションに従ってメソッドを記述することが、可読性を高める上で重要です。使いわけに自信がない場合は、「resourcesメソッドの使い方」の記事もご参照ください。

手元に置いておきたい1冊

こちらの「Webを支える技術」は、Webとは何か、Webの歴史から始まりWebサービスの設計まで思想や技術がこの1冊にまとめられています。

Webに携わる方は、ぜひ手元に置いておきたい良書です。

Ruby on Railsを学習している方は、主にWebアプリケーションを開発することが多いと思いますが、この本をおさえておけばWebに関する必要最低限の知識は学べます。

初学者にはやや難しい内容になっていますが、最初から全て理解しようとするのではなく手元に置いて必要になったら都度見返すのが良いでしょう。

他にもRailsの設計に関わる「REST」を解説しているので、ぜひ読んでおきたい1冊です!

webを支える技術
Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webサービスの実践的な設計について、包括的に解説されています。

似ているメソッドとの違いや使い分け

updateメソッドと似ているメソッドがいくつか用意されているので、その使いわけについて解説します。

update_attribute

レコードの、1つのカラムを変更できるメソッドです。updateとは引数の書き方が違い、カラム名と値をカンマで区切って指定します。

1
@item.update_attribute(:num, 100)

update_attributeの実行時は、バリデーションのチェックがされないため、特別な理由がある場合以外は使用しないことが好ましいでしょう。

update_attributes

update_attributesはupdateのエイリアスメソッド(別名)なので、動作は全く同じです。

upate_all

update_allは、レコードの全ての値を一括で変更できるメソッドです。

1
Item.update_all( num: 1)

このような記述で、Itemsテーブルの全てのレコードのnumカラムの値を1に変更することができます。今まで見てきたメソッドとは違い、クラスメソッドなのでItemなどのモデルに対して実行します。

また、実行時にバリデーションがかからないため、誤った操作をすると大きな影響が出てしまう可能性があります。使用するときは注意が必要なメソッドです。

update!

updateとupdate!メソッドの違いは、結果の返し方が異なります。
updateの場合、保存の成否をtrueかfalseで返します。それに対してupdate!は保存に失敗したときに例外を返します。

複数のデータ更新を順次行うときに、トランザクションという機能を使うことがあります。その場合はupdate!を使用すると、例外の発生とともにロールバック処理が行われるのでupdateより便利です。

更新がうまくいったときと、そうでないときで処理を分ける方法

バリデーションをかけている時など、更新処理に失敗することがあります。成功か失敗かで処理を分ける方法を解説します。

1
2
3
4
5
6
7
(省略)
if @item.update(item_params)
  redirect_to @item
else
  render :edit
end
(省略)

このような書き方で、更新できた場合はredirect_toメソッドが、失敗した時はrenderメソッドが呼ばれるように分岐することができます。

if分の条件式が少しわかりにくいので詳しく確認しましょう。

このようにupdateメソッドの返り値を変数resultに代入するとします。

1
result = @item.update(item_params)

この時、updateメソッドが成功するとresultに「true」が、失敗した時は「false」が入ります。

よって、返り値がtrueであれば条件が成立しますので、redirect_toが実行されます。逆にfalseであればelseの中身であるrenderが実行される、という流れになります。

updateメソッドがうまく実装できないときのデバッグ方法

更新処理がうまくいかない場合の解決手順を解説します。
全てのケースに当てはまるとは限りませんが、大抵の場合原因にたどり着くと思いますので参考にしてください。

基本的なデバッグの考え方

update関連のコードがうまくいかない場合のデバッグの考え方をご紹介します。
pry-railsを使った方法になりますので、使い方が不安な方は先にこちらをご確認ください。

Pryについて徹底解説!

updateがうまくいくためには、以下のコードが正しく動く必要があります。

  1. ビューから、ユーザーが入力したデータが正しく送信される。
  2. ストロングパラメータの許可が正しくできている。
  3. updateメソッドが正しく実行できる。

逆に言えば、エラーが出てしまう場合は上記の3点がうまくいっているのか、順に確認していけばよいということになります。

1. ビューからデータが正常に送信されているか確認する

1
2
3
4
5
6
7
8
9
10
def update

  binding.pry  

  if @item.update(item_params)
    redirect_to @item
  else
    render :edit
  end
end

binding.pryを使ってアプリを一度止めて内容を確認します。
まずはupdateの冒頭で確認するのがよいでしょう。

binding.pryの記述を追加したら、実際にブラウザで更新操作を行います。
「更新」ボタンを押すと動作が止まりますので、ターミナルを確認します。

ビューからのデータなどは、paramsというメソッドで取り出すことができます。

1
2
[1] pry(#<ItemsController>)> params
=> <ActionController::Parameters {"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"0SBiFfAqA/ecV9w4+xd3T+K3lBoxDZQiXnUgpgigQnb7HUeelCaMVIMQntTt4DB000pom4vwHfrBXlnvF9nA6A==", "item"=><ActionController::Parameters {"name"=>"abc", "num"=>"2"} permitted: false>, "commit"=>"Update Item", "controller"=>"items", "action"=>"update", "id"=>"1"} permitted: false>

このような表示がされます。情報が少し多いですが、注目すべきは「"item"=>」の直後です。

1
 {"name"=>"abc", "num"=>"2"} permitted: false

この前半のハッシュの中に、保存すべきデータが全て入っているかを確認します。もしなければ、ビューの記述に不具合がある可能性があるのでチェックしましょう。

2. ストロングパラメータの許可がうまくできているか確認する

①で問題がなければ、続いてストロングパラメータの設定が正しいか見てみましょう。

ターミナルで、ストロングパラメータの記述をしているメソッド名(例えばitem_paramsなど)を実行します。

うまくいっていれば、このような表示がされます。
・保存するためのカラムのデータが全てハッシュに含まれていること
・permitted: trueと表示されきちんと許可がされていること
この2点を確認しましょう。

1
{"name"=>"abc", "num"=>"2"} permitted: true

そうなっていない場合は、ストロングパラメータの設定が誤っている可能性がありますので、コードを確認しましょう。

また、ストロングパラメータについては、以下の記事で詳しく解説しています。
ストロングパラメーターについて徹底解説!

3. updateメソッドがうまくいっているか確認する

ここまで確認しても原因が特定できない場合は、最後にupdateメソッドの実行結果を確認してみましょう。

確認のために、ターミナルで実際にupdateメソッドを実行します。

1
2
3
4
5
6
[1] pry(#<ItemsController>)> @item.update(item_params)
   (0.3ms)  BEGIN
  ↳ (pry):7
   (0.2ms)  ROLLBACK
  ↳ (pry):7
=> false

updateメソッドに失敗している時は、このようにROLLBACKによってデータベースの更新が取り消されているはずです。

この原因を探るためには、errorsメソッドが活用できます。

1
2
3
4
5
6
7
8
9
10
11
[2] pry(#<ItemsController>)> @item.errors
=> #<ActiveModel::Errors:0x00007fd5d9a32008
 @base=
  #<Item:0x00007fd5db73e818
   id: 1,
   name: "abc",
   num: 200,
   created_at: Mon, 15 Jul 2019 14:23:18 UTC +00:00,
   updated_at: Sun, 28 Jul 2019 09:21:15 UTC +00:00>,
 @details={:num=>[{:error=>:less_than, :value=>200, :count=>5}]},
 @messages={:num=>["must be less than 5"]}>

上記の例で、@itemのupdateに失敗した時は、@itemの中にエラー情報が格納されます。それを取り出すのがerrorsメソッドです。

@messagesを見ると、「:num」に対して「"must be less than 5"」というエラーメッセージが出ていることがわかります。

これは、numカラムに「5未満」というバリデーションの設定をしているにも関わらず、それ以上の数で更新しようとしたことを意味しています。

そのため、5未満の数で更新すればうまくいくはずですし、実際のアプリ開発では少ない数の入力を促すメッセージを表示すべきでしょう。

この記事のまとめ

  • updateはテーブルのデータを更新するためのメソッド
  • うまく実装できないときはpryを使って原因を探ってみよう