おれろぐ #z_a_ki3

(・∀・) オイ!

【復習】Ruby on Rails入門 ~ミニブログを作りながら学ぶWebアプリケーション制作 第2回~

無料動画のオンライン学習サイトのスクーで鳥井 雪(@yotii23)先生が教えてくださる
RoR入門第2回を復習します。

Ruby on Rails入門 ~ミニブログを作りながら学ぶWebアプリケーション制作 第2回~ 鳥井 雪 先生 - 無料動画学習|schoo(スクー)

ゴール

  • リクエストからレスポンスまでの、Rails内部での処理の流れを理解する。
  • View(表示)のカスタマイズができるようになる。

リクエストからレスポンスまでのRailsの処理の流れ

1.routes.rbで処理を分岐する。

URL+HTTPメソッドでどの処理を実行するかは ./config/routes.rb で定義する。

前回scaffoldで生成したentriesは以下のように定義されている。

Rails.application.routes.draw do
  resources :entries

リクエスト(URL+HTTPメソッド)を受けたRailsroutes.rb でどの処理を
呼び出すかを、決定し、その"処理"を実行してレスポンスを返す。

※同じURLでもHTTPメソッドが違っていれば異なる処理を実行することもある。

処理を構成する三要素:MVC

"処理"は3つの要素に分かれていて、それをMVCと呼ぶ。

  • M:Model(モデル)
  • V:View(ビュー)
  • C:Controller(コントローラ)

2.MVCでレスポンスをつくる

  • routes.rbからどのControllerのどの処理を実行するか決定する。*
  • Controllerを呼び出す。*
  • ControllerがModelを呼び出す
  • Modelがデータを用意し、Controllerに返す
  • ControllerがデータをViewに渡す
  • Viewがレスポンスを用意する

※処理の流れの理解は大事

MVCの基本

RailsMVCディレクトリ構造

./my_app/app/ の下にmodels,controllers,viewsが配置されている。

 my_app
    ├── app
    │   ├── assets
    │   ├── controllers *
    │   ├── helpers
    │   ├── mailers
    │   ├── models      *
    │   └── views       *

Controllerの主な役割

  • routes.rb から一番最初に呼ばれる
  • Modelを呼び出してデータを揃える(揃えさせる)
  • 揃えた(Modelから受け取った)データをViewに渡す

前回、scaffoldで生成したentryのコントローラはentries_controller.rb

class EntriesController < ApplicationController
  before_action :set_entry, only: [:show, :edit, :update, :destroy]

  # GET /entries
  # GET /entries.json
  def index
    @entries = Entry.all
  end
  ~略~
  • URLで /entries を指定してアクセスした場合、routes.rbdef index を呼び出す。
  • #で始まるコメントに対応するURLが記載されている。(コマンドで作成した場合)
  • Entry.all は一覧画面用にモデルから全てのデータを取得する処理。
  • @entriesはインスタンス変数で、インスタンス変数の値はViewに渡すことができる。
  • def から end までの間にViewを呼び出す処理がないが、railsが対応するViewを呼び出す。

HTTPメソッドとControllerの対応付けは以下が参考になります。

Rails のルーティング — Rails ガイド

Modelの主な役割

  • データのやり取りを担当する
  • ActiveRecode::Baseに基本の機能が用意されている
  • クラスの名前からテーブル名を推測する

前回、scaffoldで生成したentryのモデルはentry.rb

class Entry < ActiveRecord::Base
end
  • クラスをみると空だが、Railsが用意している ActiveRecode::Base を継承している。
  • モデルに対応するテーブル名は命名規則(テーブル名;モデル名の複数形)から推論している。
  • ここにはモデル固有の処理(文字数制限をしたり他のデータとの関係性などをつけたり)を書いていく。

Viewの主な役割

  • 渡されたデータに基づいてHTML(など)を組み立てる
  • 「画面」ごとに対応する1ファイルがある

前回、scaffoldで生成したentryのビューは/views/entries配下の複数ファイル

サンプルは index.html.erb

<p id="notice"><%= notice %></p>

<h1>Listing Entries</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Body</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @entries.each do |entry| %>
      <tr>
        <td><%= entry.name %></td>
        <td><%= entry.body %></td>
        <td><%= link_to 'Show', entry %></td>
        <td><%= link_to 'Edit', edit_entry_path(entry) %></td>
        <td><%= link_to 'Destroy', entry, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Entry', new_entry_path %>
  • <% @entries.each do |entry| %>@entries はControllerに登場したインスタンス変数。
  • <% code %> は中に記載したRubyコードを実行する。(実行のみ)
  • <%= code %> は中に記載したRubyコードを実行し、その実行結果を埋め込む。
  • <td><%= entry.name %></td>entry.name を実行し、その実行結果がもし z_a_ki3 であれば
    <td>z_a_ki3</td> となる。

ちなみに link_to は良い感じにリンクを生成してくれるヘルパーと呼ばれるものなんですが、詳細は別途・・・

MVCのメリット

MVCと3つに役割を分担することで、開発しやすくメンテナンスしやすいアプリケーションになる。

MVCRailsでもJavaASP.NETなどでも当たり前になっているデザインパターンなので、
MVC何それおいしいの?状態にならないように基本的なことは押さえておいた方が良いと思います。

ただ、MVCは"こう実装するのがジャスティス!"なものが無いのでここは経験を積みましょう。

