概要
第1章に続いて第2章です。
scaffoldを用いてToyアプリケーションを作ります。
それでは頑張って行きましょう!
アプリケーション計画
ユーザがマイクロポスト(ツイッターのツイート)をするというアプリケーションです。
モデル
ユーザモデルはidとnameとemailを持つシンプルな構成です。
マイクロポストはidとcontentとuser_idを持ちます。
ユーザとマイクロポストの関係は一対多になります。
Usersリソース
上記で設計したモデルを実際に作って行きます。
概要でも説明した通り、今回はscaffoldを使って実装します。
rails generate scaffold User name:string email:string
Userというモデルをnameがstring型、emailもstring型で作成するっていうことかな?
これを実行した後に、dbにマイグレートするために
rails db:migrate
を実行します。
作成されたユーザページを見てよう!
| Url | アクション | 用途 |
|---|---|---|
| /users | index | ユーザの一覧を表示する |
| /users/1 | show | id=1のユーザを表示 |
| /users/new | new | 新規ユーザ作成 |
| /users/1/edit | edit | id=1のユーザを編集する |
| newで作って色々やって見てください。 |
MVCの挙動
config/routes.rbを見てみましょう。
Rails.application.routes.draw do
resources :users
end
resources :usersの一行が追加されていることがわかります。この記法の説明は4.3.3で行います。
今回はrootを/users/に変更します。
Rails.application.routes.draw do
resources :users
root 'users#index'
end
次にapp/controllers/users_controller.rbを見てみましょう。
index,show,new,editcreate,update,destoryのメソッドが追加されています。
RESTに基づいてつくられているので詳細は省きます。
class UsersController < ApplicationController
...
def index
@users = User.all
end
...
end
User.allを呼び出すことでdb上のユーザすべてを取り出しています。
これはActive RecordというRubyのライブラリによるものです。
また、@usersのように@をつけた変数をインスタンス変数と呼び、viewでもその変数を使えるようにします。
<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 %>
今はコードの詳細についてわからなくても構いません。
viewでcontollerで作成したusersを用いて、user一覧のhtmlを作成していることがわかればおkです。
Usersリソースの欠点
- データの検証が行われていない。 ユーザのメールアドレスが空欄であったり、メールアドレスの書式をしていなくても作成、変更されてしまいます。
- ユーザー認証が行われていない。 ログイン、ログアウト機能がないので、誰でもユーザ情報を変更することができます。
- テストが書かれていない。
- レイアウトやスタイルが整っていない。
Micropostsリソース
Usersと同様に下記を実行
rails generate scaffold Micropost content:text user_id:integer
rails db:migrate
あとはUserと同様に同じ様なページが作成されていることを確認してください。
マイクロポストをマイクロにする
マイクロポストに文字数制限をつけてみましょう。
今回は140文字制限で実装します。
class Micropost < ApplicationRecord
validates :content, length: { maximum: 140 }
end
これで/micropost/newのContentに140文字以上入力した時に、エラーが表示されるようになりました。
ユーザーはたくさんマイクロポストを持っている
ユーザとマイクロポストのリレイーションを作成します。
class User < ApplicationRecord
has_many :microposts
end
class Micropost < ApplicationRecord
belongs_to :user
validates :content, length: { maximum: 140 }
end
それでは、Railsのconsoleを使って作成したリレーションの確認を行います。
rails consoleでconsoleを立ち上げることができます。
$ rails console
>> first_user = User.first
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.org",
created_at: "2016-05-15 02:01:31", updated_at: "2016-05-15 02:01:31">
>> first_user.microposts
=> [#<Micropost id: 1, content: "First micropost!", user_id: 1,
created_at: "2011-11-03 02:37:37", updated_at: "2011-11-03 02:37:37">,
"2016-05-15 02:37:37", updated_at: "2016-05-15 02:37:37">, #<Micropost id: 2,
content: "Second micropost", user_id: 1, created_at: "2016-05-15 02:38:54",
updated_at: "2016-05-15 02:38:54">]
>> micropost = first_user.microposts.first # Micropost.first would also work.
=> #<Micropost id: 1, content: "First micropost!", user_id: 1, created_at:
"2016-05-15 02:37:37", updated_at: "2016-05-15 02:37:37">
>> micropost.user
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.org",
created_at: "2016-05-15 02:01:31", updated_at: "2016-05-15 02:01:31">
>> exit
継承の階層
model
userもmicropostもApplicationRecordというクラスを継承しています。(class Micropost < ApplicationRecord)
また、ApplicationRecordはActiveRecord::Basetというクラスを継承しています。
このActiveRecord::Baseのクラスを継承することによって、DBからデータをって来たり書き込んだりすることができます(ORM)。
controller
controllerはApplicationControllerというクラスを継承しています。
ApplicationControllerはActionController::Baseというクラスを継承しているため、HTTP requestのフィルタリング、viewをhtmlで出力などの機能を持つことができています。
また、ApplicationControllerにログインようのメソッド等を定義するとすべてのコントローラでも使用することができるようになります。
まとめ
だいぶ端折りました。
他のMVCのアプリケーション触ったことがあるので、RESTとかMVCとかそういう説明は省いています。