Rails-tutorial自分用まとめ(2章 主に演習)

1から続きます

2章:Toyアプリを作ろう!

cd ~/environment
rails _5.1.6_ new toy_app
cd toy_app/

Gemfileを編集していく

source 'https://rubygems.org'

gem 'rails', '5.1.6'
gem 'puma', '3.9.1'
gem 'sass-rails', '5.0.6'
gem 'uglifier', '3.2.0'
gem 'coffee-rails', '4.2.2'
gem 'jquery-rails', '4.3.1'
gem 'turbolinks', '5.0.1'
gem 'jbuilder', '2.7.0'

group :development, :test do
  gem 'sqlite3', '1.3.13'
  gem 'byebug', '9.0.6', platform: :mri
end

group :development do
  gem 'web-console', '3.5.1'
  gem 'listen', '3.1.5'
  gem 'spring', '2.0.2'
  gem 'spring-watcher-listen', '2.0.1'
end

group :production do
  gem 'pg', '0.20.0'
end

Gemのインストールをする↓以下をコマンド

bundle update
bundle install --without production
git init
git add -A
git commit -m "Initialize repository"
git remote add origin git@bitbucket.org:<username>/toy_app.git
git push -u origin --all

2.2 Usersリソース

Railsのscaffoldは、rails generateスクリプトにscaffoldコマンドを渡すことで生成されます。

rails generate scaffold User name:string email:string
rails db:migrate

2.2.2 MVCの挙動

1:ブラウザから「/users」というURLのリクエストをRailsサーバーに送信する。

2:/users」リクエストは、Railsのルーティング機構 (ルーター) によってUsersコントローラ内のindexアクションに割り当てられる。

3:indexアクションが実行され、そこからUserモデルに、「すべてのユーザーを取り出せ」(User.all)と問い合わせる。

4:Userモデルは問い合わせを受け、すべてのユーザーをデータベースから取り出す。

5:データベースから取り出したユーザーの一覧をUserモデルからコントローラに返す。

6:Usersコントローラは、ユーザーの一覧を@users変数 (@はRubyのインスタンス変数を表す) に保存し、indexビューに渡す。

7:indexビューが起動し、ERB (Embedded RuBy: ビューのHTMLに埋め込まれているRubyコード) を実行して HTMLを生成 (レンダリング) する。

8:コントローラは、ビューで生成されたHTMLを受け取り、ブラウザに返す。

Railsルートで使うUsersリソース用のルール
config/routes.rbで以下のような記述をする

Rails.application.routes.draw do
 resources :users
 root 'application#hello'
end
ルートからusersへのルーティングを追加する 
config/routes.rb

Rails.application.routes.draw do
 resources :users
 root 'users#index'
end

GET /users index              すべてのユーザーを一覧するページ
GET /users/1 show            id=1のユーザーを表示するページ
GET /users/new new        新規ユーザーを作成するページ
POST /users create           ユーザーを作成するアクション
GET /users/1/edit edit       id=1のユーザーを編集するページ
PATCH /users/1 update    id=1のユーザーを更新するアクション
DELETE /users/1 destroy  id=1のユーザーを削除するアクション

Toyアプリケーションの簡潔なユーザーindexアクション
app/controllers/users_controller.rb

 app/controllers/users_controller.rb
class UsersController < ApplicationController
.
.
.
  def index
   @users = User.all
  end
.
.
end

indexアクションに対応しているビュー

app/views/users/index.html.erb

<h1>Listing users</h1>
 <table>
  <thead>
   <tr>
    <th>Name</th>
    <th>Email</th>
    <th colspan="3"></th>
   </tr>
  </thead>
   <% @users.each do |user| %>
    <tr>
     <td><%= user.name %></td>
     <td><%= user.email %></td>
     <td><%= link_to 'Show', user %></td>
     <td><%= link_to 'Edit', edit_user_path(user) %></td>
     <td><%= link_to 'Destroy', user, method: :delete,
              data: { confirm: 'Are you sure?' } %></td>
     </tr>
   <% end %>
  </table><br>