やはりお前らのMVCは間違っている

ぼくがかんがえたさいきょうのMvc

HTTPメソッドの種類

HTTPメソッド 処理内容
GET データを取得する
POST 作成
PUT(PATCH) 更新
DELETE 削除

このなかで更新はPUTとPATCHで多重定義されています。

授業の中では仕様が揺れていると言うことでしたが、Rails4で更新はPATCHとされたようです。
なので、新しいRailsを使うのであれば"更新はPATCH"と考えても良いかもしれません。

Rails アップグレードガイド — Rails ガイド

また、PUTとPATCHの違いについては以下のページに詳細があります。

次期RailsがPATCHメソッドを採用 - ぶろぐ。@はてな

CRUDとHTTPメソッドの対応

CRUD HTTPメソッド
CREATE POST
READ GET
UPDATE PUT(PATCH)
DELETE DELETE

Viewをカスタマイズしよう!

アンケート:HTMLとCSSの関係が説明できますか?

  • HTMLは文章を構造化する為の言語
  • CSSはHTMLなどの構造に対する修飾の定義

Viewの役割

  • レスポンスの最終的な形を整形する
  • HTML+Rubyのプログラム+RailsでHTMLを便利に書くヘルパー
  • <% %>で囲まれた部分はRubyのプログラムを書ける
  • <%= %>で囲まれた部分はRubyのプログラムを使って書き出される内容がかける

app/views/entries.index.html.erbを編集する

まずは表示を日本語に変更します。

編集前

編集前
<h1>Listing Entries</h1>

編集後
<h1>投稿一覧</h1>

一覧画面以外のタイトルは当然、影響を受けていません。

app/views/layouts/application.index.html.erbを編集する

編集前
<%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>

編集後
<link rel="stylesheet" href="//railsgirls.com/assets/bootstrap.css" />
<link rel="stylesheet" href="//railsgirls.com/assets/bootstrap-theme.css" />
<%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
変更前
<%= yield %>

変更後
<div class="container">
    <%= yield %>
</div>

※これはRails Girlsのサイトで配備されてるcssファイルを拝借してる感じなので、実際の自分のアプリを使う場合は、
自分でダウンロードしたファイルを使うか、Bootstrap CDNを使わないとダメですね。

Getting started · Bootstrap

編集前
<link rel="stylesheet" href="//railsgirls.com/assets/bootstrap.css" />
<link rel="stylesheet" href="//railsgirls.com/assets/bootstrap-theme.css" />

編集後
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css" />

これで一覧画面、詳細画面、作成画面等を見ると全ての画面で追加したスタイルシートが適用されてます。

ここで登場している <%= yield %> の裏にある処理がとっても気になるんですが、とりあえず、
関連しそうなリンクを張り逃げして、再復習の時にまた追っていきたいと思います。

yield を理解できるまで寝ないスレッド · Issue #336 · yochiyochirb/meetups · GitHub

レイアウトと個別のview

  • headerやfooterなどの共有部分:application.index.html.erb
  • 個別のページの内容:index.html.erb

app/views/entries/_form.html.erbを編集する

変更前
<%= f.label :name %><br>

変更後
<%= f.label :name,"名前" %><br>
変更前
<%= f.label :body %><br>

変更後
<%= f.label :body,"本文" %><br>

今回、修正した f.label は次のような構文になっていて、ラベル配下のコンテンツを追加しています。

f.label(プロパティ名 [, ラベル配下のコンテンツ] [, オプション])

label - リファレンス - Railsドキュメント

個別のviewと共通のview(パーシャル)

/entries/newentries/1/edit の画面を見てみると非常に似た構造になっています。
ここで views/entries 配下の new.html.erb を見てみると、

new.html.erb

<h1>New Entry</h1>

<%= render 'form' %>

<%= link_to 'Back', entries_path %>

<%= render 'form' %><%= link_to 〜 %> しかありません。
次に edit.html.erb を見てみると、

edit.html.erb

<h1>Editing Entry</h1>

<%= render 'form' %>

<%= link_to 'Show', @entry %> |
<%= link_to 'Back', entries_path %>

同じく <%= render 'form' %><%= link_to 〜 %> しかありません。

この中で <%= render 'form' %> が、先ほど編集した _form.html.erb に対応しています。

個別のViewの中で共通している部分をパーシャルという仕組みでまとめる事ができます。
パーシャルのファイル名は""(アンダーバー)からはじめ、renderで指定するときは""を外す。

次回以降の内容

  • Railsが作ってくれた今の機能に、自分のやりたいことを足してゆく
  • 新しい情報を付け加える
  • Railsの構造、モデルの機能追加を理解する

宿題

  • 自分で個別のviewファイルとレイアウトのファイルを書き換えてみて、その変更を見てみましょう
  • 全ページに共通のフッターをつけてみましょう

application.html.erb を修正

変更前
<%= yield %>

変更後
<%= yield %>
<footer>&copy; Copyright 2015, @z_a_ki3.</footer>

単純に足しただけ・・・

  • /entries/ ページの "Name" と "Body" を日本語に書き換えてみましょう。

index.html.erb を修正

変更前
<th>Name</th>
<th>Body</th>

変更後
<th>名前</th>
<th>本文</th>

単純に変えただけ・・・

質疑応答

オススメのサイト

第1章 ゼロからデプロイまで | Rails チュートリアル