7
5

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 3 years have passed since last update.

remote: trueでajaxの投稿をPOSTをするよ。

Last updated at Posted at 2021-01-09

何をしたか

Railsでアプリを作っています。タイトルの通りなのですが、remote: trueajaxの投稿ができるフォームを作りました。
初回ではないのでスルスル作れたのですが、手順や考え方がしっかり身についていないので、自分のためのノートとしてメモします。

なお、実行環境は以下の通りです。

  • Rails 5.2.3
  • Ruby 2.6.0

参考記事

実装にあたっては、以下の記事を大変参考にさせていただきました。

【Rails】remote: trueでフォーム送信をAjax実装する方法とは?

今回の手順も↑こちらとそっくりになってしまったので、丁寧な解説をみたい方は上記の記事を見ていただいた方が良いかと思います。(こちらはあくまでも、私自身のためのメモですので。。。。)

実装方法

作ったもの

Image from Gyazo
今回作ろうとしたのは、こんな感じの、投稿にぬるぬるとコメントを投稿できる仕組みです。DB構造的にはpostsテーブルに紐づくcommentsがある状況です。(画像は作成中のものなので、そのうち挿げ替えるかもしれません。)

remote: trueのフォームを作ってみる

まずは、通常通りコメントを投稿するフォームを作ってみました。なお、装飾のためのclassや、今回の実装に関係ない要素は省略しています。(以下、全てのコードで同じ)

= form_with model: [@post, @comment] do |f|
  = f.text_field :text
  = f.submit '投稿'

form_withはデフォルトがremote: trueなので、local: trueもついていない、非常にシンプルなフォームになっています。

controller

comments_controller.rb
def create
  @comment = @post.comments.build(comment_params)
  @comment.save!
end

controllerも非常にシンプルにしました。
なお、今回はremote: trueの挙動確認が主な目的なので、

1) redpond_to, formatでhtmlとjsの処理を分けること
2)@commentが保存できなかった時のエラーハンドリング

は実装していません。

2)ついては別記事にしたいなとも思うのですが、実際に実装するときには上記の2点も考慮しているというのは追記しておきます。

とにかくにも、上記のcontrollerによってjsフォーマットのcreate.js.erbが呼び出されるようになります

create.js.erb

ところで、**.js.erbって、聞き慣れないファイル名ですよね。このファイルは何ができるかというと、(以下、先に紹介したこちらの記事からの引用です。)

  1. ファイル内に記述したJavaScriptのコードを実行する
  1. ERBタグを使用することができる
  2. インスタンス変数を使用することができる

上記のことができます。便利ですね:relaxed:
なので、上記に記した、create.js.erbに例えば下記の様に書くと...。

comments/create.js.erb
$('.comments').append("<%= @comment.text %>");

それだけでこのようなビューを作ることができます。

Image from Gyazo

まだ形は整っていないですが、ぬるぬると投稿が表示されていきますね:relaxed:

補足1:投稿をする先のビューについて

なお、順番が前後してしまいましたが...。今回投稿をするのビューはこの様な構造になっています。

.comments
  = render @comments

.commentsクラスの下に、@commentsの中身を展開して呼びだす構造になっていて、(←こちら、すごく端折った書き方ですので、「???」という方はこちらの記事をご覧ください)

先に書いたこのコードで、

comments/create.js.erb
$('.comments').append("<%= @comment.text %>");

.comments内の@comment群の末尾に、投稿した新しい@commentが足されていきます。

補足2:実際に書いたコードについて

実は上記のコードだけでは、投稿後、フォームの中に投稿したコメントが残り続けます。そのため、実際には下記の様なコードを書いています。

= form_with model: [@post, @comment], class: 'js-comment-form' do |f| #追記
  = f.text_field :text
  = f.submit '投稿'

フォームにjs-comment-formというクラスをつけ、

comments/create.js.erb
$('.comments').append("<%= @comment.text %>");
$('.js-comment-form')[0].reset();

テキストの追加後、.js-comment-formの中身をリセット(空に)しています。

create.js.erbでのパーシャルの呼び出し

とにかくにも、これで非同期で投稿できる様になりましたので、あとはもう少し見た目をリッチにしていきたいと思います。

結論から言うと、書いたコードは下記の通りです。

comments/create.js.erb
$('.comments').append("<%= j(render 'comment', comment: @comment) %>");

まず、render 'comment'の部分で、comments/_commentのパーシャルを呼び出しています。

(先の補足1の箇所に戻りますが、今回、コメントを投稿するのビューは下記の通りです。したがって_commentというパーシャルが存在します。)

.comments
  = render @comments

次に、jメソッドでJavaScriptのコードをエスケープしています。この辺りは、この2記事を読んで理解を深めました。

パーシャルの中身は、詳しくは省略しますが、大体こんな感じです。こちらはhamlslimなどを使って書いてなんら問題ありません。

comments/_comment.html.slim
div
 = アイコンの画像
 = comment.user
 div
   = comment.text
    div
      = 削除アイコン
      = 編集アイコン

完成!

ここまでの実装で、上記にあげた画像の実装を実現しています。
Image from Gyazo

ちょっと苦手なところだったのですが、一段落したところで記事を書くことで、実装に関する理解を深め、ついでにリファクタリングもできました:relaxed:

これから、エラーハンドリングや編集・削除の非同期での実装も頑張っていきたいです。

7
5
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
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?