連載
» 2011年06月27日 00時00分 公開

Ruby on Rails3で学ぶWeb開発のキホン(4):ActiveRecordの更新系操作 (1/2)

前回はActiveRecordを使った参照について解説しましたが、今回は登録、更新、削除などの更新系を中心に見ていきます。

[大場寧子, 河野十行, 鳥井雪,株式会社万葉]

 前回の記事では、Ruby on Railsのモデル層を担当するActiveRecordの概要と参照系の操作について解説しました。今回は、登録、更新、削除などの更新系の機能を中心に見ていきます。

 登録・更新の際には、モデルに不正な値が保存されないようにデータをチェックして、問題があれば保存しないようにする「検証」(Validation)の仕組みが走ります。この検証機能の背後には、ActiveRecordのコールバックという仕組みがあります。コールバックを使うことで、登録、更新、検証、削除処理の前後に様々な処理を追加できます。今回と次回の2回にわたって、ActiveRecordの更新系操作のやり方とともに、検証、コールバックについて詳しく解説していきます。また、検証メッセージはローカライズのニーズが強い箇所なので、併せてRailsの国際化の仕組みについても触れます。

 なお、ActiveRecordには、例えば「店」と「店員」のように、関係のあるモデル同士(テーブル同士)をオブジェクト指向に沿った形で紐付ける仕組みとして「関連」(Association)があります。関連は非常に重要かつ魅力的な機能ですが、説明が複雑になるため、次々回に詳しく説明することにします。

前回のおさらい - ActiveRecordとRDB

 本記事を読み進めるにあたって、もう一度、ActiveRecordとRDBの関係を整理しておきましょう。ActiveRecordは、RDBの世界をオブジェクトの世界にマッピングします。基本的には、1つのテーブルが1つのActiveRecordクラスに対応し、1つのレコードが1つのActiveRecordインスタンスオブジェクトに対応します。なお、本記事では、ActiveRecordインスタンスオブジェクトのことをActiveRecordオブジェクトと呼ぶことにします。

 従って、今回解説する更新系の操作は次のような意味になります。

  • 登録…SQLのinsertを、モデルクラス/オブジェクトを通じて行う
  • 更新…SQLのupdateを、モデルクラス/オブジェクトを通じて行う
  • 削除…SQLのdeleteを、モデルクラス/オブジェクトを通じて行う

登録

 登録は基本的に次の2つのステップで行います。

  1. オブジェクトの生成
  2. 生成したオブジェクトをDBに保存する

 このために利用するメソッドは、1と2を別々に行うか同時に行うかと、プログラマがその保存が成功すると「信じている」かそうでないかによって、以下の表のように4つに分類することができます。

  保存は失敗するかもしれない 保存が成功すると信じている
1と2を別々に行う (1) instance.save (3) instance.save!
同時に行う (2) ModelClass.create (4) ModelClass.create!
表1 登録のための4つの基本的な方法

saveとcreateと違い

 表1の(1)と(2)の違いは、2つのステップを自分で順番に行うか、モデルクラス側でいっぺんにやってもらうかの違いです。また、返り値も異なります。

 まずは(1)のsaveについて見ていきましょう。saveを使用する場合は、あらかじめオブジェクトをnewなどで作成しておく必要があります。

user = User.new(:name => 'yuki.torii', :email => 'xxx@everyleaf.com') 
if user.save 
  …
elseend

 saveの返り値は、保存が成功したときはtrue、失敗したときはfalseとなります。

 保存が失敗するとはどういうことでしょうか? 保存が失敗する主な原因は、検証を通らないことです。例えば、必須の入力項目をユーザーが入れなかったときなどに発生します。

 createを使うと、オブジェクトの生成と保存を1行で指示することができます。簡潔に書けますね。

obj = User.create(:name => 'yuki.torii', :email => 'xxx@everyleaf.com')

 createの返り値は、生成されたオブジェクトになります。ここでひとつ注意すべき点があります。それは、保存が成功してもしていなくても、返り値は同じく生成されたオブジェクトとなることです。保存されたかどうかを確認するには、例えば次のようにオブジェクトを調べる必要があります。

if obj.new_record?
  # あれ、保存されていない!
  ...
else
  ...
end

 そのため、保存に失敗する可能性を懸念する場合は、(4)のcreate!のほうが使い勝手が良いかもしれません。

 両者の使い分けとしては、生成と保存を同時に行って良い場合は、簡潔に書けるcreate/create!を使い、そうでないときはsave/save!を使うようにすると良いでしょう。後者の例としては、次のようなケースがあります。

  • 一度オブジェクトを作成したあとに属性の操作などを行ってから保存したい
  • 既存のレコード由来のオブジェクトと新規のオブジェクトをあわせて同じsave/save!で処理したい

 save/save!は、新規データの登録と、既存データの更新の双方に使うことが出来るメソッドとなっているため、上記の2つめのようなケースで使うのに適しているのです。

「!」の有無による違い

 saveとsave!、createとcreate!は基本的な動作は同じで、保存に失敗したときの動作だけが異なります。これらの4つのメソッドで、保存に失敗したときの動作は次のようになります。

メソッド 保存に失敗したときの動作
save falseが返る
create 生成されたオブジェクトが返る。オブジェクトはnew_record?のまま
save! 例外が発生する
create! 例外が発生する

 一般的にプログラミングでは、例外は「例外的な失敗」に対して使います。つまり、save!やcreate!は、プログラマが次のように考えている時に使うべきメソッドといえます。

  • この保存は必ず成功するはず
  • もし失敗するとすればプログラムミスや環境に異変があるなどの異常事態

 逆に、saveやcreateは、「ユーザーの入力次第では保存が失敗するかもしれない。その場合は別途、対応しよう」と考えるような場面で使うのに適しています。

       1|2 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。