データの検索
では、実際にそのUserモデルを使っているソースコードを読んでいきましょう。まずは、データベースからデータを検索して取得する部分からです。
Userモデルを利用して、Usersテーブルからデータを検索する際に使うのは、ActiveRecordに用意されたfindメソッドを使います。findメソッドは、クラスメソッドとして用意されています。
では実際に、Userモデルのfindメソッドを呼び出すソースコードはどこに記述するのが一般的でしょうか。それが、MVCのCに当たるコントローラ部分になります。コントローラ部分は、ユーザーからのアクションを受けて処理が実行されますが、その中でMVCのMであるモデルを呼び出します。
参考となるソースコードですが、管理機能のユーザー情報の編集をする画面を表示するアクション部分で説明します。ユーザー情報の一覧画面から「編集」というリンクをクリックすると、「ユーザ情報編集画面」へ遷移するのですが、その際の処理が、指定された任意のユーザー情報を検索して画面に表示するという動きになっています。
図2 ユーザ情報編集画面への遷移 |
この「編集」をクリックして実行される部分のソースコードは以下です。
45 |
def edit |
app/admin/controllers/users_controller.rb |
46行目で、Usersテーブルからデータを検索するためにfindメソッドを呼び出しています。Webブラウザからのリクエストに含まれるパラメータのうち、idを引数にして呼び出していることが分かります。これによって、実際にはSQLでは以下のようなクエリが発行されることになります(例:params[id]を37とします)。
SELECT * FROM users where id = 37; |
取得したデータは、上記ソースコードでいえば、@userという変数に代入されて、Rubyオブジェクトとして扱うことができるようになります。Usersテーブルのカラム名が、そのままオブジェクトのアクセッサとなり、値の取得が可能となっているのです。
このように、ActiveRecordを使うことで、SQLを直接書かなくても、Rubyのコードだけでデータベースにアクセスするコードを記述することができるのです。
データの更新
データの取得の次は、データの更新処理について読んでいきましょう。対応するテーブルのカラム名が、オブジェクトのアクセッサになるということは前述のとおりです。
Usersテーブルにはnameというカラムが存在しています。前述のfindメソッドを使って取得したオブジェクトを、@userという変数に代入したとすると、@user.nameと記述することで検索したレコードのnameカラムの値を取得できます。
逆に、@user.nameに対して値を代入することも可能です。ただし、代入の処理を記述しただけでは、まだデータベースへの保存はされておらず、メモリ上で変更されているにすぎません。
そこで、saveメソッドを使います。値を変更したオブジェクトのsaveメソッドを呼ぶことで、実際のデータベースに変更が反映、保存されます。新規のレコードを作成する際は、findメソッドを使わずにnewメソッドを使って作成できます。
実際のソースコードは、前節のデータの検索で表示した「ユーザ情報編集画面」から「更新」ボタンを押した際のアクションで読んでみることにします。
図3 ユーザ情報編集画面 |
以下のソースコードは、既存のデータを上書きする操作になっています。
57 |
def update |
app/admin/controllers/users_controller.rb |
58行目で用意した@userオブジェクトに対して、65行目でsave!メソッドを使って保存を行っています。!マークの付いたsave!メソッドでは、データの保存に失敗した場合に例外をスローするようになります。従って、失敗した場合のことは気にせずに、66行目、67行目の正常系の処理が続いています。
save!の直前の59行目から64行目の処理は、この管理機能の仕様の「編集者自身が本人のデータを編集できない」という部分を実装しています。60行目のstatusや、61行目のadminメソッドが、カラムの情報から生成された動的なメソッドです。
save!で、メモリにあった情報をデータベースへ保存したわけですが、その事前のデータの設定はどこで行われたのでしょうか。58行目のmake_user_by_idがその処理に当たります。このメソッドは、SKIP独自のもので、ActiveRecordを継承したモデルクラスで実装しています。以下がそのソースコードです。
82 |
def self.make_user_by_id(params, admin = false) |
app/models/user.rb |
84行目が前節のデータ検索で行ったfindメソッドを使っている個所です。次の85行目でパラメータを代入しています。このメソッドの最後の90行目でuserオブジェクトを返していますが、この時点ではデータベースに保存はされておらず、上記のコントローラの処理で保存されることになります。
2/4 |
Index | |
ActiveRecordを使ったソースコードを読もう | |
Page1 SKIPバージョン1.0リリース! MVCモデルのM |
|
Page2 データの検索 データの更新 |
|
Page3 値の検証(バリデーション) コールバック |
|
Page4 テーブルの関連 トランザクション |
Railsコードリーディング 〜scaffoldのその先へ〜 |
Ruby/Rails関連記事 |
プログラミングは人生だ まつもと ゆきひろのコーディング天国 ときにプログラミングはスポーツであり、ときにプログラミングは創造である。楽しいプログラミングは人生をより実りあるものにしてくれる |
|
生産性を向上させるRuby向け統合開発環境カタログ Ruby on Rails 2.0も強力サポート 生産性が高いと評判のプログラミング言語「Ruby」。統合開発環境を整えることで、さらに効率的なプログラミングが可能になる |
|
かんたんAjax開発をするためのRailsの基礎知識 Ruby on RailsのRJSでかんたんAjax開発(前編) 実はAjaxアプリケーション開発はあなたが思うよりも簡単です。まずはRuby on Railsの基礎知識から学びましょう |
|
Praggerとnetpbmで作る画像→AA変換ツール Rubyを使って何か面白いものを作ってみよう! 一般的な画像をアスキーアートに変換するツールを作ってみる。さらに出力にバリエーションを持たせてみよう |
|
コードリーディングを始めよう Railsコードリーディング〜scaffoldのその先へ〜(1) 優れたプログラマはコードを書くのと同じくらい、読みこなす。優れたコードを読むことで自身のスキルも上達するのだ |
|
- プログラムの実行はどのようにして行われるのか、Linuxカーネルのコードから探る (2017/7/20)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。最終回は、Linuxカーネルの中では、プログラムの起動時にはどのような処理が行われているのかを探る - エンジニアならC言語プログラムの終わりに呼び出されるexit()の中身分かってますよね? (2017/7/13)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、プログラムの終わりに呼び出されるexit()の中身を探る - VBAにおけるFileDialog操作の基本&ドライブの空き容量、ファイルのサイズやタイムスタンプの取得方法 (2017/7/10)
指定したドライブの空き容量、ファイルのタイムスタンプや属性を取得する方法、FileDialog/エクスプローラー操作の基本を紹介します - さらば残業! 面倒くさいエクセル業務を楽にする「Excel VBA」とは (2017/7/6)
日頃発生する“面倒くさい業務”。簡単なプログラミングで効率化できる可能性がある。本稿では、業務で使うことが多い「Microsoft Excel」で使えるVBAを紹介する。※ショートカットキー、アクセスキーの解説あり
|
|