ajaxを使ったコメント作成


```show.html.rb
<%= render partial: 'books/cards/comments', locals: { impression_id: impressions.id, comments: impressions.comments} %>
```

```comment.rb
belongs_to :impression, optional: true
```
```impression.rb
has_many :comments
```

## _comment.html.erb
・画面遷移を防ぐためにsubmitを外す（非同期だと同時に処理がされるので画面遷移の処理が同時に行われるのを防ぐ）
・フォームの中身をjqueryに送る
・コントローラーに送るためにjquery内にurlとデータをセットする
・今からつくるコメントをhtml上に表示させたい場所を用意する
・buttonをclickしてイベントを発火させたあとの処理を考える
・コントローラー内でparamsでコメントのデータを受け取りそれをnewで作った変数に代入する
・保存成功したデータとは別にコメントの文字列が入ったデータをjqueryに返す処理をする
・帰ってきたデータをjquery内で使いやすいように変数に格納する
・htmlに表示したい形のイベントを書いてあげる

```_comment.html
# headに記述がないないのなら読み込みー
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
```

## form
### submit処理を消す
submitが押されるとフォームの処理が走ってフォームが指定したurlに支持が送られる。
この時urlでほかの画面を呼び出せば当然画面遷移が行われる。コントローラーを指定してもコントローラーからの支持を受け取るために画面がロードされるので`onclick="submit();"`を

```
<button id="button" type="button" onclick="submit();">送信</button>
```
から消してurlへ支持を送れなくする。urlは書いてあるが、処理を行えなくしたのでurlをコントローラーに送るためにjqyery内に処理を書く

```_comment.html
<div class="comment-form" >
  <%= form_with model: Comment, url: '/comments/create' do |form| %>
    <div class="comment">
      <%= form.label :コメント %>
      <%= form.text_field :comment %> 
      <%= form.hidden_field :user_id, :value => @current_user.id %>
      <%= form.hidden_field :impression_id, :value => impression_id %>
    </div>
    <div class="btn-form">
      <button id="button_form" type="button" >送信</button>
    </div>
  <% end%>
</div>
```

 ・jqueryの方でurlを指定しているからこっちに書かなくてもいいだろうと思ってurlを消したらエラーがでた
`undefined method 'comments_path'`
fomr_withは
URLを指定：そのURLがあるか調べる
URLを指定：URLをmodel or controller などから勝手に推測する
のでform_withの欲求を満たす何者かをおいて置く必要があるみたいです

 ・local: trueは処理の行き先を決めているものだから今回は
１　html上で処理しようと思ってもできない
２　buttonにjqueryイベントがついている
ので行き先はlocalで指定しなくても決まっているので消してもエラーは出ない

・最初は`model: Comment.new`と書いていたがnewを消しても動くみたいです

# jquery

#### jquery用の値
テーブル＿カラムの形で、自動でデータを作ってくれているみたいです。
`id="comment_comment"` `id="comment_user_id"` `id="comment_impression_id"`と既にrailsの方でidを作っているのでjqueryで使う値を取得するコードをformに記述する必要はない。書いたらエラー。書き方間違えただけかもだけど

```_comment.html

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
 $(function () {
   $('#button_form').click(function () {
      var self = $(this);
      # railsの値をjqueryで扱えるように代入する
      var userId = $("#comment_user_id").val();
      var impressionId = $("#comment_impression_id").val();
      var comment = $("#comment_comment").val();
      $.ajax({
        url: '/comments/create',
        type: 'POST',
        dataType: "json",
        timespan: 2000,
        data: {
          'user_id' : userId,
          'impression_id' : impressionId,
          'comment' : comment,
        }
      })
      .done((data) => {
        $('#comment_comment').val(""); // データがうまく渡ったらフォームをリセットする
        var newComment = data.comment; // controllerから受け取った文字列を変数に代入
        var pTag = $("<p>");
        pTag.html(newComment);
        $('.new_comments').after(pTag);
        console.log(data.comment);
        console.log("success");
      })
      .fail((data) => {
        console.log("fail");
      })
      .always((data) => {
        console.log("always");
      });
   });
  });
</script>
```
`$('#comment_comment').val("");`この段階ではフォームの保存は終わっているので中身は消せばいい。コメントの中身は変わるかもしれないがユーザー情報が画面遷移なしに変わることはないのでこの値だけを空の文字列を入れてフォームの中をきれいにする

```comment_controll.rb
def create
    impression_id = params[:impression_id].to_i //paramsは文字列なのでto_iで数値にしている
    new_comment = params[:comment]
    user_id = params[:user_id].to_i
    comment = Comment.new
    comment.impression_id = impression_id
    comment.comment = new_comment
    comment.user_id = user_id
    # binding.pry
    if comment.save
      success_json = { // これがjson形式ということでしょうかね
        "comment" => new_comment,
      }
      render :status => :ok, :json => success_json
    else
      failer_json_object = {'status' => 'failer'}
      render :status => :internal_server_error, :json => failer_json_object
    end
  end
```

## 表示のされかた
show.html.erbのrenderで`comments: impressions.comments`とされているので@がついていないcommentsを使ってます

```_comment.html
<div class="new_comments">
   #　既存のコメントが呼び出されている
  <% comments.each do |comment| %> 
    <p><%= comment.comment %></p>
　　ここに新しいコメント
  <% end %>
</div>
```
既存のコメントは一番下に一番新しいコメントがでてくるのだけれども
新しいコメントは.afterを指定してコメントを挿入しているので新しいコメントが割り込む形になる


読んでくれてありがとう