******** ビュー ******** ======================== とりあえず動かしてみる ======================== 前回、Studentについては ``scaffold`` でモデル・ビュー・コントローラを作った(:numref:`scaffold`)ので、ウェブサーバとデータベースを接続すれば動くはずである。 .. image:: 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 * ブラウザで http://localhost:3000/ をアクセスすると、ウェルカムページが表示される。 * 次に http://localhost:3000/students/ にアクセスしてみる。 ``students`` と複数形なことに注意。 終了するにはコントロールCを押す。なお、終了するかバックグラウンドにしないと、そのターミナルでは他のコマンドが入力できないので注意。 ============= ERBファイル ============= ビューの役割は、ブラウザで表示するHTMLを生成すること。つまり、プログラムの出力結果がHTMLになるようにするのだが、いちいち ``puts ''`` とか書いていくのはかったるいし読みにくいので、固定的な部分はHTMLをそのまま書き、変化する部分だけRubyで書く。この形式をERBという。 * 参考資料: `テンプレートの中でRubyコードを使う - RubyLife `_ 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とファイルの対応関係については、次回に説明する。 ============ レイアウト ============ ブラウザで 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`` はアセットタグヘルパーと呼ばれている。 * 参考資料: `アセットタグヘルパー - Railsガイド `_ .. note:: アセット(特にJavaScript)の管理方式は変化が激しい。Rails5まではSprockets、Rails6ではWebpack、Rails7ではImportmapが標準になっているが、標準でない方式を使うことも可能である。資料を参照する時は、どの方式を使っているかに注意すること。 ================ スタイルシート ================ CSSを拡張したSCSSで書くことができる。 * 参考資料: `Sass、そしてSassy CSS (SCSS) - Kyo Nagashima `_ ``app/assets/stylesheets/`` の下には、ビューごとに別のファイルができるのだが、デフォルトでは全部のファイルを連結して読み込むので注意。 ====================== その他のアセットタグ ====================== 画像や音声を埋め込むためのメソッドが用意されている。 * 参考資料: `アセットタグヘルパー - Railsガイド `_ .. admonition:: 課題13 :class: exercise ``app/views/layouts/application.html.erb`` を次のように変更せよ。 1. 日本語が化けないように ``head`` 要素の中に ```` を追加せよ。(もし ``UTF-8`` 以外の文字コードで書いている場合はそれに合わせること)。 2. `Railsガイドのアセットタグヘルパーの説明 `_ を読み、 ``image_tag`` を追加して、SFCのロゴ( http://www.sfc.keio.ac.jp/img/logo.png )を各ページの一番下に表示するようにせよ。 提出は ``app/views/layouts/application.html.erb`` ファイル。 :ref:`【解答例】 ` ================ 一覧表示ページ ================ ブラウザで http://localhost:3000/students/ のソースを表示し、エディタで ``app/views/students/index.html.erb`` を表示し、並べてみよ。 * 1行目の ``notice`` は ``flash`` に記憶されているメッセージを表示するためのメソッドである。なぜ変数に記憶しないかというと、リクエスト・レスポンスの処理が終わるごとにCGIプロセスは終了して変数は全部消えてしまうので、次のリクエストの時点でメッセージを表示するためには、データベースに記憶しておかないといけないから。 * 6行目の ``<% @students.each do |student| %>`` は、Rubyの構文的には11行目にある ``<% end %>`` とつながっているので注意。この間に挟まれたERBの処理がブロックになり、繰り返し実行(HTMLを出力)される。 * これを実行する時、 ``@students`` には ``Student`` クラスのインスタンスの配列が入っている(実はコントローラで入れているが、それは次回)。 * 7行目の ``render student`` は ``_student.html.erb`` というファイルを呼び出す。 .. admonition:: 課題14 :class: exercise 1. このビューは前回の ``scaffold`` によって出来た(:numref:`scaffold`)ものだが、その時には学年を指定せず、後で追加した(:numref:`model_modification`)ので、このビューには学年が表示されない。修正して学年も表示するようにせよ。 2. 学部が番号で表示されると人間には分かりにくいので、学部の名前を表示するようにせよ。ヒント:前回、 ``Student`` のインスタンスから ``Faculty`` のインスタンスを得る方法をやった(:numref:`association`)ので、それを使う。 提出は、 ``app/views/students/_student.html.erb`` ファイル。 :ref:`【解答例】 ` ======== リンク ======== ``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を与えたのと同じになる。 ============================ 詳細表示ページと編集ページ ============================ URL http://localhost:3000/students/1 をアクセスすると、 ``Student`` モデルの ``id`` 1番のデータが表示される。対応するERBファイルは、レイアウトが ``app/views/layouts/application.html.erb`` 、その中の ``yield`` で ``app/views/students/show.html.erb`` が呼び出される。 * 9行目の ``button_to`` はHTMLのフォームを生成する。フォームについては後で説明する。 同様にURL http://localhost:3000/students/1/edit は ``app/views/students/edit.html`` に対応している。 ============== 今日のまとめ ============== .. image:: view-summary.png `ここまでのソースコードはこちら `_ `課題14実行後はこちら `_