LoginSignup
7
7

More than 5 years have passed since last update.

ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (24〜30)/全46

Last updated at Posted at 2014-03-13

主な内容 - Blogシステムを作る(続き)

#24 新しい記事を追加しよう (1)
#25 新しい記事を追加しよう (2)
#26 新しい記事を追加しよう (3)
#27 バリデーションを設定しよう
#28 バリデーションエラーを表示しよう
#29 フラッシュメッセージを表示する
#30 メッセージをjQueryで消す

Scaffoldを使わずに、一からブログアプリケーションを作成しよう(実践的)(続き)

  • コントローラーのメソッドと、それに対応するViewを作っていきましょう(続き)
  • Scaffoldでは自動生成してくれたModel、DBの設定、Controller、URL、Controllerのメソッド、Viewを自力で作ります。(続き - new,create)

記事のタイトル一覧を表示するindexメソッド、その記事を表示するshowメソッドは完成したので次はその記事を表示するページが欲しいですね。ということでnewメソッド(新規作成フォーム)を作ります。また、フォームから送信されたデータを処理して新しい記事を作成するcreateメソッドも作成します。

バリデーション(検査)の設定をやってみよう(実践的)

仕様(再確認)

  1. Post(記事を投稿、編集、削除できる機能)
  2. Comment(記事に対してコメントを投稿、削除できる機能)

作成の流れ

  1. blogプロジェクトを作成
  2. Modelを作成
  3. DB
  4. Controllerの作成
  5. URLの作成(ルーティングの設定) ←ここまで終わっています
  6. Controllerのメソッドの作成 ←今はここです
  7. メソッドに対応するViewを作成

6. 7. Controller内のMethod、それに対応するViewを作成(続き)

作成するメソッド

  • index(完了)

app/views/posts/index.html.erb

  • create

    Viewは無し(フォームに入力されたデータを処理するだけのメソッドなので、Viewは必要ありません。)

  • new

    app/views/posts/new.html.erb

  • edit

    app/views/posts/edit.html.erb

  • show(完了)

app/views/posts/show.html.erb

  • update

    Viewは無し(編集画面からの送信を処理するだけのメソッドなので、Viewは必要ありません。)

  • destroy

    Viewは無し(削除リンクをindex.html.erbにつけますが、destroy専用のViewは必要ありません。)

new

まず新規オブジェクトを生成するnewメソッドを作ります。

newメソッドを作成

Postモデルのオブジェクトを生成します。生成したオブジェクトに対してViewのフォームに入力されたデータで操作を加えていくのはcreateの仕事です。

app/controllers/posts_controller.rb
class PostsController < ApplicationController

    #indexメソッド
    def index
        # Postから全てのデータを引っ張りだし、インスタンス変数postsに代入
        @posts = Post.all
    end

    #showメソッド
    def show
        # PostモデルのfindメソッドにparamsでURLから受け取ったIDを引数として与え、
        # そのデータが見つかったらインスタンス変数postに代入
        @post = Post.find(params[:id])
    end

    # newメソッド
    def new
      # 空のPostモデルオブジェクトを生成し、インスタンス変数postsに代入
      @post = Post.new
    end

end

(補足)newの動きを確認するためにrails consoleで実行してみます。

では、Post.newを実行し、Postモデルのオブジェクトを作成し、その結果を確認します。

