Ruby on Rails

入門5

  • 前回のまでで、基本の機能【 CRUD 】について学び、【 newファイル 】【 editファイル 】を作成し、コントローラにはアクションメソッドを用意したところでした。
  • さっそく続きをやっていきましょう。

前回の確認

  • では、まずは作成した【 newファイル 】【 editファイル 】を、とりあえず以下のように編集してください。

仮のビューファイルを作る

editファイル( app/views/books/edit.html.erb

newファイル( app/views/books/new.html.erb

  • もちろん、これで完成というわけではなく、後でしっかり作っていきます。
  • まずは「それぞれのページに、アクセス(表示)できるようにする設定」を先にしていきます。
  • 表示されるためには、以下の動きが必要でした。
    1. 「サイトを見る人(ブラウザ)」からの「リクエスト(要求)」があった時に、適切なコントローラのメソッド(アクション)へのルートを用意する。
    2. ルートに対応したコントローラーが、データをデータベースから取得し、それを元にビューを渡す。
    3. ビューが、データを元にHTMLを作る。
  • つまり「ルーティング」「コントローラ」「ビュー」の順番になりますので、この順番通りに作っていきましょう。
    1. まずはルート設定からです。次へ。
  • ルート設定と言えば【 routesファイル 】ですね。
  • ここに、newページ と、editページ 用のルートを作ります。以下のように編集してください。※コメント部分は削除しています。
  • URLの末尾に「 /books/new 」が付いていれば、booksコントローラ の newメソッド が実行され、
  • 「 /books/edit/パラメータ 」が付いていれば、booksコントローラ の editメソッド が実行される、という設定ですね。
  • editに関しては「 どの本を編集するのか? 」という指定が必要なため、show と同じようにパラメータ(id)を指定しています。

routesファイル

  • 試しに、ページを表示してみましょう。
  • これでルート設定(ルーティング)がうまくいっていることが確認できました。
  • 尚、editページですが、まだ「パラメータによって、表示内容を変える」ということはしていないので、どんなパラメータを指定しても同じページが開きます。

routesファイル

editページ

newページ

  • では次は、コントローラーの設定です。
  • booksコントローラー( app/controllers/books_controller.rb )を以下のようにしてください。
    • ※今回変更する箇所は、newメソッド と editメソッド だけですので、それ以外のコードは下の画像には、のせてません。
    • ※ただ省略しているだけなので、削除したりはしないでください。newメソッド と editメソッドの部分だけ変更してください。
  • newメソッド の「 Book.new 」の部分は、「新しいレコードを作る」という意味です。それが @book に代入されます。
  • つまり、@book の中身は、まだ中身が空っぽのレコード(1冊の本のデータ)という感じです。
    • ※正確には、現時点では Bookクラスのインスタンスというものが作成されています。
    • ※データベースに保存(.save)してからレコードになります(保存しなかった場合は、インスタンスは削除されます)
  • editメソッドに関しては showメソッド とまったく同じですね。
  • URLで指定したパラメータを元に、データベースの idカラム から、レコード(1冊の本)を持ってくるという意味です。

コントローラ

editメソッド

newメソッド

  • 最後はビューを変更します。
  • 今回作る newページ と editページ は「データをデータベースに登録するため」のページです。
    • 今まで作った indexページ と showページ は「データを表示するだけ」でした。ここが大きく違う点です。
  • 「データをデータベースに登録するため」のページは、基本的に「 form(フォーム)」があります。→の画像のように、サイトを見る人が、何かしらを入力するような画面のことです。
  • HTMLだと <form>タグ を使って、フォームを作りますが、Railsでは専用のコードが用意されており、それを使ってフォームを作るのが基本です。
  • では、まずは newページ から作っていきましょう。次のページへ。

ビュー

  • app/views/books/new.html.erb 」を以下のように変更してください。

ビュー

  •  form_with 」がフォームを作成ために、Railsで用意されているメソッドです。(ヘルパーメソッドという)
    • ※フォームを作るメソッドは色々ありますが、基本的には form_with を使います。(Railsのバージョン4以前は、form_forが基本でしたが)
  • ()の中の引数部分は細かくなるので、また後で説明します。
  • とりあえず、これでページを確認してみましょう。次へ。
  • ちゃんと表示されたらOKです。※まだ、登録を押してもエラーになります。

ビュー

  • 今は入力できるのが「タイトル」だけですよね?
  • 他にも「読んだ日(dateカラム)」や「評価(starカラム)」や「感想(impressionカラム)」が bookモデルにはあります。
  • それもフォームから登録できように、フォームを変更しましょう。
    • ※もし、出来そうならチャレンジしてみてください。とりあえずは下のような表示になればOKです。
  • 答えは次のページ。
  • 以下のように変更したら良いですね。※カラム名の部分など間違いやすいので、注意してみておいてください。

ビュー

  • また、どのコードが、画面のどこにつながるのか、なんとなくで良いので意識しておいてください。

ビュー

  • さらに改良します。
  • 入力欄(フィールド)が横に並んでいると使いづらいので、縦に並べるために<p>で囲んでおきます。
  • かなり適当なHTMLですが、今はRailsの方に集中したいので、気にしないで行きましょう。

ビュー

  • 大体今はこんな感じの画面になっていると思います。

ビュー

  • 今はすべて「文字」で入力するフィールド(text_field)のため、ちょっと使いにくいです。
  • 「読んだ日」はマウスで日付を選択できた方が良いですし、「感想」は1行だけだと短すぎるので、もっと入力フィールドが大きくないと使いにくいですよね?
  • ということで、さらに改良します。次のページへ。
  • 以下のように変更してください。※書いてない部分は省略しているだけなので、消さないでください。

ビュー

  • このように変更できたら、再度ページを確認してみましょう。次へ。
  • 以下のようになればOKです。実際にフォームを触ってみてください。

ビュー

  • このようにRailsでは必要に応じて、色々なタイプのフィールドを作れるようになっています。
    • ※他にもまだまだありますが、とりあえず今はいっぱいある、ということをわかっていればOKです。
  • では、とりあえずビューに関してはOKとすることにして、実際に「登録」ボタンを押した時に、データベースに登録できるようにするためにはどうするか?という話に進みましょう。
  • まぁ詳しい説明の前に、一旦フォームの「登録」ボタンを押してみましょう。以下のようなエラーになるはずです。

ビュー

  • 「Routing Error」(ルーティング エラー)と出ていますね。
  • 「ルーティングってことは、ルート設定がおかしいのかな?」っと思った人は素晴らしいです。よくわかっています。
  • そう、これはルートがわからない(どこのコントローラーのメソッドで処理させるかわからない)ためにエラーが起きています。
  • 実はフォームというのは、基本的に登録ボタン(実際には送信ボタン)を押すと、入力したデータを送信すると同時に「どこかのURLを開く(遷移:せんい と言う)」処理が動きます。
  • その時に「どこに行っていいかわからない」という状態が今です。次へ。
  • では、この「どこのURLに行くか」の設定は、どこにあるかと言うと、先ほどのコードの以下の部分になります。

ビュー

  • url 」って書いてますもんね。
  • じゃあ url の右の「 book_index_path 」とはなにか?というと「 ~/books/index 」の事です。
    • 結構前に作ったきりの、indexページです。→のページ
  • Railsでは「 ~/books/index 」なら「 book_index_path 」みたいに、別名が付けられています。
    • ルートヘルパーメソッドといって、URLの指定を便利にするもので、変数みたいな感じで使います。
    • (長いので、以後ルートヘルパーと呼びます)
  • 新しい本を登録した後は、この「本の一覧ページ(indexページ)」に行く、という設定なわけです。
  • この設定自体は別に良いはずなのですが、なぜルーティングエラーになるのでしょうか?
    • 「 ~/books/index 」のページは、普通にアクセスできるはずですよね?
  • これの答えが「HTTPメソッド」というものになります。次へ。
  • 「HTTPメソッド」が何かと言うと、サイトを見る人(正確にはブラウザ:クライアントともいう) が サーバ(今回はRails)にお願いする時の「お願いの種類」のことです。
  • 例えば、ただ「このURLのページを見せて」という「お願いの種類」なら「 get (ゲット)というHTTPメソッドを送信します。
  • 今回のように「データを登録して」という「お願いの種類」の場合は、一般的に「 post (ポスト)というHTTPメソッドを送信します。
  • このように HTTPメソッドとは「お願いの種類」に応じて、適切に使いわけられています。
    • ※もう少し正確にいうと、「データベースに登録して」という場合も get を使うことは出来ますが、get は登録するデータが丸見えになるため、セキュリティの都合で post を使います。
  •  HTTPメソッドは色々な種類がありますが「 get 」「 post 」と「 patch (パッチ:部分更新)delete (デリート:削除)を主に使います。
  • このHTTPメソッドが、どこで設定されているかと言うと、先ほどのコードの以下の場所です。

HTTPメソッド

  • method(メソッド)と、post て書いてますよね?
  • では、今度はルート設定を確認しなおしてみましょう。次へ。
  • ルート設定と言えば「 config/routes.rb 」です。今は以下のようになっています。

HTTPメソッド

  • get という文字が books/index の所に書いてますよね?
  • これは「 get メソッドで、/books/index にアクセスがあった時」という意味になります。
    • つまり「 post だった場合 」のことは何も書かれていないのです。
    • だからルートがわからずにルーティングエラーになっています。
  • じゃあ post のルートも追加してあげましょう。次へ。
  • 以下のように post でも /bools/index に行けるようにルートを追加してください

ルーティング

  • ルートが出来たので、もう一度登録ボタンを押して、試してみましょう。
    • ※とりあえず本の名前とかは、aaaみたいにしておいてください。
  • エラーにはならず、ちゃんと indexページが開くはずです。→
  • 次のページへ。
  • ふー良かった良かった、と思うのはまだ早い!
  • 実はまだデータは登録されていません!(indexページも何も変わってないですよね?)
  • そう、ただ indexページが開くようになっただけで、登録の処理はなにもしてないからです。当然データベースにも登録されません。
  • 少し話をさかのぼってみると、新規登録をするために「 createメソッド 」というのを用意したのを覚えているでしょうか?
  • これがまったく使われていませんね。今度はこの createメソッド を使って「データを新規登録する」ということをやっていきます。
  • つまりフォームの「登録」ボタンを押したら、すぐに indexページ に行くのではなく、先に「 createメソッド 」を実行してから、indexページを開く、という流れになります。
  • とりあえず、ルート設定をやり直します。以下のようにしてください。

ルーティング

  • これで「postメソッドで、/books/index のURLが指定された場合は、booksコントローラーの createメソッドを実行する」というルートになりました
  • 次は createメソッド を作っていきます。
  • ここでは「フォームから送信されてきたデータを受け取って、データベースに新規登録する」という処理が必要ですね。
  • 以下のようにしてください。※ createメソッド 以外は画像にのってないですが、消してはいけません。

createメソッド

  • これはまだ途中段階ですが、以前、初期データを登録するときに seedファイル というのを作ったと思いますが、それと同じ書き方です。
  • 最初に @book = Book.new で新しい bookクラス のインスタンス(セーブしたらデータベースのレコードになる)を作り、そのカラムに、名前や日付などを入れて、最後に @book.save で保存する、という流れです。
  • 今は、= の右側部分が空白ですが、ここにフォームから送信されたデータが入ることになります。次へ。

フォームから送信されてくるデータを指定する

  • つまり後はフォームから送信されてくるデータを、どうやって取得すれば良いか?ということだけです。
  • フォームから送信されてくるデータは、params(パラムズ)に入れられているので、そこから取り出す、ということになります。
    • params は、URLの末尾につけたパラメータも入っていましたね。
    • Rails では、様々な送信データのやり取りは基本的に params を使って行います。
  • では、今回はどのように取り出せば良いか?というと、以下のように書きます。

createメソッド

  • あまり馴染みのない書き方かもしれませんが、フォームから送信されてくるデータを取得するには「 params[:モデル名][:カラム名]  」と書きます。次へ。

ハッシュのネスト構造

  • この「 params[:モデル名][:カラム名]  」という書き方は、ハッシュが2重になっている構造です。

[:book]

params

ハッシュ

book

ハッシュ

[:id]

[:name]

[:date]

[:star]

[:impression]

これが「:book」に入っている(紐づいている)

  • つまり「 params[:book][:name] 」の場合は「 params[:book]の中の、(つまりbookハッシュの)[:name] 」という指定になります。
  • フォームを使って送信した場合、このような形で、params に入れられます。
  • これでデータの新規登録はOKです。ただ試す前に、もう一つやることがあります。
  • 登録した後に、結局どのページを開くのか?というのが決まっていません。
    • ルート設定の「post 'books/index' => 'books#create'」という設定は、この createメソッド を実行する、という設定であって、indexページを開く設定ではありません。
    • なので、データの保存後に、再度indexページを開く処理を書きます。それが以下です。

createメソッド

  • redirect_to ルートヘルパー(URL)」と書けば、そのルートへ、get メソッドでアクセスしてくれます。
    • つまりルート設定の「 get 'books/index' 」へ、アクセスされます。ここまで出来たら、実際に本を登録してみましょう。
  • フォームから登録後、indexページに本が追加されていれば成功です。

createメソッド

  • これで「新規作成」、CRUDの内「 C(create)」は完了しました。後は「U」と「D」だけですね。
  • では、「U(update)」を作っていきます。
  • これは、すでに登録している本のデータ(レコード)の「編集」のことでしたね。
  • まずは editページ を仕上げていきたいと思いますが、実は newページ とほとんど同じでので、コピペを活用してください。
    • 次のページへ。

editファイル

  • editファイルを以下のようにしてください。

editファイル

newファイルと違う点は

赤線の3か所だけです。

book_update_path(@book)に関しては、

次のページで解説します。

  • url として設定した「 book_update_path(@book) 」なのですが、実はまだこのルートヘルパーは存在していません。(なのでエラーになります)
  • newファイルの時に使った「 books_index_path 」というルートヘルパーは、Railsが勝手に作ってくれていたのですが、すべてのヘルパーを作ってくれるわけではないので、必要なものは自分で作ります。
  • 作る場所は、ルートの設定なのでもちろん「 routes.rb 」です。以下の箇所を追加してください。

ルート設定と、ルートヘルパー設定

  • 赤枠の部分が通常のルートの設定です。patch メソッドで「 ~books/パラメータ 」のURLにアクセスがあれば「 booksコントローラーの、updateメソッド 」にルートを作っています。ここまでは、new の時と同じ感じです。
  • 青枠の部分が「ルートヘルパー」を設定している部分です。これで「 books_update_path(:パラメータ) 」というルートヘルパーが使えるようになります。 次へ。
  • また、update だけじゃなく、showページに対してルートヘルパーも自分で作らないといけないため、先に設定しておきます。
    • ※(「編集」が完了した後は、編集した本の show ページを表示する予定なので)
  • showに関しては、すでにルート設定はあるので、ルートヘルパーの設定だけ追加します。

ルート設定と、ルートヘルパー設定

  • これで「 book_show_path(:パラメータ) 」とすれば、指定した本の showページ が開くようになります。次へ。
  • 最後にコントローラーの「 updateメソッド 」を完成させましょう。以下のようにしてください。
    • これも、大部分が createメソッド と同じなので、コピペを活用してください。

updateメソッド

  • createメソッドと違い、新しいレコード(インスタンス)を作るのではなく、編集したいレコードのデータを「 Book.find_by(id: params[:id]) 」で取得しています。
  • また、「 redirect_to books_show_path(@book) 」で編集した本のshowページにアクセスしています。
    • ※(@book)の所は、本来 id番号を指定するところですが、@bookだけで、@bookのid情報を取り出してくれます。
    • つまりは省略した書き方で、もし省略せずに書くと(@book.id)になります。
  • では、実際に編集できるか確かめてみましょう。
  • editページを表示するには「 ~/books/edit/id番号 」となります。
  • おそらく、今は最低4つの本が登録されていると思うので、id番号として、1から4のどれかを指定し、何か変更して試してみましょう。

updateメソッド

ここでは、id番号 1 の本のタイトルを編集しています

ちゃんと編集されていればOK

  • ちなみに、ルート設定や、ルートヘルパーの設定を確認する方法を紹介しておきます。
  • 色々あるのですが、一番簡単で見やすいのが「ルーティングエラー」の画面です。なので、わざとエラーを出して確認するのもありです。

ルートの確認方法

ルートヘルパー

HTTPメソッド

URL(Path:パスとも言います)

対応するコントローラー#メソッド

何も書いてない所は

ルートヘルパーが未設定のルート

  • 以上で、CRUDの内、CRUまでが終わりました。後は「D(delete)」だけです。
  • これは専用のページはいらないので、editページに「削除ボタン」を用意すれば良さそうです。
  • delete に対応するコントローラーのメソッドは destroyメソッド でしたね。これを作っていきます。
    • app/controllers/book_controller.rb 」の destroyメソッド を以下のようにしてください。

destroyメソッド

  • 今までのメソッドに比べて、非常にシンプルですね。
  • 最初に、削除したいbookのレコードを持ってきて、それを「 @book.destroy 」で削除しています。
    • 削除に関してはこれだけです。
  • その後、indexページを開いています。
  • 後は、このdestroyメソッドを実行すれば良いだけです。次へ。
  • この destroyメソッド を実行する方法も、基本的には今までと同じで「どこかのURLから、コントローラーのメソッドへのルートを作って、そのルートにアクセスすることで、メソッドを実行する」ということです。
  • ただ、今回は専用のページはありませんので、editファイル(app/views/books/edit.html.erb)に以下のコードを追加してください。

場所は、ファイルの一番下

※必ず<% end %>よりも下に作る事。

<% end %>よりも上になると、フォームの中に入ってしまうため、編集しようとしても、削除になってしまう、ヤバイバグになります。

拡大版

destroyメソッド

  • 説明です。

destroyメソッド

  • button_toは、HTMLのbuttonタグを作るヘルパーメソッドです。
  • これに、URL(パス)として「 book_destroy_path(@book) 」と、HTTPメソッドとして「 delete 」を設定しています。
  • まだこのルートや、ルートヘルパーはないので、それを作れば完成です。
  • 次へ。
  • 以下のように追加してください。

destroyメソッド

  • これでルート設定と、ルートヘルパーが設定できました。
  • 実際に試してみましょう。
    • ※削除すると戻せないので、消えても良い本の編集ページを開き、削除してください。
  • 以下のように赤線部分を追加してください。

destroyメソッド

indexページを見ると、

ちゃんと消えてればOK

お疲れ様でした

  • これで、CRUDの機能すべてが追加できました。
  • 次はもう少し操作しやすいサイトを目指して、「ルートの見直し」や「サイト内リンク」を作っていきたいと思います。
  • 続きは次回のスライドで。