railsチュートリアル第十三章 マイクロポストを作成する

###マイクロポストを作成する
####Micropostsコントローラのcreateアクション
app/controllers/microposts_controller.rb

```rb
class MicropostsController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
  # create,destroyを行う前にログインを求めらえれる。

  def create
    @micropost = current_user.microposts.build(micropost_params)
    # 慣習的に関連するモデルを生成するときは、buildを使う
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
      # redirect_to は、view の表示には直接は関係なく、新たな HttpRequest が発行されます。
    else
      render 'static_pages/home'
      # action で view を指定しない場合、規約に従って、リソース名 や
      #   action名を元に、表示する view が決まります。
    end
  end

  def destroy
  end

  private

    def micropost_params
      params.require(:micropost).permit(:content)
      # マイクロポストのcontentカラムだけ取り出すことができる。
    end
end
```

####Homeページ（/）にマイクロポストの投稿フォームを追加する
app/views/static_pages/home.html.erb

```html
<% if logged_in? %>
  <div class="row">
    <aside class="col-md-4">
      <section class="user_info">
        <%= render 'shared/user_info' %>
      </section>
      <section class="micropost_form">
        <%= render 'shared/micropost_form' %>
      </section>
    </aside>
  </div>
<% else %>
<div class="center jumbotron">
  <h1>Welcome to the Sample App</h1>

  <h2>
    This is the home page for the
    <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
  </h2>

  <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
</div>
<%#= image_tag("kitten.jpg", alt: "Kitten") %>
<%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
                      "https://rubyonrails.org/" %>
```

####サイドバーで表示するユーザー情報のパーシャル
app/views/shared/_user_info.html.erb

```html
<%= link_to gravatar_for(current_user, size: 50), current_user %>
<!--グラバターの画像と何か-->
<h1><%= current_user.name %></h1>
<!--ユーザー名-->
<span><%= link_to "view my profile", current_user %></span>
<!--リンクとリンク先-->
<!--current_user とは権限のチェックに使われるユーザー識別子-->
<span><%= pluralize(current_user.microposts.count, "micropost") %></span>
<!--マイクロポストの数を表示する-->
<!--例　３micropost-->
```

####マイクロポスト投稿フォームのパーシャル
app/views/shared/_micropost_form.html.erb

```html
<%= form_with(model: @micropost, local: true) do |f| %>
<!--local: trueがない場合、Rails5ではAjaxによる送信という意味になる。
       普通にHTMLとしてフォームを送信する場合にlocal: trueが必要になる-->
<!--マイクロポストをHTMLのフォームとして一つずつ取り出す-->
  <%= render 'shared/error_messages', object: f.object %>
  <!--sharedフォルダのerror_messagesを表示させる。-->
  <!--object: f.objectでは、f.objectに@userが入っている-->
  <!--object: f.objectはerror_messagesパーシャルの中でobjectという変数名を
      作成してくれるので、この変数を使って
        エラーメッセージを更新すればよいということです-->
  <div class="field">
    <%= f.text_area :content, placeholder: "Compose new micropost..." %>
    <!--コメント欄を作ることができる-->
    <!--その欄にコメントを書いておく-->
  </div>
  <%= f.submit "Post", class: "btn btn-primary" %>
  
<% end %>
```
####homeアクションにマイクロポストのインスタンス変数を追加する
app/controllers/static_pages_controller.rb

```rb
class StaticPagesController < ApplicationController
  def home
    @micropost = current_user.microposts.build if logged_in?
    # ログインされたら current_userのマイクロポストを生成する
  end

  def help
  end
  
  def about
  # aboutアクションを作成
  end
  
  def contact
  end
  
end
```

####Userオブジェクト以外でも動作するようにerror_messagesパーシャルを更新する
app/views/shared/_error_messages.html.erb

```html
<% if object.errors.any? %>
  <div id="error_explanation">
    <div class="alert alert-danger">
      The form contains <%= pluralize(object.errors.count, "error") %>.
      <!--@user.errors.countはエラーの回数-->
      <!--pluralizeは引数が出力される-->
      <!--エラーの回数と"error"の文字列が表示される-->
    </div>
    <ul>
    <% object.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>
```

