LoginSignup
111
107

More than 5 years have passed since last update.

モモンガでも使えるAjax(えいじゃっくす) − 投稿したコメントをリロードせずに表示しよう

Last updated at Posted at 2015-08-07

あなたがRails触る人なら見ておきたい「体系的な」豆知識」からの派生記事です。

Railsでフォームに入力した文章をリロード無しで保存、描画することで最も簡単なAjaxの流れの説明を試みたいと思います。

Ajaxとは

「Ajaxとは」と検索すると大量に説明文が出てきますがよく「非同期通信の総称」とかいう記述を目にします。
難しい話はよくわからないので「何かフォームからデータを送信した時にページをリロードせずにデータの保存・描画を行う」ことだとしましょう。以下のような感じです。

Ajaxのイメージ

いちいちリロードしないとは素晴らしいですね!
これを応用すると「いいねボタン」なども簡単につくれます。

Ajax通信の必要条件

  • formにremote属性がセットされていること
  • 対応するアクションが存在すること
  • 対応するJSファイルが存在すること

実はこれくらいです。
ファイルを作り、記述をちょちょいっと変えるだけでAjaxは導入できてしまいます。

Ajax通信のイメージ

ajax.png

順を追って見て行きましょう。

  1. 非同期通信の発生

    • 上記のようにフォームにAjaxを導入したときは、submitボタンを押した時に「 非同期通信を行いなさい 」という指令がControllerに飛びます。
  2. JSの応答

    • 非同期通信を行うよう指令を受けたControllerは指定のアクションを実行し、その後テンプレートファイルを読み込みにかかります。
    • 通常ここではフォーマットを指定しない限りHTMLファイルが読み込まれますが、「非同期通信を行いなさい」と指定されたControllerはHTMLファイルを読み込まず アクション名と対応したJSファイル を読み込みにかかります。
    • update アクションを実行したのであれば対応するJSファイルは update.js.erb です。
  3. スクリプトの実行

    • JSファイルが読み込まれると中に記述してあるスクリプトを実行し、一連の処理を終了します。
    • このスクリプトに「 ビューの中のこの部分をこのように変更しなさい 」という指示を織り込むことで、ページリロードせずともページ内の一部表示が再描画されるのです。

実際に書いてみる

今回題材にするのは、あるプロトタイプの投稿に対する「コメント機能のAjax化」です。
上記で示した順序に沿って実装してみましょう。

  1. Ajaxする前の段階を確認
    【 View 】

    prototypes/show.html.haml
    %div
      = render @prototype.comments
    %div
      = form_for @new_comment do |f|
        %h4 Write a comment
        = f.text_area :text
        = f.submit :comment, class: "btn btn-primary"
    
    prototypes/_comment.html.haml
    %div
      %div
        = image_tag comment.avatar_thumbnail
      %div
        %h4
          = comment.user.name
        %p
          = comment.text
    

    【 Controller 】

    comments_controller.rb
    def create
      Comment.create(comment_params)
      @prototype = Prototype.find(params[:id])
      redirect_to prototype_path(@prototype)
    end
    
    • コメントを書いて投稿ボタンを押すと、「ページがリロードされて書いたコメントが表示される」という何の変哲もないフォームです。
  2. 投稿ボタンを押した時に非同期通信が走るようにする

    sample.html.haml
    #comments
      = render partial: 'prototypes/comment', collection: @prototype.comments
    %div
      = form_for @new_comment, remote: true do |f|
        %h4 Write a comment
        = f.text_area :text, id: "comment_field"
        = f.submit :comment, class: "btn btn-primary"
    
    prototypes/_comment.html.haml
    -# 変更なし
    
    • まずは送信ボタンを押した際に「非同期通信を行いなさい」という指令が出るようにしたいのですが、これは form_for に対して remote: true を設定して完了です。
    • 後々JSによる操作を行いやすくするために、「コメントを表示する部分(#comments)」と「コメントを入力するフィールド(#comment_field)」にそれぞれ固有のidを付与しています。
  3. 非同期通信が走った後に投稿を保存しJSのテンプレートファイルを呼び出す

    comments_controller.rb
    def create
      Comment.create(comment_params)
      @prototype = Prototype.find(params[:id])
    end
    
    • redirect処理を消去しただけです。これでアクション名と対応したJSテンプレートファイルを読み込みにいってくれます。
  4. スクリプトを実行してコメント部分のみ再描画する

    comments/create.js.erb
    $('#comment_field').val('');
    $('#comments').html(
      '<%= j(render partial: 'prototypes/comment', collection: @prototype.comments) %>'
    );
    
    • JSテンプレートファイルは js.erb 形式で他のビューファイルと同ディレクトリに作成し、読み込まれるとファイル中のスクリプトを実行してくれます。
    • 今回の場合は、投稿ボタンを押したタイミングで以下の動作を行っています。
      1. コメントを入力するフィールドの文字を消去し
        • $('#comment_field').val('');
      2. コメントを表示する部分のHTMLを再描画する
        • $('#comments').html('<%= j(render partial: 'prototypes/comment', collection: @prototype.comments) %>');
    • jメソッド はビューヘルパーである escape_javascriptメソッド のエイリアスです。クォーテーションや改行をエスケープしてくれるため、慣習的に付けておきます。
    • 今回使用しているように、JSテンプレート内では外部の部分テンプレートも問題なく呼び出すことができます。

動作を確認してみる

ここまでで大方仕様は作りこめたので、動かしてみましょう+(0゚・∀・) + ワクテカ +

\\ ポチッ! //
Ajaxのイメージ

うごいたぁぁぁぁ!!

カウンター部分は今回解説に含めていないので、どうすればできそうか考えてみてください。
ちなみに応用するといいねボタンもつくれます。
いいねボタン

こんな感じですが、まずは習うより慣れろです!
コピペでも構わないので、まずは自分の今書いているコードに導入してみてください。

111
107
2

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
111
107