Ruby
JavaScript
Ajax
Rails4

RailsでAjax基本形(Scaffoldで学ぶ)

More than 1 year has passed since last update.


前提


  • 超単純なモデル構造(1モデル)

  • コントローラーはindex以外Ajax(シングルページな感じ)

  • new, editなんかも新しいページに遷移するんじゃなくて、同じページ内にdivを挿入する感じ

  • rails new済のところからスタート

  • viewのhtmlレンダリングエンジンはhaml


前準備(Ajaxの前まで)


Model作成

$ ./bin/rails g model task name:string


Controller作成

$ ./bin/rails g controller tasks


RouteとControlle#index

ベースになるページを作る。


ルーティング設定


config/route.rb

Rails.application.routes.draw do

root 'tasks#index'
resources :tasks
end


コントローラー


app/controllers/tasks_controller.rb

def index

@tasks = Task.all
end


ビュー(ベースになるページ)


app/views/tasks/index.html.haml

%h1 Task List

%table{id: "tasks", class: "table"}
= render @tasks


補足

初心者的にようわからんポイントは、 = render @tasks のとこ・・

これは省略されているだけで、フルで書くと

= render :partial => 'task', :collection => @tasks

になる。

参考:Rails Best Practices - Simplify render in views


ビュー(partial)

各taskをリスト表示する部分


app/views/tasks/_task.html.haml

%tr

%td=task.name


やっとこさAjaxしますよ!(こっから本題)


Step 1. 一覧ページに、TaskController#newのajax呼び出しをいれる

さっきのページに一番下に1行追加

ajaxなので remote: true


app/views/tasks/index.html.haml

%h1 Task List

%table{id: "tasks", class: "table"}
= render @tasks
= link_to "New Task", new_task_path, remote: true


Step 2. Controllerの動き


app/controllers/tasks_controller.rb

def new

@tasks = Task.new
respond_to do |format|
format.html
format.js
end
end

scaffoldに従うと、こんな感じで、 respond_to が入ってくる。

コレがないと対応したformatの呼び出しに応答してくれない。。

(htmlはデフォルトなのでなければhtml応答になる)

ここではrenderを省略しているので、Railsのデフォルトであるコントローラーアクション名と同名のテンプレートをレンダーしようとしてくれる。


remote: true なしの場合

HTMLを返そうとするので、探しに行くテンプレートは

app/views/tasks/new.html.haml


remote: true ありの場合

JSを探しに行く

app/views/tasks/new.js.erb


app/views/tasks/new.js.erb

$('#task-form').html("<%= j (render 'form') %>");

$('#task-form').slideDown(350);

JSコードとして返され、評価される。

erbを使ってフォームのレンダリングを組み込んでいる。

ちなみにerbはRailsのデフォルトなのでhamlを使っていても使えないわけじゃない。

jsコード内にhamlは書きにくいらしいので、erbでやるほうがやりやすいらしい。

jsからレンダーされるform


app/views/tasks/_form.html.haml

= simple_form_for @task, remote: true do |f|

= f.input :description
= f.input :deadline
= f.button :submit

ここでも remote: true が使われているが、これはsubmitのアクションをajax呼び出ししたいから。

ここでは新規作成後のPOSTなので、呼び出されるコントローラーは TasksController#create


app/controllers/tasks_controller.rb

def create

@task = Task.build(task_params)
respond_to do |format|
if @task.save
format.html
format.js
else
format.js { render :new }
end
end
end

呼び出されるのは format.js で指定されている app/views/tasks/create.js.erb


app/views/tasks/create.js.erb

$('#tasks').html("<%= j (render @tasks) %>");

$('#task-form').slideUp(350);

j (render @tasks) の j は ActionView::Helpers::JavaScriptHelper#escape_javascript

のエイリアスメソッド。


Escapes carriage returns and single and double quotes for JavaScript segments.


改行コード、シングルクオート、ダブルクオートをJavaScript用にエスケープしてくれるヘルパメソッド(のエイリアス)

erb が Ruby コードとして解釈した文字列をJavaScriptで正しく扱えるようにエスケープしてくれる。

この例の場合 render @tasks なので、 app/views/tasks/_index.html.haml が評価された文字列が入ってくる。

(RubyMineがあると、j メソッドの呼び出しが何なのか、Cmd + B で定義元にジャンプしてくれてとてもわかりやすい)



参考URL

めっちゃわかりやすいので、↑を見れば良い・・という・・・