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章のまとめ
-
Scaffold機能でコードを自動生成すると、Webのあらゆる部分からモデルデータにアクセスしてやりとりできるようになる
-
Scaffoldは何よりも手っ取り早いのがとりえだが、これを元にRailsを理解するには向いていない
-
RailsではWebアプリケーションの構成にMVC (Model-View-Controller) というモデルを採用している
-
Railsが解釈するRESTには、標準的なURLセットと、データモデルとやりとりするためのコントローラアクションが含まれている
-
Railsではデータのバリデーション (validation) がサポートされており、データモデルの属性の値に制限をかけることができる
-
Railsには、さまざまなデータモデル同士を関連付けを定義するための組み込み関数が多数用意されている
-
Railsコンソールを使うと、コマンドラインからRailsアプリケーションとやりとりすることができる