概要
みなさんこんにちはcandleです。
今回はrailsのformをremoteを使ってajaxした時に、
サーバに送った値をjavascript側で受け取る方法を紹介します。
ちなみに、私は下のサイトを参考にしました。
http://ericlondon.com/2014/01/25/ruby-on-rails-4-ajax-form.html
前提
適当なrailsプロジェクトがある
twitter bootstrap gemを使っても良いでしょう。
twiwtter bootstrap gemはデザイン名で見やすくする為に使うので、無くても構いません。
もしも、記事と同じ様に、進行したい場合は下のURLを参考にしてください。
scaffoldを作成する
scaffolを作成します。
rails g scaffold RemoteForm title:string description:text
作成されたら、マイグレーションファイルをデータベースに反映させます。
rake db:migrate
twitter bootstrap gemを入れている場合は
下のコマンドでデザインを適応させます。
rails g bootstrap:themed RemoteForms
これでscaffoldが完成しました。
フォームをajax化する
scaffoldで作成したフォームは普通にpostかputで送信してしまうので変更します。
app/views/remote_forms/_form.html.erbを開いて、以下の部分を変更しましょう。
<%= form_for @remote_form, remote: true, format: :json ,:html => { :class => 'form-horizontal remote_form' } do |f| %>
ここではリモートフォームの設定と、format jsonは多分jsonで値を返すみたいな意味だと思います。
新しくclassでremote_formというのを加えておきます。クラス名自体に意味はありません。
これでフォームのリモート化は完了です。
controllerを変更する
scaffoldで作成されたcreateアクションとupdateアクションはリダイレクトかjsonで値を返すことを想定しています。
今回の場合は送られたフォームが保存に失敗しても成功しても、jsonで返してほしいので、以下の様に変更します。
app/controllers/remote_forms_controller.rbを開きます。
まずはcreateアクションの以下の部分を変更します。
respond_to do |format| if @remote_form.save format.html { redirect_to @remote_form, notice: 'Remote form was successfully created.' } format.json { render json: @remote_form } else format.html { render action: 'new' } format.json { render json: @remote_form.errors.full_messages, status: :unprocessable_entity } end end
変更している箇所はform_josnの所のみです。
同じ様にupdateアクションも変更します。
respond_to do |format| if @remote_form.update(remote_form_params) format.html { redirect_to @remote_form, notice: 'Remote form was successfully updated.' } format.json { render json: @remote_form } else format.html { render action: 'edit' } format.json { render json: @remote_form.errors.full_messages, status: :unprocessable_entity } end end
これでコントローラー側から適切なjsonを返せるようになりました。
RemoteFormのバリデーションを設定する
saveの成功と失敗をテストしたいので、バリデーションを加えます。
一番簡単なバリデーションの未入力を禁止するものを設定します。
先ほど作成したscaffoldではtitleとdescriptionがありましたが、
手っ取り早くtitileカラムにのみそれを適応させます。
app/models/remote_form.rbを開きます。
以下の内容を加えます。
validates :title, presence: true
保存しましょう、これで、フォームからtitle未入力で値が送られてきた時はエラーを返します。
javascriptを記述して値を受け取る
最後に、javascriptを記述してフォームを送信して返ってきたjsonをうけとります。
coffeescriptで記述します。
app/assets/javascripts/remote_forms.js.coffeeを開きます。
$(document).on 'ready page:load', -> $(document).bind "ajaxSuccess", "form.remote_form", (event, xhr, settings) -> console.log xhr.responseJSON console.log xhr.responseJSON.title $(document).bind "ajaxError", "form.remote_form", (event, jqxhr, settings, exception) -> $.each jqxhr.responseJSON, (index, message) -> console.log message
説明しますと、送信が失敗したか成功したかで大きく分けます。
サーバから返ってきたjsonの値は成功したらxhr、失敗したらjqxhrに格納されています。
jsonは.resposeJSONで取得できます。
正直、これ微妙にjsonじゃない気がするけど。
上コードのconsole.logの部分はデバッグ用に表示する為に書いています。
これで値をjsonを受け取れる様になりました。
動かして確認する
それではデモとして動かしてみましょう。
サーバを起動して
bundle exec rails s
アクセスして、
http://localhost:3000/remote_forms/
適当なデータをアップデータします。
インスペクタを表示して、値を見てみます。
まずはエラーが取得出来るか試してみます。
titleを空にして送ってみます。
インスペクタにerrorが出てrails側が用意したエラーが表示されています。
「Title can’t be blank」というのがそれですね。
正しい値を送ってみます。
タイトルに値をいれて送ってみます。
最初の結果にはjsonの中身が表示されています。
次にjsonのtitleの中身が表示されています。
いい感じですね。
まとめ
私が参考にしたサイトにはもう少し、改良されたエラー表示やデータが保存された時の表示などがありましたが、最低限上のように記述しておけば簡単なコードで動くのでぜひやってみてください。