<%= link_to 'New User', new_user_path %>

演習

1:2.2.2を参考にし/users/1/editというURLにアクセスしたときの
振る舞いについて図を書いてみてください。

2.2.2の図で脳内シミュレーションする。

1:ブラウザから「/users1/edit」というURLのリクエストをRailsサーバーに送信する。

2:/users1/edit」リクエストは、Railsのルーティング機構 (ルーター) によってUsersコントローラ内のeditアクションに割り当てられる。

3:indexアクションが実行され、そこからUserモデルに、選択したものを取り出せ@user = User.find(params[:id])と問い合わせる。

4:Userモデルは問い合わせを受け、すべてのユーザーをデータベースから取り出す。

5:データベースから取り出した編集したいものをUserモデルからコントローラに返す。

6:Usersコントローラは、編集したいものを@user変数 (@はRubyのインスタンス変数を表す) に保存し、editビューに渡す。

7:editビューが起動し、ERB (Embedded RuBy: ビューのHTMLに埋め込まれているRubyコード) を実行してHTMLを生成 (レンダリング) する。

8:コントローラは、ビューで生成されたHTMLを受け取り、ブラウザに返す。 Railsルートで使うUsersリソース用のルール

2:図示した振る舞いを見ながら、Scaffoldで生成されたコードの中で
データベースからユーザー情報を取得しているコードを探してみてください。

users_controller.rbの

class UsersController < ApplicationController
(中略)
private

  def set_user
    @user = User.find(params[:id])
  end
end

3:ユーザーの情報を編集するページのファイル名は何でしょうか?

edit.html.erb

2.3.1マイクロポスト(ツイート)DB作成とmigrate

rails generate scaffold Micropost content:text user_id:integer

rails db:migrate
config/routes.rb
  Rails.application.routes.draw do
    resources :microposts
    resources :users
  root 'users#index'
end
#1人のユーザーに複数のマイクロポストがある。
app/models/user.rb

class User < ApplicationRecord
  has_many :microposts
end

演習2.3.1.1

CSSを知っている読者へ: 新しいユーザーを作成し、ブラウザのHTMLインスペクター機能を使って「Micropost was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?

表示が消える

演習2.3.1.2

マイクロポストの作成画面で、ContentもUserも空にして作成しようとするどうなるでしょうか?

エラーなく、登録成功してしまう

“User was successfully created.”

演習2.3.1.3

141文字以上の文字列をContentに入力した状態で、マイクロポストを作成しようとするとどうなるでしょうか? (ヒント: WikipediaのRubyの記事にある1段落目がちょうど150文字程度ですが、どうなりますか?)

エラーなく、登録成功してしまう
“User was successfully created.”

演習2.3.1.4

上記の演習で作成したマイクロポストを削除してみましょう。

“Micropost was successfully destroyed.”

2.3.2 マイクロポストをマイクロにする

マイクロポストの最大文字数を140文字に制限する。

app/models/micropost.rb
  class Micropost < ApplicationRecord
    validates :content, length: { maximum: 140 }
  end

演習2.3.2.1

先ほど2.3.1.1の演習でやったように、もう一度Contentに141文字以上を入力してみましょう。どのように振る舞いが変わったでしょうか?

エラーが表示される

演習2.3.2.2

ブラウザのHTMLインスペクター機能を使って、表示されたエラーメッセージを調べてみてください。
‘error_explanation’というidが追加されている

2.3.3 ユーザーはたくさんマイクロポストを持っている

1人のユーザーに複数のマイクロポストがある。
app/models/user.rb

class User < ApplicationRecord
 has_many :microposts
end
1つのマイクロポストは1人のユーザーにのみ属する。 
app/models/micropost.rb

class Micropost < ApplicationRecord
  belongs_to :user
  validates :content, length: { maximum: 140 }
end

演習2.3.3.1

ユーザーのshowページを編集し、ユーザーの最初のマイクロポストを表示してみましょう。同ファイル内の他のコードから文法を推測してみてください。うまく表示できたかどうか、/users/1 にアクセスして確認してみましょう。

