204
213

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.

JS形式のレスポンスと remote: true を使う

Last updated at Posted at 2014-10-29

Railsで、とてもスマートにAjaxできる方法が判ったので、メモです。
判ったらすごく使いやすいのですが、理解できるまでずいぶん迷走しました。

やりたいこと

表の一部をクリックすると編集モードになって、確定ボタンかなんかでまた表示モードになるようなやつ。
Viewを partialで作っといて、その部分だけ更新かかるようにしたい。

ポイント

  • レスポンスを JS形式で返す!

Viewにこんな感じのjQueryのコードを書くことで、ページの一部分だけ更新できました。

$( ('#<%= id %>' ) ).html('<%= j( render( 'show_form' ) ) %>');

j は、escape_javascript のエイリアスで、改行と括弧をエスケープしてくれるメソッドです。

  • フォームは remote: true を指定する
<%= form_for(@page, data: { remote: true }) do |f| %>
    <%= f.hidden_field :id %>
    <%= f.text_field :title %>
    <%= f.submit('更新') %>
<% end %>

こうするとページを更新しないでリクエストだけ投げてくれます。
パラメータのやり取りは、普通のフォームと同じに出来るのが最高です。

実際のところ

中身はこんな感じです。(ダミーに直してるので動かないかも。。。)

ファイル構造

通常のCRUDと、Ajax部分はコントローラを分けたけど、一緒でも出来るんじゃないかな。
Modelはご想像の通りということで。

|
|-- app
    |-- assets
    |   |-- javascripts
    |       |-- pages_ajax.js.coffee
    |-- controllers
    |   |-- pages_ajax_controller.rb
    |-- views
        |-- pages
        |   |-- index.html.erb
        |-- pages_ajax
            |-- _edit_form.erb
            |-- _show_form.erb
            |-- edit.js.erb
            |-- show.js.erb
config/routes.rb
  resources :pages, path:'pages/ajax', controller: :pages_ajax
  resources :pages

最初に呼ばれる普通のView

他のコントローラの partialを呼びたい時は、コントローラ名まで指定すればOK。
このとき、部分テンプレートを意味する頭の_は取る。

app/views/pages/index.html.erb
<table>
	<thead>
		<tr>
			<th>タイトル</th>
		</tr>
	</thead>
	<tbody>
		<% @pages.each do |page| %>
		<tr id="<%= page.id %>">
			<%= render partial: 'pages_ajax/show_form' %>
		</tr>
		<% end %>
	</tbody>
</table>

コントローラ

普段通りでOK。
メソッド名とレスポンス形式で自動的にViewを選択してくれるみたいです。
このレスポンス形式ってどうやって選択してんだろというのがちょっと疑問ですが、とりあえずAjaxで来た時はJS形式で返してくれます。

app/controllers/pages_ajax_controller.rb
class PagesAjaxController < ApplicationController
  before_action :set_page, only: [:show, :edit, :update]

  def show
  end

  def edit
  end

  def update
    @page.update(asign_params)
  end

  private
    def set_page
      @page = Page.find(params[:id])
    end

    def page_params
      params.require(:page).permit(:id, :title)
    end
end

表示モード、編集モードの部分テンプレート

app/views/pages_ajax/_show_form.erb
<%= @page.title %>
&nbsp;
<a class="edit" id="<%= @page.id %>"><%= fa_icon "edit" %></a>

Font Awesome使ってるのは、記事テーマとは関係ないですが。

app/views/pages_ajax/_edit_form.erb
<div style="text-align: right;">
	<a class="close"><%= fa_icon "times" -%></a>
</div>
<%= form_for(@page, data: { remote: true }) do |f| %>
    <%= f.text_field :title %>
    <%= f.submit('更新') %>
<% end %>

閉じるボタンは付けとかないとですね。

JavaScript

これだけ? これだけです!

app/assets/pages_ajax.js.coffee
$(document).on 'click', 'a.edit', ->
	id= $(this).attr('id')
	$.get("pages/ajax/#{id}/edit")

$(document).on 'click', 'a.close', ->
	id= $(this).attr('id')
	$.get("/pages/ajax/#{id}")
app/views/pages_ajax/edit.js.erb
$( ('#<%= @page.id %>' ) ).html('<%= 
    j( render( 'edit_form' ) ) 
  %>');
app/views/pages_ajax/show.js.erb
$( ('#<%= @page.id %>' ) ).html('<%= 
    j( render( 'show_form' ) )
  %>');

はまったとこ

最初は、pages.js.coffee に、ベタ書きで JavaScriptを書いてました。
リクエストに付けるパラメータを自分で処理しなきゃいけなくて死にました。

あと、編集→更新→もいっかい編集が出来ない。
更新のとこで受け取った部分テンプレートには、JavaScriptがついて来なくて。

レスポンスをJS形式で返却するというのは目からウロコでした。

Thanks a lot!!

↓のサイトを参考にさせて頂きました。
http://www38.atwiki.jp/eyes_33/pages/61.html

204
213
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
204
213

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?