更新日:
【Rails】 updateメソッドの使い方を徹底解説!
updateメソッドとは、すでにテーブルに保存されているデータを、新しい情報に更新するメソッドです。
1
モデルのインスタンス.update(更新データ)
1
2
@item = Item.find(1)
@item.update(name: "Tシャツ", price: 1800)
updateメソッドは、以下の流れで使用します。
1.変数に、更新したいレコードの情報を代入する。
例では、Itemsテーブルのidが1番のデータを代入しています。
2.その変数に対してupdateメソッドを使用する。
updateメソッドの引数には、変更後のデータをハッシュ形式で与えます。
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サービスの実践的な設計について、包括的に解説されています。
似ているメソッドとの違いや使い分け
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を使った方法になりますので、使い方が不安な方は先にこちらをご確認ください。
updateがうまくいくためには、以下のコードが正しく動く必要があります。
- ビューから、ユーザーが入力したデータが正しく送信される。
- ストロングパラメータの許可が正しくできている。
- 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を使って原因を探ってみよう