Rails 非同期通信(ajax)


記事にコメントを実装します。
リロードしなきゃ投稿したコメントが表示されない状態だったのでajaxで実装しました。

記事に表示は`tops_controller.rb`
コメントもこの中のアクションに記述しています。

完成形
<img width="854" alt="スクリーンショット 2019-04-25 0.32.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265805/69c78716-5d31-7527-fc53-e5d34367fe4a.png">

<img width="778" alt="スクリーンショット 2019-04-25 1.42.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265805/c9357772-e2e1-4357-3010-a7332c05d749.png">




##アソシエーション

```article.rb
  has_many :comments, dependent: :destroy
```

```comment.rb
  belongs_to :article
```

##コメント作成

```tops_controller.rb

  def show
    @article_id = Article.find(params[:id]) #記事id取得
    @comment = Comment.new　#コメント作成
    @comments = @article_.comments　　#記事に紐づくコメント全取得
    # @comments = Comment.where(article_id: @article_id) 上と同じ意味(書かなくていい)
    session[:article_id] = @article_id.id #sessionに格納して次のアクションでも使えるように
  end

  def create
    @article_id = Article.find_by(id: session[:article_id])　　#記事id取得
    @comment = Comment.new(comment_params)  #コメント作成
    @comment.article_id =  @article_.id #アソシエーションしてるのでarticle_idを指定

    if @comment.valid? #バリデーションひっかってるか確認
       @comment.save　#大丈夫そうだったら保存
       @comments = []　#空配列を定義
       @comments << @comment #@commentsに今作った@commentをpush・・・comment_lists.html.erbで使う
       render :comment_lists　(アクションは必要ない（このファイルのjs.erbファイルを作る）)
    else
      render :action => "show"
    end
  end
```

```_comment_form.html.erb

<%= form_with model: [@article_id, @comment], :url => { :action => 'create' }  do |f| %>
#@article_idは記事ID取得の変数、@commentはコメント作成の変数
  <div class = "form">
    <div class="label">
      <%= f.label(:name)%>
    </div>
    <div class="parts clearfix">
      <%= f.text_field :name, :class => 'text' %>
    </div>
  </div>
  <div class = "form">
    <div class="label">
      <%= f.label(:email)  %>
    </div>
    <div class="parts clearfix">
      <%= f.text_field :email, :class => 'text' %>
    </div>
  </div>
  <div class = "form">
    <div class="parts clearfix">
      <%= f.text_area :content, :placeholder => "コメント内容", :class => 'text' %>
      <%= error_on(:comment, :content)%>
    </div>
  </div>

  <div class = btn_wrap>
    <%= f.submit "コメントする", :class => "check" %>
  </div>
<% end %>
```

```comment_lists.html.erb

<% if @comments %>
  <% @comments.each_with_index do |comment,i| %>
    <div class="comment_box">
      <div class ="wrap">
        <div class = "id"><%= link_to "#{i+1}", new_reply_path %></div>
          <div class = "name"><%= comment.name %></div><br>
         <div class = "date"><%= comment.created_at.strftime("%Y/%m/%d %H:%M")%></div>
      </div>
      <div class ="content"><%= comment.content %></div>
    </div>
  <% end %>
<% end %>
```


```comment_lists.js.erb

// 内容消してる
$('textarea').val('');
$('input').val(''); 

//コメント一覧に今作成したコメントを追加（動的に）
$('.comment_lists').append('<%= j(render 'comment_lists') %>'
);
```

参考URL２つめを参考にに書いていた↓にかいてある`collection:`に記述している変数は、ただ`comment_lists.html.erb`で使える編集を記述しているだけらしく、今回の場合コントローラに@commentsを定義しているからいらないらしい

```
$('.comment_lists').append('<%= j(render 'comment_lists'), collection: @comments) %>');
```


参考記事
https://ysk-pro.hatenablog.com/entry/2018/02/10/101739
https://qiita.com/Yama-to/items/377f8a92cf30a3ebf454