“<%= @user.microposts.first.content %>”を追加

users_show.html.erb

(前略)
<p>
<strong>Content:</strong>
<%= @user.microposts.first.content %>
</p>
(後略)

firstメソッドによって最初の配列を表示している。lastは最後から取れるよ!

演習2.3.3.2

リスト 2.16は、マイクロポストのContentが存在しているかどうかを検証するバリデーションです。マイクロポストが空でないことを検証できているかどうか、実際に試してみましょう (図 2.16のようになっていると成功です)。

マイクロポストのコンテンツが存在しているかどうかの確認

app/models/micropost.rb
class Micropost < ApplicationRecord
  belongs_to :user
  validates :content, length: { maximum: 140 },
  presence: true
end

答え:実際に試して検証する(フォームに何も書かないで投稿する)

演習2.3.3.3

リスト 2.17のFILL_INとなっている箇所を書き換えて、Userモデルのnameとemailが存在していることを検証してみてください

app/models/user.rb

class User < ApplicationRecord
  has_many :microposts
  validates :name, presence: true
  validates :email, presence: true
end

答え:実際に試して検証する

演習2.3.4.1

Applicationコントローラのファイルを開き、ApplicationControllerがActionController::Baseを継承している部分のコードを探してみてください。

答え:class ApplicationController < ActionController::Base

application_controller.rb

class ApplicationController < ActionController::Base
(後略)

演習2.3.4.2

<問題> ApplicationRecordがActiveRecord::Baseを継承しているコードはどこにあるでしょうか? 先ほどの演習を参考に、探してみてください。ヒント: コントローラと本質的には同じ仕組みなので、app/modelsディレクトリ内にあるファイルを調べてみると?)

答え:app/models/application_record.rbに以下のような記述があるのを見つける

class ApplicationRecord < ActiveRecord::Base
(後略)

演習2.3.5.

1:本番環境で2〜3人のユーザーを作成してみましょう。

本番環境のフォームで実際に作成する。

2:本番環境で最初のユーザーのマイクロポストを作ってみましょう

本番環境で最初のユーザーのマイクロポストを作る

3:マイクロポストのContentに141文字以上を入力した状態で、マイクロポストを作成してみましょう。バリデーションが本番環境でもうまく動くかどうか、確認してみてください。

マイクロポストのContentに141文字以上を入力した状態で、マイクロポストを作成する。

 

まとめ:Scaffoldの良い点は?

Rails全体を概観できた。
MVCモデルについての仕組みがわかった。
RESTアーキテクチャに初めて触れた。
データモデルの作成を初めて行った。
データベースを背後に持つWebアプリケーションを本番環境で動かした。

Scaffodの弱点は?

レイアウトもスタイルも設定されていない。
“Home” や “About” のような定番の静的なページがない。
ユーザーがパスワードを設定できない、ユーザーが画像を置けない。
ログインの仕組みがない。
セキュリティのための仕組みがまったくない。
ユーザーとマイクロポストの自動関連付けが行われていない。
Twitterのような「フォロワー (following)機能」や
「フォロー中 (followed)機能」がない。
マイクロポストをフィードできない。
まともなテストがない 理解が困難。

2章のまとめ

  1. Scaffold機能でコードを自動生成すると、Webのあらゆる部分からモデルデータにアクセスしてやりとりできるようになる

  2. Scaffoldは何よりも手っ取り早いのがとりえだが、これを元にRailsを理解するには向いていない

  3. RailsではWebアプリケーションの構成にMVC (Model-View-Controller) というモデルを採用している

  4. Railsが解釈するRESTには、標準的なURLセットと、データモデルとやりとりするためのコントローラアクションが含まれている

  5. Railsではデータのバリデーション (validation) がサポートされており、データモデルの属性の値に制限をかけることができる

  6. Railsには、さまざまなデータモデル同士を関連付けを定義するための組み込み関数が多数用意されている

  7. Railsコンソールを使うと、コマンドラインからRailsアプリケーションとやりとりすることができる

その3に続く

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です