<%= render partial: 'books/cards/comments', locals: { impression_id: impressions.id, comments: impressions.comments} %>
belongs_to :impression, optional: true
has_many :comments
_comment.html.erb
・画面遷移を防ぐためにsubmitを外す(非同期だと同時に処理がされるので画面遷移の処理が同時に行われるのを防ぐ)
・フォームの中身をjqueryに送る
・コントローラーに送るためにjquery内にurlとデータをセットする
・今からつくるコメントをhtml上に表示させたい場所を用意する
・buttonをclickしてイベントを発火させたあとの処理を考える
・コントローラー内でparamsでコメントのデータを受け取りそれをnewで作った変数に代入する
・保存成功したデータとは別にコメントの文字列が入ったデータをjqueryに返す処理をする
・帰ってきたデータをjquery内で使いやすいように変数に格納する
・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内に処理を書く
<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に記述する必要はない。書いたらエラー。書き方間違えただけかもだけど
<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("");
この段階ではフォームの保存は終わっているので中身は消せばいい。コメントの中身は変わるかもしれないがユーザー情報が画面遷移なしに変わることはないのでこの値だけを空の文字列を入れてフォームの中をきれいにする
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を使ってます
<div class="new_comments">
# 既存のコメントが呼び出されている
<% comments.each do |comment| %>
<p><%= comment.comment %></p>
ここに新しいコメント
<% end %>
</div>
既存のコメントは一番下に一番新しいコメントがでてくるのだけれども
新しいコメントは.afterを指定してコメントを挿入しているので新しいコメントが割り込む形になる
読んでくれてありがとう