非同期通信の実装においての理解をアウトプットしてみた。
非同期通信でメッセージ送信とは?
身近な例で言えば、LINEでメッセージを送信した際、送信したメッセージが画面の下にスクロールする動作がそれに当たる。
実装手順
1.フォームが送信されたら、イベントが発火するようにする
2.イベントが発火したときにAjaxを使用して、messages#createが動くようにする
3.messages#createでメッセージを保存し、respond_toを使用してHTMLとJSONの場合で処理を分ける
4.jbuilderを使用して、作成したメッセージをJSON形式で返す
5.返ってきたJSONをdoneメソッドで受取る
6.doneメソッドで受取り、HTMLを作成する
7.作成したHTMLをメッセージ画面の一番下に追加し、その分メッセージ画面を下にスクロールさせる
8.非同期に失敗した場合の処理も準備する
9.完成ソースコード
1.フォームが送信されたら、イベントが発火するようにする
$("#new_message").on('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
var url = $(this).attr('action');
})
new_message であるフォームが送信されたら、イベントが発火する。
2.イベントが発火したときにAjaxを使用して、messages#createが動くようにする
$.ajax({
url: url,
type: "POST",
data: formData,
dataType: 'json',
processData: false,
contentType: false
})
以上のように、ajax通信を行って、」コントローラのcreateアクションを動かす。
3.messages#createでメッセージを保存し、respond_toを使用してHTMLとJSONの場合で処理を分ける
messages_controller.rb
def create
@message = @group.messages.new(message_params)
if @message.save
respond_to do |format|
format.html {redirect_to group_messages_path(@group), notice: 'メッセージが送信されました'}
format.json
end
else
@message = @group.message.includes(:user)
flash.now[:alert] = 'メッセージを入力してください'
render :index
end
end
以上のように、respond_to do |format| を使い、コントローラーのcreateアクション内で、formatがHTMLの時とjsonの時との処理を分ける。
4.jbuilderを使用して、作成したメッセージをJSON形式で返す
create.json.jbuilder
json.user_name @message.user.name
json.content @message.content
json.time @message.created_at
json.id @message.id
5.返ってきたJSONをdoneメソッドで受取る
.done(function(data){
var html = buildHTML(data);
$('.messages').append(html);
$('.form__message').val('');
$('.form__submit').prop('disabled', false);
$('.messages').animate({ scrollTop: $('.messages')[0].scrollHeight});
})
.fail(function(){
alert('error')
$('.form__submit').prop('disabled', false);
6.doneメソッドで受け取ったHTMLを作成する
$(function() {
function buildHTML(message){
var html = `<div class="message">
<div class="upper-message">
<div class="upper-message__user-name">
${ message.user_name }
</div>
<div class="upper-message__date">
${ message.time }
</div>
</div>
<div class="lower-message">
<p class="lower-message__content">
${ message.content }
</p>
</div>
</div>`
return html;
}
})
})
})
7.作成したHTMLをメッセージ画面の一番下に追加し、その分メッセージ画面を下にスクロールさせる
.done(function(data){
var html = buildHTML(data);
$('.messages').append(html);
$('.form__message').val('');
$('.form__submit').prop('disabled', false);
$('.messages').animate({ scrollTop: $('.messages')[0].scrollHeight});
})
スクロールさせる時は、animateとscrollHeightのメソッドが必要となる
8.非同期に失敗した場合の処理
.fail(function(){
alert('error')
$('.form__submit').prop('disabled', false);
連続でメッセージを送信しようとすると、エラーメッセージがアラートされる
9.完成ソースコード
$(function() {
function buildHTML(message){
var html = `<div class="message">
<div class="upper-message">
<div class="upper-message__user-name">
${ message.user_name }
</div>
<div class="upper-message__date">
${ message.time }
</div>
</div>
<div class="lower-message">
<p class="lower-message__content">
${ message.content }
</p>
</div>
</div>`
return html;
}
$("#new_message").on('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
var url = $(this).attr('action');
$.ajax({
url: url,
type: "POST",
data: formData,
dataType: 'json',
processData: false,
contentType: false
})
.done(function(data){
var html = buildHTML(data);
$('.messages').append(html);
$('.form__message').val('');
$('.form__submit').prop('disabled', false);
$('.messages').animate({ scrollTop: $('.messages')[0].scrollHeight});
})
.fail(function(){
alert('error')
$('.form__submit').prop('disabled', false);
})
})
})
以上、ざっくりとした解説でした。細かいコードの意味までは、まだ全然理解できていないので、どなたかご指摘いただけると助かります。
以上