LoginSignup
125
151

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-08-27

前提

  • 超単純なモデル構造(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

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

125
151
3

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
125
151