##### テスト
```
ubuntu:~/environment/sample_app (user-microposts) $ rails t
Running via Spring preloader in process 9841
Started with run options --seed 3594

ERROR["test_password_resets", #<Minitest::Reporters::Suite:0x0000558f7e479e20 @name="PasswordResetsTest">, 3.4448097949998555]
 test_password_resets#PasswordResetsTest (3.45s)
ActionView::Template::Error:         ActionView::Template::Error: undefined local variable or method `object' for #<#<Class:0x0000558f7df2a370>:0x0000558f7e3a5fd0>
        Did you mean?  object_id
            app/views/shared/_error_messages.html.erb:1
            app/views/password_resets/edit.html.erb:8
            app/views/password_resets/edit.html.erb:6
            test/integration/password_resets_test.rb:49:in `block in <class:PasswordResetsTest>'

ERROR["test_should_get_home", #<Minitest::Reporters::Suite:0x0000558f7e66cc50 @name="StaticPagesControllerTest">, 3.56740082899978]
 test_should_get_home#StaticPagesControllerTest (3.57s)
ActionView::SyntaxErrorInTemplate:         ActionView::SyntaxErrorInTemplate: Encountered a syntax error while rendering template: check <% if logged_in? %>
          <div class="row">
            <aside class="col-md-4">
              <section class="user_info">
                <%= render 'shared/user_info' %>
              </section>
              <section class="micropost_form">
                <%= render 'shared/micropost_form' %>
              </section>
            </aside>
          </div>
        <% else %>
        <div class="center jumbotron">
          <h1>Welcome to the Sample App</h1>
        
          <h2>
            This is the home page for the
            <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
            sample application.
          </h2>
        
          <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
        </div>
        <%#= image_tag("kitten.jpg", alt: "Kitten") %>
        <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
                              "https://rubyonrails.org/" %>
        
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            test/controllers/static_pages_controller_test.rb:19:in `block in <class:StaticPagesControllerTest>'

