1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ajaxを使ったコメント作成

Last updated at Posted at 2019-01-02
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は処理の行き先を決めているものだから今回は
1 html上で処理しようと思ってもできない
2 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を指定してコメントを挿入しているので新しいコメントが割り込む形になる

読んでくれてありがとう

1
4
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
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?