8. ビュー

8.1. とりあえず動かしてみる

前回、Studentについては scaffold でモデル・ビュー・コントローラを作った(7.1 章)ので、ウェブサーバとデータベースを接続すれば動くはずである。

_images/dynamic-page.png
  • WebサーバはPuma(Railsをインストールすると一緒についてくる)を使用する。

    • 本番のサービスではApacheやNginxをデーモンとして動かし、リバースプロキシを入れたりして重装備になることも多いが、開発している途中は自分だけが使えればよいので、Pumaをお手軽にターミナルから起動して使うのが普通。

    • 最近は本番でもDockerの中でPumaを動かすことが増えているようだ。

  • データベースはSqlite3を使用する。

    • 本番のサービスではPostgresqlやMySQLを使うことが多いが、データ量が少なければSqlite3の方がお手軽。

まず、Pumaを起動する。

% cd /home/school
% rails server -b 0.0.0.0

終了するにはコントロールCを押す。なお、終了するかバックグラウンドにしないと、そのターミナルでは他のコマンドが入力できないので注意。

8.2. ERBファイル

ビューの役割は、ブラウザで表示するHTMLを生成すること。つまり、プログラムの出力結果がHTMLになるようにするのだが、いちいち puts '<html>' とか書いていくのはかったるいし読みにくいので、固定的な部分はHTMLをそのまま書き、変化する部分だけRubyで書く。この形式をERBという。

ERBファイルは、一見HTMLファイルのように見えるが、ところどころ <% %><%= %> というタグがある。この部分はRubyプログラムとして実行される(正確には、 <% %><%= %> で囲まれていない部分がHTMLを出力するプログラムに変換され、全体がRubyプログラムとして実行される)。

  • <% %> : Rubyの式を評価する。式の値は捨てられる。

  • <%= %> : Rubyの式を評価する。式の値はHTMLの中に埋め込まれる。

http://localhost:3000/students/ に対応するERBファイルは、次の二つである。

  • app/views/layouts/application.html.erb :アプリケーションの全ページに共通なレイアウト

  • app/views/students/index.html.erb :このページ特有の部分

URLとファイルの対応関係については、次回に説明する。

8.3. レイアウト

ブラウザで http://localhost:3000/students/ のソースを表示し、エディタで app/views/layouts/application.html.erb を表示し、並べてみよ。

  • 最初の5行は固定的なHTMLなので、そのまま出力されている。

  • ソースの6〜28行目はERBファイルの6〜11行目に対応している。

    • 6行目の csrf_meta_tags はセキュリティ関係の設定(Cross Site Request Forgeries 対策)をしている。

    • 9行目の stylesheet_link_tag 'application' は、 app/assets/stylesheets/ の下にある application.css を参照するようにHTMLの link 要素を生成する。さらに、その中のコメントにしたがって他のCSSファイルも参照される。

    • 10行目の javascript_importmap_tags は、 Importmapを用いて app/javascript の下にあるJSファイルを読み込むようにHTMLの script 要素を生成する。

  • ERBファイルの14行目は yield を実行して、このページ特有のERBファイルを呼び出し、その結果をこの部分に挿入している。

ここで使われている stylesheet_link_tag はアセットタグヘルパーと呼ばれている。

注釈

アセット(特にJavaScript)の管理方式は変化が激しい。Rails5まではSprockets、Rails6ではWebpack、Rails7ではImportmapが標準になっているが、標準でない方式を使うことも可能である。資料を参照する時は、どの方式を使っているかに注意すること。

8.4. スタイルシート

CSSを拡張したSCSSで書くことができる。

app/assets/stylesheets/ の下には、ビューごとに別のファイルができるのだが、デフォルトでは全部のファイルを連結して読み込むので注意。

8.5. その他のアセットタグ

画像や音声を埋め込むためのメソッドが用意されている。

課題13

app/views/layouts/application.html.erb を次のように変更せよ。

  1. 日本語が化けないように head 要素の中に <meta charset="UTF-8"> を追加せよ。(もし UTF-8 以外の文字コードで書いている場合はそれに合わせること)。

  2. Railsガイドのアセットタグヘルパーの説明 を読み、 image_tag を追加して、SFCのロゴ( http://www.sfc.keio.ac.jp/img/logo.png )を各ページの一番下に表示するようにせよ。

提出は app/views/layouts/application.html.erb ファイル。

【解答例】

8.6. 一覧表示ページ

ブラウザで http://localhost:3000/students/ のソースを表示し、エディタで app/views/students/index.html.erb を表示し、並べてみよ。

  • 1行目の noticeflash に記憶されているメッセージを表示するためのメソッドである。なぜ変数に記憶しないかというと、リクエスト・レスポンスの処理が終わるごとにCGIプロセスは終了して変数は全部消えてしまうので、次のリクエストの時点でメッセージを表示するためには、データベースに記憶しておかないといけないから。

  • 6行目の <% @students.each do |student| %> は、Rubyの構文的には11行目にある <% end %> とつながっているので注意。この間に挟まれたERBの処理がブロックになり、繰り返し実行(HTMLを出力)される。

  • これを実行する時、 @students には Student クラスのインスタンスの配列が入っている(実はコントローラで入れているが、それは次回)。

  • 7行目の render student_student.html.erb というファイルを呼び出す。

課題14

  1. このビューは前回の scaffold によって出来た(7.1 章)ものだが、その時には学年を指定せず、後で追加した(7.3 章)ので、このビューには学年が表示されない。修正して学年も表示するようにせよ。

  2. 学部が番号で表示されると人間には分かりにくいので、学部の名前を表示するようにせよ。ヒント:前回、 Student のインスタンスから Faculty のインスタンスを得る方法をやった(7.5 章)ので、それを使う。

提出は、 app/views/students/_student.html.erb ファイル。

【解答例】

8.7. リンク

app/views/students/index.html.erb の9行目と14行目は link_to によってHTMLの a 要素を生成している。引数は、表示文字列、URL、オプション(ハッシュの形で与える)。

URLは文字列で書いてもよいが、URLを生成するメソッドが各モデルごとに用意されるので、それを使う方が後々の保守のためにはよい。例えば、 scaffold で作った Student モデルの場合は次のようになる。

内容

URL

メソッド

モデルのデータの一覧表示

/students

students_path

各データの詳細表示

/students/番号

student_path(インスタンス)

各データの編集

/students/番号/edit

edit_student_path(インスタンス)

  • 9行目のShow this studentボタンでは、URL(またはURLを生成するメソッド)を書くはずのところに student という変数( Student クラスのインスタンスが入っている)が書いてある。本来なら student_path(student) と書くべきところだが、面倒くさいので直接インスタンスを与えると、そのインスタンスの詳細表示ページのURLを与えたのと同じになる。

8.8. 詳細表示ページと編集ページ

URL http://localhost:3000/students/1 をアクセスすると、 Student モデルの id 1番のデータが表示される。対応するERBファイルは、レイアウトが app/views/layouts/application.html.erb 、その中の yieldapp/views/students/show.html.erb が呼び出される。

  • 9行目の button_to はHTMLのフォームを生成する。フォームについては後で説明する。

同様にURL http://localhost:3000/students/1/editapp/views/students/edit.html に対応している。

8.9. 今日のまとめ

_images/view-summary.png

ここまでのソースコードはこちら

課題14実行後はこちら