【復習】Ruby on Rails入門 ~ミニブログを作りながら学ぶWebアプリケーション制作 第3回~
無料動画のオンライン学習サイトのスクーで鳥井 雪(@yotii23)先生が教えてくださる
RoR入門第3回を復習します。
Ruby on Rails入門 ~ミニブログを作りながら学ぶWebアプリケーション制作 第3回~ 鳥井 雪 先生 - 無料動画学習|schoo(スクー)
ゴール
- Modelの役割、拡張のしかたを身につける
- 1:多の「リレーション」の考え方を理解する
バリデーション:入力値に制約をつけてみよう
バリデーションとは(Railsとしての)
Railsがリクエストを受けて、コントローラからモデルに渡された値が、
保存(処理?)する条件にふさわしいか検証するModelの機能。
例えば)電話番号がすべて数字であるか?郵便番号の桁数があっているか?
やってみること
- 「本文(body)」を必須項目にする(ないとエラー)
- 「名前(name)」に文字数制限をつける(15文字以内)
「本文(body)」を必須項目にする
entry.rb
にバリデーションの処理を追加する。
#修正前 class Entry < ActiveRecord::Base end #修正後 class Entry < ActiveRecord::Base validates :body, presence: true end
詳細
http://railsguides.jp/active_record_validations.html#presence
「名前(name)」に文字数制限をつける
#修正前 class Entry < ActiveRecord::Base validates :body, presence: true end #修正後 class Entry < ActiveRecord::Base validates :body, presence: true validates :name, length: { maximum: 15 } end
詳細
http://railsguides.jp/active_record_validations.html#length
他にも様々なバリデーションの設定が使えるので、実装しながら調べながら覚えるしかないですね。
http://railsguides.jp/active_record_validations.html
コメント機能を追加してみよう
作りたいものを考える
- 投稿詳細画面(Showを押下し、遷移する画面)
- もともとの投稿表示の下に投稿に対する複数のコメントのリスト
- 新規コメントフォーム
データの名前と種類、関係性を考える
コメントというモデルはcommentという名前とします。
名前(投稿者名)はnameという名前で短い文字列、本文はbodyという名前で長いテキストとします。
短い文字列の形式はstring、長いテキストはtextという形式です。
Model同士の関係性を実現する
データの構造
entriesテーブル
id | name | body |
---|---|---|
1 | hoge | 本文1 |
2 | foo | 本文2 |
3 | bar | 本文3 |
commentsテーブル
id | name | body | entry_id |
---|---|---|---|
1 | hoge | 本文1に対するコメント1 | 1 |
2 | foo | 本文1に対するコメント2 | 1 |
3 | bar | 本文2に対するコメント3 | 2 |
※関係性を表すデータは、Model名_idというカラムに相手のidを保存する。
commentモデルを生成する
$ rails generate scaffold comment name:string body:text entry_id:integer
$ rake db:migrate
Model同士の関係性をModelに書く
Entryモデル entry.rb
class Entry < ActiveRecord::Base has_many :comments (中略) end
Commentモデル comment.rb
class Comment < ActiveRecord::Base belongs_to :entry end
「今回時間が無いので言うとおりにやってください!」
今回はモデルの授業なのでコントローラやビューに関する実装はさくさく進みました。
コントローラ:Entry entries_controller.rb
に追加。
# 修正前 def show end # 修正後 def show @comment = @entry.comments.build end
entryに属するcommentを用意するメソッドを呼び出している。
この時点ではまだDBに保存されていない。
ビュー:entriesの詳細(show) /entries/show.html.erb
に追加。
<h3>コメント</h3> <% @entry.comments.each do |comment| %> <div> <strong><%= comment.name %></strong> <br /> <p><%= comment.body %></p> <% if comment.persisted? %> <p><%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: '削除してもよろしいですか?' } %></p> <% end %> </div> <% end %> <%= render 'comments/form' %>
<% @entry.comments.each do |comment| %>
でentryに属するcommentを1つずつ取得して、
コメント毎の<div>
ブロックを組み立ててます。
<%= render 'comments/form' %>
はコメント投稿用のフォームをパーシャルで組み込んでるんですね。
<% if comment.persisted? %>
のpersisted?
は保存済みかどうかチェックするメソッドなので、
対象のコメントデータがDBに保存されていればコメントを削除する為のリンクを表示します。
ビュー:commentsのフォーム用パーシャル /comments/_form.html.erb
を変更
変更前 <div class="field"> <%= f.label :entry_id %><br> <%= f.number_field :entry_id %> </div> 変更後 <%= f.hidden_field :entry_id %>
一般的にコメントを投稿するときにどのエントリーに属しているかを投稿者が入力することがないので、
ここでは関連づけの entry_id をhidden(隠し)項目に変更しています。
投稿者が関連づけを変更できてしまうとリレーションがめちゃめちゃになります。
コントローラ:Entry comments_controller.rb
を修正。
# POST /comments # POST /comments.json def create @comment = Comment.new(comment_params) respond_to do |format| if @comment.save # 修正前 format.html { redirect_to @comment, notice: 'Comment was successfully created.' } # 修正後 format.html { redirect_to @comment.entry, notice: 'Comment was successfully created.' }
投稿完了後のリダイレクト先を @comment.entry
でコメントが属しているエントリを取得し、設定している。
※このままだと削除したときにcomment一覧にリダイレクトしてしまうので、destroy
も変更すると
完璧だと思います。
# DELETE /comments/1 # DELETE /comments/1.json def destroy @comment.destroy respond_to do |format| # 変更前 format.html { redirect_to comments_url, notice: 'Comment was successfully destroyed.' } # 変更後 format.html { redirect_to @comment.entry, notice: 'Comment was successfully destroyed.' }
リレーション:has_many, belongs_to について
直訳すると
A has many B : Aは、多くのBを所有する。
Entry has_many comments(EntryはたくさんのCommentsを持っている)
A belongs to B : Aは、Bに属する。
Commentは(ひとつの)Entryに属している。
Comment belongs_to entry(Commentは(ひとつの)Entryに属している。)
has_many <-> belongs_to は対になって1:多の関係性を表す。
宿題
- Commentモデルにバリデーションを追加してみよう
- 名前に15文字制限
- 本文に必須項目制限、140文字制限
これまで宿題はすっぽかしてきたので、しっかりやります。
# 変更前 class Comment < ActiveRecord::Base belongs_to :entry end # 変更後 class Comment < ActiveRecord::Base belongs_to :entry validates :name, length: { maximum: 15 } validates :body, presence: true validates :body, length: { maximum: 140 } end
この実装だけだと、バリデーションエラーになったら + 投稿する + コメントの詳細画面に飛ぶ + エラー詳細が表示される
な流れでいちいち画面遷移するの気持ち悪いからコメント入力しているエントリの詳細画面に
パーシャルで埋め込んだコメントのフォーム部分でエラー詳細を出したいんだけど、、、
コントローラを修正するんだろうなと当たりはついているけど、どう直せば良いか
わからない、、、0(:3 )~ =͟͟͞͞(’、3)_ヽ)_
おまけ:Railsのモデルを可視化する。
Graphvizパッケージをインストールする
sudo yum install graphviz
Gemfile
に rails-erd を追加する。
gem 'rails-erd'
rake erd
を実行する。
$ bundle exec rake erd
実行するとカレントディレクトにpdfファイルができます。
文字化けは気にしないでください。
今回のcommentモデル作成時点
モデルに関連性(has_many, belongs_to)追加時
ちゃんと関連性がついたのがわかります。便利ですね。
オススメ書籍
紹介されてました電車本です。
RailsによるアジャイルWebアプリケーション開発 第4版
- 作者: Sam Ruby,Dave Thomas,David Heinemeier Hansson,前田修吾
- 出版社/メーカー: オーム社
- 発売日: 2011/12/01
- メディア: 単行本(ソフトカバー)
- 購入: 12人 クリック: 206回
- この商品を含むブログ (40件) を見る
ただ、Rails3.2対応と古いですし、常にRailsは変化していくので
先生もおっしゃられていましたが Ruby on Rails チュートリアル で
学んだ方がいいと思います。