Terminal
$ rails console
        SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
        This poses a security threat. It is strongly recommended that you
        provide a secret to prevent exploits that may be possible from crafted
        cookies. This will not be supported in future versions of Rack, and
        future versions will even invalidate your existing user cookies.

       Called from: /Users/shiraihiroki/.rbenv/versions/1.9.3-p125/lib/ruby/gems/1.9.1/gems/actionpack-3.2.3/lib/action_dispatch/middleware/session/abstract_store.rb:28:in `initialize'.

Loading development environment (Rails 3.2.3)
irb(main):001:0> p = Post.new
=> #<Post id: nil, title: nil, content: nil, created_at: nil, updated_at: nil>
irb(main):002:0> 
irb(main):002:0> p
=> #<Post id: nil, title: nil, content: nil, created_at: nil, updated_at: nil>

きちんとオブジェクトが生成されていることが確認できました。
もちろん、中身は空っぽです。ここをcreateメソッドでViewから渡されたデータを使って操作していきます。

showメソッドに対応するView(show.html.erb)を作成

生成したPostオブジェクト(@post)に対するフォームを生成します。

Terminal
$ touch app/views/posts/new.html.erb
app/views/posts/new.html.erb
<%# ヘッダー %>
<h1>New Post</h1>

<%# @postに対するフォームを生成 %>
<%= form_for(@post) do |f| %>

  <%# titleに対するテキストフィールド %>
  <div class = "field">
    <%# titleというIDが付いたTitleという文字列ラベルを生成 %>
    <%= f.label :title %>
    <%# titleというIDが付いたTitleというテキストフィールドを生成 %>
    <%= f.text_field :title %>
  </div>

  <%# contentに対するテキストエリア(5行分) %>
  <div class = "field">
    <%# contentというIDが付いたContentという文字列ラベルを生成 %>
    <%= f.label :content %>
    <%# ContentというIDが付いたContentという5行分のテキストエリアを生成 %>
    <%= f.text_area :content, :rows => 5 %>
  </div>

  <%# 送信ボタンを生成 %>
  <div class = "actions">
    <%# contentというIDが付いたContentという文字列ラベルを生成 %>
    <%= f.submit %>
  </div>

<% end %>

<%# HOME(index)へ戻るリンク %>
<%= link_to 'home', posts_path %>

フォームの部分を少し詳しくみてみます。

  • <%= form_for(@post) do |f| %>

    @postにPostオブジェクトが入っていれば変数fに代入してそれに対応するフォームを生成。(今回はモデルにtitleとcontentの2つを設定してあるので、これらが生成されます。)

    フォームを生成してくれるRailsのヘルパーメソッドはform_for、form_tagの2つがありますが、今回は特定のモデルに特化したform_forを使います。form_tagは特定のモデルに特化しない(汎用的な)フォームを生成するメソッドです。(いろいろなモデルで動作する検索フォームなどで使います。)

  • <%= f.label :title %>

    titleというIDが付いたラベルをlabelというヘルパーメソッドを用いて生成して表示。

    これでTitleラベルをクリックするとtitleというIDが付いたテキストフィールドを選択できるようになります。テキストフィールドさえ作成すれば、これは別になくてもかまいません。

  • <%= f.text_field :title %>

    titleというIDが付いたテキストフィールドを生成

  • <%= f.submit %>

    フォームfに入力された内容をHTTPリクエストで:urlオプションで指定したメソッドに送信します。
    ここではメソッドを指定していませんが、デフォルトでform_forに渡されたオブジェクトが空だったら<%= form_for @user, :url => {:action => 'create'} do |f| %>、値が入っていたら<%= form_for @user, :url => {:action => 'update'} do |f| %>と同じ動作になるので、特に指定していません。
    また、送信ボタンも同じようにCreate PostUpdate Postのようになります。

動作確認

http://localhost:3000/
スクショ7.png

Newをクリックします。

スクリーンショット 2014-03-11 19.33.48.png

レイアウトがださいですが、@postに対するフォームが完成しました。
また、homeへのリンクもきちんと表示されていますね。

create

newのViewから渡された@postのデータをデータベースに登録するメソッドを作成します。

createメソッド

newビューからHTTPリクエストで送信されたデータを元にオブジェクトを生成し、データベースに保存します。

app/controllers/posts_controller.rb
class PostsController < ApplicationController

    # indexメソッド
    def index
        # Postから全てのデータを引っ張りだし、インスタンス変数postsに代入
        @posts = Post.all
    end

    # showメソッド
    def show
        # PostモデルのfindメソッドにparamsでURLから受け取ったIDを引数として与え、
        # そのデータが見つかったらインスタンス変数postに代入
        @post = Post.find(params[:id])
    end

    # newメソッド
    def new
      # 空のPostモデルオブジェクトを生成し、インスタンス変数postsに代入
      @post = Post.new
    end

    # createメソッド
    def create
      # Viewから渡されたデータを元にオブジェクトを生成
      @post = Post.new(params[:post])
      if @post.save
        # もしDBへの生成したオブジェクトの保存が成功したら/postsへリダイレクト(移動)  
        redirect_to posts_path
      else
        # もしDBへの生成したオブジェクトの保存が成功しなかったら/posts/newへ戻ってnewビューを直させる 
        render action: 'new'
      end
    end

end

paramsメソッドを用いてHTTPリクエストからデータを取得します。
{"title"=>"テキストフィールドの内容", "content"=>"テキストエリアの内容"} こんな感じで取得されます。

動作確認

http://localhost:3000/posts/new
フォームに適当に入力します。

スクリーンショット 2014-03-11 20.49.03.png

Create Postをクリックします。

スクリーンショット 2014-03-11 20.52.24.png

/postsにリダイレクトされました。
リストにきちんと追加されていることが確認できました。

スクリーンショット 2014-03-11 20.52.32.png

もちろんcontentもみれますね。

バリデーションの設定

実は今のままだとnewで内容を入力しなくてもPostオブジェクトのデータが生成されてしまいます。内容のないブログなんてだれも見ませんので、「この条件でないとデータは生成しませんよ〜」というような規約を書いていきます。

スクリーンショット 2014-03-13 13.17.28.png

データに関する規約はModelに書くのでしたね。
validatesを用いて、データに関する規約を書いていきます。

app/models/post.rb
class Post < ActiveRecord::Base
  attr_accessible :content, :title

  # titleは入力が必須(presence -> 存在していることが必須)
  validates :title, :presence => true

  # titleは入力が必須かつ、文字数の長さが最低5は必須
  validates :content, :presence => true,
                      :length => { :minimum => 5 }
end

動作確認

http://localhost:3000/posts/new
スクリーンショット 2014-03-13 13.30.04.png

フォームの内容を空のままにしてCreate Postをクリックします。

スクリーンショット 2014-03-13 13.30.18.png

Createメソッドで、データをセーブする段階でこのバリデーションの設定が読込まれます。
データの規約に反しているため、newページへ戻されました。

スクリーンショット 2014-03-13 13.30.31.png

もちろん、データは作成されていません。

バリデーションエラーの表示

バリデーションの設定は完了しましたが、このブログのユーザーからしてみると、なんでこんな動作になるのかわかりません。どんな理由でnewページに戻されているのかを示してあげる必要がありますね。ということでバリデーションエラーを表示する機能も付けてみたいと思います。

app/views/posts/new.html.erb
<%# ヘッダー %>
<h1>New Post</h1>

<%# @postに対するフォーム %>
<%= form_for(@post) do |f| %>

  <%# もし@postにエラーがあったら %>
  <% if @post.errors.any? %>
    <%# 順序無しリスト %>
    <ul>
      <%# エラーの数だけループ %>
      <% @post.errors.full_messages.each do |msg| %>
        <%# メッセージの内容を表示  %>
        <li><%= msg %></li>
      <% end %>
    </ul>
  <% end %>

  <%# titleに対するテキストフィールド %>
  <div class = "field">
    <%# titleに対するテキストフィールド %>
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>

  <%# contentに対するテキストエリア(5行分) %>
  <div class = "field">
    <%= f.label :content %>
    <%= f.text_area :content, :rows => 5 %>
  </div>

  <%# 送信ボタン(createメソッドへ) %>
  <div class = "actions">
    <%= f.submit %>
  </div>

<% end %>

<%# HOME(index)へ戻るリンク %>
<%= link_to 'home', posts_path %>

エラー表示の部分を少し詳しくみてみます。

  • <% if @post.errors.any? %>

    バリデーションエラーがあった場合は、エラーが発生したオブジェクトのerrorsにエラーが発生したIDが格納されます。

  • <% @post.errors.full_messages.each do |msg| %>

    エラーの詳しい内容(フルメッセージ)はerrors.full_messagesに格納されます。

動作確認

さっきと同じようにフォームを空のままCreate Postします。

スクリーンショット 2014-03-13 14.21.34.png

  • Title、Contentは空にはできない。
  • Contentが短すぎる。(最小は5文字)

ということがエラーメッセージからわかります。

フラッシュメッセージの表示

ユーザーの操作に対してブログシステムがどの様に動作したかということをフラッシュメッセージ(簡単な一時的通知メッセージ)を使って知らせてあげるとさらに便利なので、やってみます。

app/controllers/posts_controller.rb
# coding: utf-8

class PostsController < ApplicationController

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
        中略
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

  # createメソッド
  def create
    # Viewから渡されたデータを元にオブジェクトを生成
    @post = Post.new(params[:post])
    if @post.save
      # もしDBへの生成したオブジェクトの保存が成功したら/postsへリダイレクト(移動)  
      redirect_to posts_path
      flash[:notice] = '作成されました!'
    else
      # もしDBへの生成したオブジェクトの保存が成功しなかったら/posts/newへ戻ってnewビューを直させる 
      render action: 'new'
    end
  end

end
  • # coding: utf-8

    プログラムのコメント以外で日本語を使う場合は必須です。UTF-8でプログラムを書いていますよ〜ということをrailsシステムに教えてあげます。

  • flash[:notice] = '作成されました!'

    ドットインストールではredirect_to posts_path, notice: '作成されました!'としています。もちろんこれでも正常に動作しますが、これはredirect_toメソッドの機能なので、flashの機能を使うことにします。これでどんなときでもflashを使うことができますね。
    flashメソッドにメッセージを格納する変数をシンボルで指定し、メッセージを指定します。

ではViewの方にも変更を加えていきます。
表示させたいところに<%= notice %>を追加するだけです。

app/views/posts/index.html.erb
<%# 一時通知メッセージ %>
<%= notice %>
<%# ヘッダー %>
<h1>Posts</h1>
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
         中略
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

動作確認

スクリーンショット 2014-03-13 17.37.37.png

なにかしら入力してCreate Postします。

スクリーンショット 2014-03-13 17.41.02.png

きちんとフラッシュメッセージが表示されていることが確認できました。

JQueryを使ってかっこよく

今作ったフラおッシュメッセージをよくある一定時間後に消すといったことをやってみます。

app/views/posts/index.html.erb
<%# 一時通知メッセージ %>
<div id="notice"><%= notice %></div>
<%# ヘッダー %>
<h1>Posts</h1>

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
         中略
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

<%# HOME、Newリンク %>
<%= link_to 'home', posts_path %> | <%= link_to 'New', new_post_path %>

<script>
    $(function() {
        //一定時間後に処理を行う(0.8秒後)
        setTimeout(function() {
            //idが"notice"のdiv要素をゆっくりとフェードアウト
            $('#notice').fadeOut("slow");
        }, 800);
    });
</script>

  • <div id="notice"><%= notice %></div>

    Javascriptでこの部分を扱うためにdivで囲ってidをつけます。

  • <script>〜</script>

    JQueryのコードです。

動作確認

さっきと同じようにフォームになにかしら入力してCreate Postしてみてください。
indexページに戻り、フラッシュメッセージがフェードアウトして消えることが確認できます。

メモ一覧

  1. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (1〜2)/全46

    #01 Ruby on Railsとは何か?
    #02 必要となるツールを揃えよう

    • Ruby on Railsはこんなものですよ
    • 必要な情報はここら辺で集まりますよ
    • 必要な知識にはこんなものがありますよ
    • 開発環境はこんな感じですよ
  2. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ 3/全46

    #03 MVCとは何か?

    • Ruby on RailsはMVCフレームワークですよ
    • MVCはこんなものですよ
  3. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (4〜8)/全46

    #04 はじめてのRailsプロジェクト
    #05 ファイル構成をみていこう
    アプリケーションを作成する基本的な流れを覚えましょう

    #06 Webサーバーを立ち上げよう
    作成したWebアプリケーションをどうささせてみましょう

    #07 scaffoldを使ってみよう (1)
    #08 scaffoldを使ってみよう (2)
    DB、Model、View、Controllerの作成、URLの設定をしてみましょう

  4. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (9〜13)/全46

    #09 ブログシステムを作ろう
    #10 新しいプロジェクトを作ろう
    #11 Postモデルを作ろう
    #12 Postsコントローラーを作ろう
    #13 ルーティングの設定をしよう
    Scaffoldを使わずに、一からブログアプリケーションを作成しよう(実践的)
    プロジェクト、Model、Controllerを作成し、ルーティングの設定をしよう

  5. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (14〜21)/全46

    #14 デバッグに使えるコンソールについて
    #15 コントローラーのメソッドについて
    #16 記事の一覧を表示する (1)
    #17 記事の一覧を表示する (2)
    #18 リンクを貼ってみよう
    #19 HTMLテンプレートを変更しよう
    #20 ロゴ画像を表示させてみよう
    #21 記事一覧画面をrootにしてみよう

    Scaffoldを使わずに、一からブログアプリケーションを作成しよう(実践的)(続き)
    rails consoleとか、rails dbconsoleなんかの便利なツールがありますよ
    コントローラーのメソッドと、それに対応するViewを作っていきましょう

    Scaffoldでは自動生成してくれたModel、DBの設定、Controller、URL、Controllerのメソッド、Viewを自力で作ります。(まずは1つ)

  6. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (22〜23)/全46

    #22 記事の詳細を表示する (1)
    #23 記事の詳細を表示する (2)

    Scaffoldを使わずに、一からブログアプリケーションを作成しよう(実践的)(続き)

    • コントローラーのメソッドと、それに対応するViewを作っていきましょう(続き)
    • Scaffoldでは自動生成してくれたModel、DBの設定、Controller、URL、Controllerのメソッド、Viewを自力で作ります。(続き - show)
  7. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (24〜30)/全46

    #24 新しい記事を追加しよう (1)
    #25 新しい記事を追加しよう (2)
    #26 新しい記事を追加しよう (3)
    #27 バリデーションを設定しよう
    #28 バリデーションエラーを表示しよう
    #29 フラッシュメッセージを表示する
    #30 メッセージをjQueryで消す

    Scaffoldを使わずに、一からブログアプリケーションを作成しよう(実践的)(続き)

    • コントローラーのメソッドと、それに対応するViewを作っていきましょう(続き)
    • Scaffoldでは自動生成してくれたModel、DBの設定、Controller、URL、Controllerのメソッド、Viewを自力で作ります。(続き - new,create)

    記事のタイトル一覧を表示するindexメソッド、その記事を表示するshowメソッドは完成したので次はその記事を表示するページが欲しいですね。ということでnewメソッド(新規作成フォーム)を作ります。また、フォームから送信されたデータを処理して新しい記事を作成するcreateメソッドも作成します。

    バリデーション(検査)の設定をやってみよう(実践的)

  8. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (31〜33)/全46

    #31 記事を更新してみよう (1)
    #32 記事を更新してみよう (2)
    #33 記事を更新してみよう (3)
    Scaffoldを使わずに、一からブログアプリケーションを作成しよう(実践的)(続き)

    • コントローラーのメソッドと、それに対応するViewを作っていきましょう(続き)
    • Scaffoldでは自動生成してくれたModel、DBの設定、Controller、URL、Controllerのメソッド、Viewを自力で作ります。(続き - edit, update)

    記事のタイトル一覧を表示するindexメソッド、その記事を表示するshowメソッド、記事の新規作成フォームを作成するnewメソッド、記事を作成するcreateメソッドは完成したので次はその記事を編集するページが欲しいですね。ということでeditメソッド(記事編集フォーム)を作ります。また、フォームから送信されたデータを処理して記事を上書きするupdateメソッドも作成します。

  9. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (34〜36)/全46

    #34 記事を削除してみよう
    #35 削除処理をAjax化しよう (1)
    #36 削除処理をAjax化しよう (2)
    Scaffoldを使わずに、一からブログアプリケーションを作成しよう(実践的)(続き)

    • コントローラーのメソッドと、それに対応するViewを作っていきましょう(続き)
    • Scaffoldでは自動生成してくれたModel、DBの設定、Controller、URL、Controllerのメソッド、Viewを自力で作ります。(続き - destroy)

    記事のタイトル一覧を表示するindex、その記事を表示するshow、記事の新規作成フォームを作成するnew、記事を作成するcreate、記事を編集するeditは完成したので次はその記事を削除するページが欲しいですね。ということでdestroyを作ります。

  10. ドットインストールでRuby on Rails 3.2を学んだ際の詳細なメモ (37〜46)/全46

    #37 Commentモデルを作ろう
    #38 Commentsコントローラーを作ろう
    #39 コメントを表示させよう
    #40 コメントを投稿してみよう (1)
    #41 コメントを投稿してみよう (2)
    #42 バリデーションを設定しよう
    #43 コメントを削除してみよう (1)
    #44 コメントを削除してみよう (2)
    #45 コメント件数を表示してみよう
    #46 Railsを日本語化しよう
    Scaffoldを使わずに、一からブログアプリケーションを作成しよう(実践的)(続き)

    • 新しい機能(Comment)を追加させましょう
    • Scaffoldでは自動生成してくれたModel、DBの設定、Controller、URL、Controllerのメソッド、Viewを自力で作ります。
7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7