ERROR["test_should_get_root", #<Minitest::Reporters::Suite:0x0000558f7ec0bb98 @name="StaticPagesControllerTest">, 3.6514615249998315]
 test_should_get_root#StaticPagesControllerTest (3.65s)
ActionView::SyntaxErrorInTemplate:         ActionView::SyntaxErrorInTemplate: Encountered a syntax error while rendering template: check <% if logged_in? %>
          <div class="row">
            <aside class="col-md-4">
              <section class="user_info">
                <%= render 'shared/user_info' %>
              </section>
              <section class="micropost_form">
                <%= render 'shared/micropost_form' %>
              </section>
            </aside>
          </div>
        <% else %>
        <div class="center jumbotron">
          <h1>Welcome to the Sample App</h1>
        
          <h2>
            This is the home page for the
            <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
            sample application.
          </h2>
        
          <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
        </div>
        <%#= image_tag("kitten.jpg", alt: "Kitten") %>
        <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
                              "https://rubyonrails.org/" %>
        
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            test/controllers/static_pages_controller_test.rb:12:in `block in <class:StaticPagesControllerTest>'

ERROR["test_login_with_valid_email/invalid_password", #<Minitest::Reporters::Suite:0x0000558f7dd5b9b8 @name="UsersLoginTest">, 4.065607392999937]
 test_login_with_valid_email/invalid_password#UsersLoginTest (4.07s)
ActionView::SyntaxErrorInTemplate:         ActionView::SyntaxErrorInTemplate: Encountered a syntax error while rendering template: check <% if logged_in? %>
          <div class="row">
            <aside class="col-md-4">
              <section class="user_info">
                <%= render 'shared/user_info' %>
              </section>
              <section class="micropost_form">
                <%= render 'shared/micropost_form' %>
              </section>
            </aside>
          </div>
        <% else %>
        <div class="center jumbotron">
          <h1>Welcome to the Sample App</h1>
        
          <h2>
            This is the home page for the
            <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
            sample application.
          </h2>
        
          <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
        </div>
        <%#= image_tag("kitten.jpg", alt: "Kitten") %>
        <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
                              "https://rubyonrails.org/" %>
        
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            test/integration/users_login_test.rb:19:in `block in <class:UsersLoginTest>'

ERROR["test_login_with_valid_information_followed_by_logout", #<Minitest::Reporters::Suite:0x0000558f7e082740 @name="UsersLoginTest">, 4.221937290999904]
 test_login_with_valid_information_followed_by_logout#UsersLoginTest (4.22s)
ActionView::SyntaxErrorInTemplate:         ActionView::SyntaxErrorInTemplate: Encountered a syntax error while rendering template: check <% if logged_in? %>
          <div class="row">
            <aside class="col-md-4">
              <section class="user_info">
                <%= render 'shared/user_info' %>
              </section>
              <section class="micropost_form">
                <%= render 'shared/micropost_form' %>
              </section>
            </aside>
          </div>
        <% else %>
        <div class="center jumbotron">
          <h1>Welcome to the Sample App</h1>
        
          <h2>
            This is the home page for the
            <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
            sample application.
          </h2>
        
          <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
        </div>
        <%#= image_tag("kitten.jpg", alt: "Kitten") %>
        <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
                              "https://rubyonrails.org/" %>
        
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            test/integration/users_login_test.rb:45:in `block in <class:UsersLoginTest>'

ERROR["test_layout_links_when_logged_in", #<Minitest::Reporters::Suite:0x0000558f7edf52b0 @name="SiteLayoutTest">, 4.905898562999937]
 test_layout_links_when_logged_in#SiteLayoutTest (4.91s)
ActionView::SyntaxErrorInTemplate:         ActionView::SyntaxErrorInTemplate: Encountered a syntax error while rendering template: check <% if logged_in? %>
          <div class="row">
            <aside class="col-md-4">
              <section class="user_info">
                <%= render 'shared/user_info' %>
              </section>
              <section class="micropost_form">
                <%= render 'shared/micropost_form' %>
              </section>
            </aside>
          </div>
        <% else %>
        <div class="center jumbotron">
          <h1>Welcome to the Sample App</h1>
        
          <h2>
            This is the home page for the
            <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
            sample application.
          </h2>
        
          <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
        </div>
        <%#= image_tag("kitten.jpg", alt: "Kitten") %>
        <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
                              "https://rubyonrails.org/" %>
        
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            test/integration/site_layout_test.rb:29:in `block in <class:SiteLayoutTest>'

ERROR["test_layout_links", #<Minitest::Reporters::Suite:0x0000558f7c452b60 @name="SiteLayoutTest">, 4.953971497999646]
 test_layout_links#SiteLayoutTest (4.95s)
ActionView::SyntaxErrorInTemplate:         ActionView::SyntaxErrorInTemplate: Encountered a syntax error while rendering template: check <% if logged_in? %>
          <div class="row">
            <aside class="col-md-4">
              <section class="user_info">
                <%= render 'shared/user_info' %>
              </section>
              <section class="micropost_form">
                <%= render 'shared/micropost_form' %>
              </section>
            </aside>
          </div>
        <% else %>
        <div class="center jumbotron">
          <h1>Welcome to the Sample App</h1>
        
          <h2>
            This is the home page for the
            <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
            sample application.
          </h2>
        
          <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
        </div>
        <%#= image_tag("kitten.jpg", alt: "Kitten") %>
        <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
                              "https://rubyonrails.org/" %>
        
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            app/views/static_pages/home.html.erb:28: syntax error, unexpected end-of-input, expecting end
            test/integration/site_layout_test.rb:6:in `block in <class:SiteLayoutTest>'

  56/56: [===========================] 100% Time: 00:00:04, Time: 00:00:04

Finished in 4.96300s
56 tests, 265 assertions, 0 failures, 7 errors, 0 skips
```
```ActionView::Template::Error:         ActionView::Template::Error: undefined local variable or method `object' ```
```ActionView::SyntaxErrorInTemplate:         ActionView::SyntaxErrorInTemplate: Encountered a syntax error while rendering template: check <% if logged_in? %> ```

と書かれている。
objectがおかしいのがわかる、その次がわからない

このパーシャルは他の場所でも使われていたため、ユーザー登録、パスワード再設定、そしてユーザー編集のそれぞれのビューを更新する必要があったのです。

####ユーザー登録時のエラー表示を更新する
app/views/users/new.html.erb

```html
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) do |f| %>
    <!--一つずつ取り出す-->
      <%= render 'shared/error_messages', object: f.object %>
      <%= f.label :name %>
      <%= f.text_field :name, class: 'form-control' %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>
```

####ユーザー編集時のエラー表示を更新する 
app/views/users/edit.html.erb

```html
<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) do |f| %>
      <%= render 'shared/error_messages', object: f.object %>

      <%= f.label :name %>
      <%= f.text_field :name, class: 'form-control' %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit "Save changes", class: "btn btn-primary" %>
    <% end %>

    <div class="gravatar_edit">
      <%= gravatar_for @user %>
      <a href="https://gravatar.com/emails">change</a>
    </div>
  </div>
</div>
```

####パスワード再設定時のエラー表示を更新する
app/views/password_resets/edit.html.erb

```html
<% provide(:title, 'Reset password') %>
<h1>Reset password</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, url: password_reset_path(params[:id]),
                  local: true) do |f| %>
    <%= render 'shared/error_messages', object: f.object %>

      <%= hidden_field_tag :email, @user.email %>
      <!--隠しフィールドとしてページ内に保存する手法をとります。-->
      <!--フォームを送信した後使用するメアドが消えてしまうので
      　　ここに保存させる。-->

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit "Update password", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>
```

###演習
1.Homeページをリファクタリングして、if-else文の分岐のそれぞれに対してパーシャルを作ってみましょう。
######home.html.erb
```rb
<% if logged_in? %>
  <%= render 'static_pages/user_logged_in' %>
<% else %>
  <%= render 'static_pages/user_not_logged_in' %>
<% end %>
```
#####user_logged_in.html.erb

```rb
 <div class="row">
    <aside class="col-md-4">
      <section class="user_info">
        <%= render 'shared/user_info' %>
      </section>
      <section class="micropost_form">
        <%= render 'shared/micropost_form' %>
      </section>
    </aside>
  </div>
```

#####user_not_logged_in.html.rb
```rb
<div class="center jumbotron">
    <h1>Welcome to the Sample App</h1>

    <h2>
      This is the home page for the
      <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
      sample application.
    </h2>

    <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
  </div>

  <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
              'http://rubyonrails.org/' %>
```

2.
マイクロポストを投稿した直後に、ブラウザの更新ボタンを押すとエラーが表示されます。なぜエラーが表示されるのでしょうか？その原因を考えてみましょう。

わからない。
3.
もし上記の現象に対応するとしたら、どんな対応方法があるでしょうか？その対応方法を考えてみましょう。（ヒント: 様々な対応方法がありますが、対応方法によっては今後の実装に支障が出ることがあります。ここでは対応方法のアイデア出しに留めておきましょう。）

わからない。